Fabric.js - Applying pixelate filter to resized image - fabricjs

Currently, the way Fabric.js works as far as I can tell is that its filters are applied to the original image, regardless of what it looks like on the canvas. Is there a way, by either "branching" the pixelate filter or through some other method, to have the filter be applied to the image as shown on the canvas, resized and oriented? How would I do this?
An example: I have an image within the canvas that can be resized. The user resizes it. I want to apply a filter to the resized version of that image, not the original uploaded image.
Thank you!

Okay, I think I see what you're trying to do. Assuming you're using the pixelate filter and want to get a consistent blocksize regardless of how big the image is on the canvas, you could simply set the filter's block size value as a function of the image's scale. By putting the blocksize calculation in an object:modified event it will recalculate each time an image is modified.
canvas.on('object:modified', function(e) {
var obj = e.target;
if(obj.type == "image") {
var blocksize = 16 / obj.scaleX;
obj.filters[0].blocksize = blocksize;
obj.applyFilters();
}
});

Related

Photoshop Script Resize Image, does not update the resolution

I have an image when manually resized to width 1000pts the resolution comes to 261.5pixels/inch
Original Image Dimensions
Manual Update width to 1000pts
The resolution downgraded to 261.5 px/in
When i try the same programmatically with js script the width changes but resolution is same as of the original image
JS Code
document.resizeImage(UnitValue(parseInt(row.width),"pt"), null, null); //working
where row.width = 1000
Image dimensions after executing the js script
How to calculate the resolution of the image automatically and set to 261.5px/inch
The new resolution should be manually calculated.
newResolution = document.resolution * (originalWidth / parseInt(row.width));
document.resizeImage(null, null, newResolution, ResampleMethod.NONE);
document.resizeImage(UnitValue(parseInt(row.width), "pt"), null, null);
If the width is changed, the height will be changed programatically, which caused an impression, ResampleMethod.NONE will set the resolution too.
Not sure if you want to shrink the image or the canvas. I've got with the former.
Use app.activeDocument.resizeImage with a width, height and resolution of your image.
resizemeth = ResampleMethod.BICUBIC;
res = 72;
w = 1000;
h = 673;
app.activeDocument.resizeImage(w, h, res, resizemeth);
Also check what units you are using.
alert(app.preferences.rulerUnits);

Using rotate for images leads to blank pdf with pdfkit

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.

Why isn't this mask working in Phaser?

I must be missing something...why isn't this working? Instead of clipping to the circle the entire 800x800 backdrop image is displayed...
var mask;
var img;
function preload() {
game.load.image('back', 'backdrop.jpg');
}
function create() {
img = game.add.image(game.world.centerX, game.world.centerY,'back').anchor.setTo(0.5);
mask = game.add.graphics(0, 0);
mask.beginFill(0xffffff);
mask.drawCircle(game.world.centerX, game.world.centerY, 600);
img.mask = mask;
}
jsfiddle here
Disclaimer: I have no formal experience in phaser.io
I was able to fix this in your fiddle by changing
img = game.add.image(game.world.centerX, game.world.centerY,'back').anchor.setTo(0.5);
to
img = game.add.image(0, 0, 'back');
JSFiddle Fork
I would assume that placing the image in the centerX,centerY position results in the mask being offset of the image. Hopefully someone with more experience than I could explain the specifics here, but I will research further and update my answer as I figure out the why to go along with the how.
Update
Okay so I've done some digging through the documentation. First, you want to use img = game.add.image(0, 0, 'back'); due to the fact that the x and y parameters in this case dictate the upper-left origin of the image, not the center. By using game.world.centerX and game.world.centerY you are trying to throw the background image to the center of the canvas even though the canvas is the same size as the image.
using .anchor.setTo(0.5) from what I can gather, is attempting to set the anchor point at which the image originates to the centerX position. However, when you remove this anchor, suddenly the mask works, even though it is not showing correctly (because the position of the background image is incorrect).
Theory - By anchoring the image, I believe that it is no longer possible to apply a mask to it. By all experimenting that I've done, having an anchor set on the background image prevents it from being masked, so the mask simply is added as a child to img and is placed as it's center, thus why you are seeing the white circle instead of the circle properly masking the image.
it appears I was a mistaken about the fluidity of the api in trying to chain that last function call... if I break it up:
img = game.add.image(game.world.centerX, game.world.centerY, 'back');
img.anchor.setTo(0.5);
it now works!
Fiddle Here

How to control the loading order of multiple images in openseadragon

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

Extendscript: How to check whether text content overflows the containing rectangle

I am using Extendscript for Photoshop CS5 to change the text of a text layer. Is there a way of checking whether the text fits e.g. by checking whether it overflows after changing the content?
I created a solution that works perfectly fine :). Maybe someone else can use it as well. Let me know if it works for you too!
function scaleTextToFitBox(textLayer) {
var fitInsideBoxDimensions = getLayerDimensions(textLayer);
while(fitInsideBoxDimensions.height < getRealTextLayerDimensions(textLayer).height) {
var fontSize = parseInt(textLayer.textItem.size);
textLayer.textItem.size = new UnitValue(fontSize * 0.95, "px");
}
}
function getRealTextLayerDimensions(textLayer) {
var textLayerCopy = textLayer.duplicate(activeDocument, ElementPlacement.INSIDE);
textLayerCopy.textItem.height = activeDocument.height;
textLayerCopy.rasterize(RasterizeType.TEXTCONTENTS);
var dimensions = getLayerDimensions(textLayerCopy);
textLayerCopy.remove();
return dimensions;
}
function getLayerDimensions(layer) {
return {
width: layer.bounds[2] - layer.bounds[0],
height: layer.bounds[3] - layer.bounds[1]
};
}
How to use / Explanation
Create a text layer that has a defined width and height.
You can change the text layers contents and then call scaleTextToFitBox(textLayer);
The function will change the text/font size until the text fits inside the box (so that no text is invisible)!
The script decreases the font size by 5% (* 0.95) each step until the texts fits inside the box. You can change the multiplier to achieve a more precise result or to increase performance.
I haven't found a way to do this directly. But I've used the following technique to determine the height I needed for a textbox (I wanted to keep the width constant) before.
expand the textbox's height well beyond what is needed to accommodate the text inside it.
duplicate the layer
rasterize the duplicate
measure the bounds of the rasterized layer.
adjust the bounds of the original text layer as needed
delete the rasterized duplicate
Totally roundabout - but it did work.

Resources