I have a Chrome extension, where I'm using the captureVisibleTab method of the chrome.tabs API to capture screenshots. I have tested the extension on 3 devices (Chromebooks) and I'm getting mixed results. Two of them work perfectly, but one always returns a completely malformed screenshot.
My code:
chrome.tabs.onUpdated.addListener(function(tabId,changeInfo,tab){
chrome.tabs.get(tabId, function (_tab) {
if (_tab.status == "complete" && _tab.active ) {
chrome.tabs.captureVisibleTab( function(dataUrl){
});
}
});
});
Any ideas what could be the issue on that one device?
EDIT
Example of a bad screenshot:
I suspect that the device pixel ratio is higher on your 3rd device. This was an issue I was having with Retina displays when building a screenshot app. Basically, certain high-resolution displays have a higher ratio pixels per square inch. You're going to want to find window.devicePixelRatio and divide the context scale by that amount.
Assuming that you are using Canvas to draw the screenshot and capture it into an image, this little snippet should help show what you're going to want to do:
var canvas = document.createElement("canvas");
canvas.width = image.width;
canvas.height = image.height;
var context = canvas.getContext("2d");
if(window.devicePixelRatio > 1){
context.scale(1/window.devicePixelRatio, 1/window.devicePixelRatio);
}
context.drawImage(image, 0, 0);
Let me know if that works for you.
Related
GOAL
I am trying to build a signature pad in SVG. You can view
Sample project here.
Description
So far, it works in Chrome, Edge and Opera as desired but, in Firefox, getScreenCTM() doesn't account for the scale.
Research
I went through a bunch of documentation from bugzilla and a couple of posts here in SO such as SVG: GetScreenCTM() for nested SVG is different in Firefox but, still couldn't figure out how to fix my issue.
Problem
I've added a browse check to handle only Firefox (since all other browsers provides the desired result) which allows me to add extra code to fix the problem but, thus far, had no success. (SPSignature:416)
Reproduce the error
To reproduce the error, open the sample link in FireFox than, resize the box so it is at least 20% smaller as in fullscreen. You will see the mouseX/Y position change as scale changes.
I've tried to get the matrix transform from the group tag but, it returns similar result from the SVG. How do I calculate the CTM, so its result is similar/equal to Chrome?
Code
Source code here SPSignature:416
_getCursorPoint(event)
{
const svg = document.querySelector('.spsignature svg');
let pt = svg.createSVGPoint();
pt.x = event.clientX;
pt.y = event.clientY;
// firefox workaround:
if (this._checkBrowser() === 'Firefox') {
const matrix = this._decomposeMatrix(svg.getScreenCTM());
let cood = {
x: event.layerX,
y: event.layerY
};
if (matrix.scaleX < 0.9 || matrix.scaleY < 0.9) {
console.log('%c #todo: fix mouse position for FF on getScreenCTM().', 'background:#c00;color:#fff;padding:3px;');
}
return cood;
}
return pt.matrixTransform(svg.getScreenCTM().inverse());
}
To "fix" the mouse XY problem on FF, I've used the root scale value to allow for the calculation of the cursor XY position.
The scale can be retrieved from the matrix based on https://gist.github.com/2052247.
Also, in FF, I've used the event.layerX and event.layerY instead of event.clientX and event.clientY for the initial mouse coordinate values.
So, instead of using matrixTransform(svg.getScreenCTM().inverse()) to return the calculated XY relative to the SVG, I've used the scale and layerXY to calculate the right XY position.
I have asked the question on the repository directly, but in my experience SO is more reactive.
Hey there,
I am trying to create a pdf from photos using pdfkit.
Depending on whether an image is in landscape or portait mode, I want to turn the image around.
This basically means the following (in typescript) :
function toPostscriptPoint(mm: number) {
return mm * 2.8346456693;
}
const document = new PDFDocument({
size: [toPostscriptPoint(156), toPostscriptPoint(106)],
});
document.pipe(fs.createWriteStream('output.pdf'));
document.save();
document.rotate(90);
document.image(
'photos/sample.jpeg',
{ width: toPostscriptPoint(150), fit: [toPostscriptPoint(150), toPostscriptPoint(100)] });
document.restore();
document.end();
What happens though is that the pdf renders completely white. I do see however that something is happening, because the pdf has the size of the input image.
Is rotation for images not supported? What would be possible alternatives? I would like to avoid having to rewrite my files before putting them in the pdf.
Thanks
Alright, after investigation, I can answer my own question :).
I could see that the images were in the pdf somehow because of the size of the file so I dived deeper.
What happened was that the image was rendered out of the viewport. This was due to multiple things:
By default, the origin of a page after rotation in pdfkit is the center of the page! ( See the doc for more info)
The origin is rotated together with the transformation.
The x and y in the image method are actually inverted.
So after getting all this right, the following code shows the image as expected :
function toPostscriptPoint(mm: number) {
return mm * 2.8346456693;
}
const document = new PDFDocument({
size: [toPostscriptPoint(156), toPostscriptPoint(106)],
});
document.pipe(fs.createWriteStream('output.pdf'));
document.save();
document.rotate(90, {origin : [0, 0]});
document.image(
'photos/sample.jpeg',
toPostscriptPoint(0),
toPostscriptPoint(-150),
{ width: toPostscriptPoint(150), height: toPostscriptPoint(100) });
document.restore();
document.end();
Note the :
origin argument in the rotation
toPostscriptPoint(-150) actually takes into account the position of the origin, and corresponds to the X axis.
Hope that helps some later on :).
Its because taking picture from camera , if picture ISO is less than 100 it will be automatically rotated , take picture with iso more than or equal to 100 to avoid autorotation.
I've 3 (loader, locker and debug view) hidden views (touchEnabled and visible set to false, and zIndex to 1) above the main view (zIndex = 2).
Each 'over' view has this method:
$.debugView.show = function() {
$.debugView.touchEnabled = $.debugView.visible = true;
$.debugView.zIndex = 3;
};
$.debugView.hide = function() {
$.debugView.touchEnabled = $.debugView.visible = false;
$.debugView.zIndex = 1;
};
This screen has the 3 'over' views hidden:
Now, I'm opening the 'debug view', but, SOMETIMES it seems like it changes the positions (as if the center it's on the top left corner instead of the center of the device).
Instead of the required result:
If I use the opacity instead of the visible property, it works properly.
This might be an SDK bug right?
<Alloy>
<Window>
<View id="content"/>
<View id="locker"/>
<View id="loader"/>
<View id="debugView"/>
</Window>
</Alloy>
All of these 4 views don't have width or height (so it uses the Ti.UI.FILL as default)
I have noticed this too with a completely different implementation. I had just one view that I included in a window.
Apparently the left and top calculations were not done properly if the elements is hidden.
What I did to solve the issue is to hardcode the left/top position by calculating the left position using this:
$.content.left = (Ti.Platform.displayCaps.platformWidth - 75) / 2;
Where in my case 75 is the width the element has, so that'll be bigger in your case. You can do the same for height.
Now, this is an iOS only solution. On Android you will need to take DPI into consideration calculating it.
I do think it is a bug, though this solution works perfectly for me. I recommend looking at JIRA and see if it is a known issue, and if not, raise it with a very specific explanation of the problem, preferably with a reproducible case delivered as an app. Classic would help most. And if it is not reproducible in classic it might be an alloy issue.
In my situation, I have 10 images loaded in a viewer with the same bounds. each image is arranged one behind other.
// source is an array of url images.
for(i=0;i < source.length-1;i++){
this.viewer.addTiledImage({
tileSource: source[i],
index: i,
opacity:0
});
}
My intention is to control opacity of each image using a slider (range input), the slider set the correspondent image opacity to 1, and let the others with no opacity. This works well.
The idea is preload images and change images smoothly.
The problem
All images are loaded at same time when zooming or panning, so I want to control the load order and give priority to the visible image then load the next image, and so on.
How can I do that? I can't find any method to pause the loading of tiles.
Thanks for your help.
You can try using the 'open' event and adding the next image once the previous one has loaded. Something like:
var i =0, viewer = this.viewer;
viewer.addTiledImage({
tileSource: source[i],
index: i,
opacity:0
});
viewer.addHandler('open', function() {
i++;
if (source[i]) {
viewer.addTiledImage({
tileSource: source[i],
index: i,
opacity:0
});
} else {
viewer.removeAllHandlers('open');
}
});
Note that this is untested sample code but you should get the idea. And you should actually use removeHandler() instead of removeAllHandlers(), but this is just an example.
I can fix my issue by controlling opacity instead of control network download, openseadragon has no method to control the download order at dzi image level, so the way is control the opacity because 0 opacity don't do any download. Thanks to the openseadragon contributors for help me to solve this issue.
https://github.com/openseadragon/openseadragon/issues/971
I am trying to put in an icon (a scaled image) as part of a button that also contains some text. I am programming in J2ME for the Nokia SDK (S60 device) and using Eclipse.
The code is as follows:
but = new Button("Some text");
Image img = null;
try {
img = Image.createImage("/flower.png");
} catch(IOException e) {
e1.printStackTrace();
}
but.setIcon(img);
The above lines are the code that works properly. I am facing problems in scaling the image to the size of the button. Whenever I try to do that, I get a divide by zero error. The function I am using to scale the image and the way it is being scaled is:
Image img2 = null;
img2 = img.scaled(but.getWidth()/2, but.getHeight());
but.setIcon(img2);
I am unable to figure out why I get a divide by zero error every time I try to run the above code. Is there some other function that I should use? Or is there something I am missing ?
which UI Framework are using, is it LWUIT? if yes, you can't get the width/height of any component before showing the form, you should use getPreferredWidth instead