Closed imanbell closed 11 months ago
The automatic thumbnail is generated from the composite image of the drawing, it's always small and compressed with JPEG compression so it's not an issue, what is taking the space is the composite image that you're setting. Instead of setting composite image and relying on automatic thumbnail generation you can just set the thumbnail yourself in psd.thumbnail
and NOT set the composite image. Here's how the thumbnail is generated internally:
function createThumbnail(psd: Psd) {
const canvas = createCanvas(10, 10);
let scale = 1;
if (psd.width > psd.height) {
canvas.width = 160;
canvas.height = Math.floor(psd.height * (canvas.width / psd.width));
scale = canvas.width / psd.width;
} else {
canvas.height = 160;
canvas.width = Math.floor(psd.width * (canvas.height / psd.height));
scale = canvas.height / psd.height;
}
const context = canvas.getContext('2d')!;
context.scale(scale, scale);
if (psd.imageData) {
const temp = createCanvas(psd.imageData.width, psd.imageData.height);
temp.getContext('2d')!.putImageData(psd.imageData, 0, 0);
context.drawImage(temp, 0, 0);
} else if (psd.canvas) {
context.drawImage(psd.canvas, 0, 0);
}
return canvas;
}
Hi, thank you for your quick reply!
Unfortunately I didn't manage to make it work. I've tried setting the psd.thumbnail property as well as psd.imageResources.thumbnail, tried the raw versions as well, while setting generateThumbnail to false and of course not setting the composite image. When I follow the code execution it looks like it should work, but in the end the thumbnail is always black. Do you maybe have a small sample code of this working to generate a basic PSD with a thumbnail? Maybe I'm doing something wrong...
Note: I'm trying to make this work in nodeJS, but I tried it on browser too and it didn't work for me
My mistake it was psd.imageResources.thumbnail
. Can you show me your code?
Here is a simple nodeJS example (in the folder run 'npm i' and then 'node index.js'). It's supposed to generate a PSD with 3 layers, and set a pink thumbnail. The PSD is generated correctly, but the thumbnail is black. Thanks for looking into this!
You're generating pink PNG image when writing it to a buffer and then using these bytes as pixels, that is not going to work.
Try something like this
const canvas = createCanvas(160, 160);
const ctx = canvas.getContext("2d")!;
ctx.fillStyle = 'pink';
ctx.fillRect(0, 0, 160, 160);
return canvas;
If you want to use thumbnailRaw
is just raw pixels so no need to use any libraries, you just use Uint8Array of pixel data, you can just fill it yourself with bytes corresponding to pink pixels.
If you set both thumbnailRaw
and thumbnail
the thumbnailRaw
will be used and thumbnail
will be ignored.
No, my getImageData function should return the width, height and the pixel data (if I'm correct on how the pngjs library works).
But in any case, I just tried the method you shared about creating the canvas directly and setting it on the thumbnail field (and putting nothing in thumbnailRaw) and the thumbnail is still black... has it worked for you?
Note: the colors I'm using to create the layers and the thumbnail are just examples, to create a simple scenario that reproduces my issue.
How are you checking the thumbnail ?
I upload the file to my Google Drive, which supports PSD thumbnail previewing.
I wrote this test:
const canvas = createCanvas(300, 200);
const context = canvas.getContext('2d')!;
context.fillStyle = 'pink';
context.fillRect(0, 0, canvas.width, canvas.height);
const canvas2 = createCanvas(300, 200);
const context2 = canvas2.getContext('2d')!;
context2.fillStyle = 'orange';
context2.fillRect(0, 0, canvas.width, canvas.height);
const psd: Psd = {
width: 300,
height: 200,
canvas: canvas,
children: [
{
name: 'bg',
canvas: canvas,
},
],
imageResources: {
thumbnail: canvas2,
},
};
const buffer = writePsdBuffer(psd, { generateThumbnail: false });
fs.writeFileSync(path.join(resultsFilesPath, `thumb_test.psd`), buffer);
and got pink thumbnail in google drive, so it seems google drive ignores the thumbnail and just displays composite image, so you're probably stuck with having to generate big file if you want it to show up properly in google drive.
The layer and composite images are compressed using RLE encoding so if you're using images with a lot of noise (like photos) then it will be large.
Oh okay I think you're right. I actually tried the files on MacOS Finder, and the small thumbnail works for the file icon. However for the file preview, indeed it seems that the composite image is necessary. And as you said Google Drive probably needs the composite image too. It looks like I'll probably need to generate the composite image for my use case. Thanks a lot for your help!
Hi!
I'm trying to generate a thumbnail when writing my PSD file. For this it seems that I have to use the imageData field in the PSD parameters to set my thumbnail image. The image in imageData must have the same dimensions as the PSD document (i.e. potentially quite big). When I tried it, I get my thumbnail, but the PSD file size becomes much bigger compared to a PSD without a custom thumbnail (for example, it goes from 7.8 MB to 20.5 MB for a 5000x5000 PSD with 2 layers). Is there a way to only generate/set a small thumbnail without using this imageData field, in order to avoid the file size increase? Am I misunderstanding its purpose?
Thanks!