Closed amitguptagwl closed 6 years ago
hello I would like to try and tackle this issue if that's okay.
@dragonhangnail Have you get the chance to look into?
yes, I am sorry this is taking so long this is my first time working on something like this.
Not an issue. I just wanted to check if you need some help.
@dragonhangnail I've hided the zoom button from toolbar until implemented. So that users will not try it.
Apart from the UI, is the zoom capability supposed to work? I tried using the shortcut Alt-M but the image scale remains unchanged.
@rclim-11 zoom functionality is not implemented yet. the purpose of Alt+M
is to select move tool or rather deselect any drawing tool.
Hi @amitguptagwl , please refer below screenshot. Is this how you want it to look like?
<action-zoom>
<style>
.zoom-button{
display: inline-block;
padding: .3em;
cursor: pointer;
}
.zoom-icon{
}
.zoom-selected{
background: coral;
}
.zoom-button:not(.zoom-selected):hover{
background: grey;
}
</style>
<div>
<div class="zoom-button" onclick={ zoomme }>
<img src="img/icons/zoomin.svg" class="zoom-icon" >
</div>
<div class="zoom-button" onclick={ zoomme }>
<img src="img/icons/zoomout.svg" class="zoom-icon" >
</div>
</div>
<script>
var tag = this;
tag.zoomme = function (e){
//TODO: should it unseect all the tools or tools in current toolbox
$(".zoom-selected").removeClass("zoom-selected");
}
</script>
</action-zoom>
I wrote up the zoom-action.tag.html that you commented out in index.html. Of course, there's no logic to process the image yet, that will take me a while longer. But please let me know if I am going the right direction. Thank you.
Yes. your understanding is correct. And I love the way you confirm.
I may not be available for any discussion, fix, or new changes for next 1 week. Though I'll try my best.
Hi @amitguptagwl I've finished the zoom function. Screencast below may take a while to load...
Each image actually stores it's own instance of scale and scaled sizes.
I've changed 4 files in total: images-slider.tag.html, workarea.tag.html, trackinglines.tag.html & zoom-action.tag.html (newly added)
First, I realized that it is better that each 'imgSelected' actually stores it's own scaled sizes, so I added 3 new variables to size object in images-slider.tag.html
function updateDimentions(imgFileSrc, imageDataObject) {
var img = new Image();
img.onload = function() {
imageDataObject.size = {
width : this.width,
height : this.height,
scaledWidth: this.width, //here
scaledHeight: this.height, //here
imageScale: 1 //here
}
addImgToStore(imageDataObject.name, imageDataObject.size);
}
img.src = imgFileSrc;
}
Zoom action in zoom-action.tag.html is straight forward. Users can zoom in as much as they want but they cannot zoom out less than 10%. Every time after zoom is pressed, the workarea is re-mounted.
var tag = this;
tag.zoomin = function (e){
imgSelected.size.imageScale += 0.1;
rescaleImage();
}
tag.zoomout = function (e){
if(imgSelected.size.imageScale<0.2)return;
imgSelected.size.imageScale -= 0.1;
rescaleImage();
}
function rescaleImage(){
imgSelected.size.scaledWidth = Math.floor(imgSelected.size.width * imgSelected.size.imageScale);
imgSelected.size.scaledHeight = Math.floor(imgSelected.size.height * imgSelected.size.imageScale);
riot.mount("workarea",{ img : imgSelected });
}
In workarea.tag.html. The img and work-canvas will be updated according to the image's scaled size instead. Updating trackinglines is the tricky part.
...
this.on('mount', function () {
$("#canvas-container img").css("opacity", appConfig.imageOpacity || 1);
$("#canvas-container img").css({"width": opts.img.size.scaledWidth, "height": opts.img.size.scaledHeight});
$("#work-canvas").attr({"width": opts.img.size.scaledWidth, "height": opts.img.size.scaledHeight});
myCanvas = new SVG('work-canvas').size(opts.img.size.scaledWidth, opts.img.size.scaledHeight);
...
To update the h_line and v_line of trackinglines, I amended the trackinglines.tag.html, such that instead of taking opts.width/opts.height everytime this tag is mounted, I take the scaled sizes from imgSelected instead. opts values cannot be changed once tag is mounted
$(tag.refs["h_line"]).width(imgSelected.size.scaledWidth > canvasContainer.width() ? imgSelected.size.scaledWidth : canvasContainer.width() );
$(tag.refs["v_line"]).height(imgSelected.size.scaledHeight > canvasContainer.height() ? imgSelected.size.scaledHeight : canvasContainer.height() );
In workarea.tag.html, I removed the opts arguments for trackinglines.
<div id="canvas-container">
<img id="img" src={ opts.img.src } width="{ opts.img.size.width }" height="{ opts.img.size.height }" />
<div id="work-canvas" width="{ opts.img.size.width }" height="{ opts.img.size.height }"></div>
<trackinglines></trackinglines>
</div>
Let me know if this is acceptable. If yes, I will create the PR. Thanks. =)
*PS: Some ideas I thought about when developing this:
Sorry for the late response, in travel.
- Shall we have a 'reset' zoom button?
Yes! it was in plan. We can combine it with this PR. I also wanted to use a slider or text box in between of zoom in/out buttons. So users know the current zoom level.
- ... appConfig.imageOpacity ...
We kept it globally because of usability. User needs to reduce opacity so that label shapes are easily visible. If I'll be labeling images, I would like to set it only once. So we can skip this.
One question (before I go in detail), have you tried to label images while testing zoom option? How it is working?
Hi @amitguptagwl I didn't take into account the feature points for zooming & I also didn't take into account the saving of the image scale. So, the feature points won't 'zoom together' as of now. And also the zoom scale is not saved (i.e. when you close and open the application and select the same image again, the image starts off as original size)
I didn't take into account the feature points for zooming
The whole purpose of providing zoom feature to enable users to label small parts of an image. So the label shapes should also zoom with the same level. However feature points should not be zoomed.
As we're using svj.js for labeling, https://github.com/svgdotjs/svg.panzoom.js can be used for this implementation.
I also didn't take into account the saving of the image scale. So, the feature points won't 'zoom together' as of now. And also the zoom scale is not saved (i.e. when you close and open the application and select the same image again, the image starts off as original size)
It's fine. It is expected.
Hi @amitguptagwl
I have been playing around with svg.panzoom.js but this library doesn't seems to work well with the existing libraries. What I did was just included in the library and added in the panZoom call.
myCanvas = new SVG('work-canvas').size(opts.img.size.scaledWidth, opts.img.size.scaledHeight).panZoom({zoomMin: 0.1, zoomMax: 20});
I will take some more time to look at this library in detail.
I also wanted to use a slider or text box in between of zoom in/out buttons. So users know the current zoom level.
I have addressed this, by adding in the input box and reset button.
*P.S I grabbed the reset button from some website and its probably licensed. Maybe you can make a new one ;)
We're using common-fonts in our application. So we can use icon-cw probably to reset zoom level.
I've never tried panZoom library before. So probably there is some compatibility issue. We may try some other libraries:
Hi @amitguptagwl ! I swear I burned some brain cells for this.. Please have a look I have used https://github.com/ariutta/svg-pan-zoom library. My code structure (as compared to my post 10 days ago) is still pretty much the same for the image zoom in/out part, but for the shapes I have added two new keys in labellingData object:
store.js:
function attachShapeToImg(id, type, bbox, points){
labellingData[ imgSelected.name ].shapes.push( {
"id" : id,
"label" : "unlabelled",
....
"zoomScale" : 1,
"defaultZoomScale": 1/imgSelected.size.imageScale//this is in relation with the image
} );
EVERY shape that is either added before or after a zoom in/out needs to have their own zoomScale, like the imgSelected has imageScale, with an additional defaultZoomScale, because each shape is IN RELATION to the parent image, hence the imageScale default of 1 doesnt mean that the shape's default zoom is 1, i.e. the shape might be added when the image is already zoomed in to scale 2 etc.. if the shape is added when image is at zoom 2, then its defaultZoomScale is 0.5 when the user click the reset zoom button.
At the workarea.tag.html, I added an additional function. This makes use of the library, and this function is called at the end of drawOnCanvas() like so setZoomLevel(shape.zoomScale, currentShape);
function setZoomLevel(zoomScale, currentShape){
var panZoomCanvas = svgPanZoom("#"+currentShape.parent().id(),{
panEnabled: false,
zoomEnabled: true,
zoomScaleSensitivity: 0.1,
minZoom: 0.1,
maxZoom: 10,
fit:false,
center: false
});
panZoomCanvas.zoomAtPoint(zoomScale,{x:0, y:0});
}
A bit of refactoring of the tag.zoom function in zoom-action.tag.html:
tag.zoom = function (e){
if(!imgSelected) return;
var mulScale = 0;
switch (e.target.dataset.zoomType) {
case 'in':
if(imgSelected.size.imageScale>=10)return;
mulScale = 1;
break;
case 'out':
if(imgSelected.size.imageScale<=0.1)return;
mulScale = -1;
break;
case 'reset':
mulScale = 0;
break;
}
const preImgSelectedScale = imgSelected.size.imageScale;
imgSelected.size.imageScale = (mulScale===0) ? 1 : preImgSelectedScale+mulScale*appConfig.zoomStepSize;
const img = labellingData[imgSelected.name];
if(img){//if there are labels
img.shapes.forEach((shape)=>{
shape.zoomScale = (mulScale===0) ? shape.defaultZoomScale : shape.zoomScale*imgSelected.size.imageScale/preImgSelectedScale;
})
}
rescaleImage();
}
This line is the magic line, each shape should scale IN RELATION to the image.
shape.zoomScale = (mulScale===0) ? shape.defaultZoomScale : shape.zoomScale*imgSelected.size.imageScale/preImgSelectedScale;
I added the zoomStepSize as a config item in appConfig.
var appConfig = {
autosave : {
syncingInterval : 10 * 1000, //10 seconds
enable : true,
deleteIfExported: true, //Mark the data as saved when exported as nimn format, and delte the copy from browser cache.
},
featurePointSize: 3,
zoomStepSize: 0.1
};
Let me know if this is ok. There's quite a lot of code change. Thanks.
You have strong brain cells. :smile:
It seems perfectly fine to me.
@Alvin-Voo In case if you want to join this project as collaborator, please visit this
@amitguptagwl Alright, I have accepted the invitation. I have also created the PR, please review. Thank you!
@Alvin-Voo PR has been merged but the zom option can't seen.
@amitguptagwl let me have a look
Sorry @amitguptagwl I missed out the config.js. Let me create another PR.
@amitguptagwl Alright.. I see it ;)
Grt!!
I observed that zoom out button doesn't work when we directly click on that but works fin when we click on image or zoom out in first. (P3)
Moreover, is it possible to not to zoom feature point? If not I believe we can reset their radius. However this approach doesn't seem feasible as there can be multiple points and we'll have to reset radius of every point. Any other suggestion? (P2)
I observed that zoom out button doesn't work when we directly click on that but works fin when we click on image or zoom out in first.
Heh? You mean when we first load the image and click zoom out? It works fine.
Moreover, is it possible to not to zoom feature point? If not I believe we can reset their radius. However this approach doesn't seem feasible as there can be multiple points and we'll have to reset radius of every point. Any other suggestion?
Because now the matrix transforms everything within the svg, you can check this out in the dev console, the library basically applies a viewport and a transform for e.g. transform="matrix(0.699999988079071,0,0,0.699999988079071,0,0) to all the components including 'circle' which are the feature points, so this is how it works. And these 'circles'/feature points have to be scaled (transform) together as well, if not their position will be wrong. Their radius has always remained at 3 by default (or whatever the user input..) TL:DR the 'zoom' doesn't really change the actual size of the shapes, it merely transforms them.
Heh? You mean when we first load the image and click zoom out? It works fine.
Not sure why I was facing the problem in first attempt. However it seems working as expected now. So please ignore it.
Because now the matrix transforms everything within the svg ...
Agree. Please ignore it for the time being. I'll check later if some alternatives come in mind.
Starting point: https://naturalintelligence.github.io/imglab/v2.html
It is quite difficult to work on large images. Hence a feature is required to zoom in / out image with SVG.
What to do
There is a tool button (2nd last on toolbox) "Zoom In". It needs to be renamed to "Zoom" (config.js)
Add an actions tag.html file in
tags\actions
folder with necessary functionalityInclude new tag file in v2.html
Check technical documentation to know how to add an action bar.