brendan-duncan / image

Dart Image Library for opening, manipulating, and saving various different image file formats.
MIT License
1.18k stars 268 forks source link

TiffEncoder encodeImage always return 96 dpi, how to increase/decrease it #394

Open murat-ti opened 2 years ago

murat-ti commented 2 years ago

Great job. As result I need to receive tiff image with 200 dpi. How can I do it? Thanks

brendan-duncan commented 2 years ago

Thanks. The Tiff encoder currently isn't writing a resolution tag, so it gets the default DPI. I'd have to add that to my list of things to do...or accept a pull request :-).

murat-ti commented 2 years ago

I know how to change dpi in photoshop. But I can't imagine how to do it programatically) I see you have experience with image encoding/decoding. How much time it can take to set dpi? Or maybe you can show me the way, where I can continue my researches. Thanks.

brendan-duncan commented 2 years ago

Tiff format has a tag in it that specifies the DPI. It doesn't change the pixel resolution of the image, it just says how many of those pixels should be packed into an inch of physical space, whether printed or when displayed in physical units. Changing the DPI of a Tiff image would be setting the value of that tag. The TiffEncoder currently doesn't write out that tag.

murat-ti commented 2 years ago

I found solution for C#, can you check if am I on right way:

https://stackoverflow.com/questions/3084725/set-dpi-value-to-tiff-image-in-c-sharp

Setting both the property value and the bitmap resolution and then resaving the image should change the resolution (It worked on my sample image). I believe the original file has to have the tags for X and Y resolution present, not sure if .NET will add those tags if not present (would have to test).

Here's an example of reading and writing the X and Y resolution a TIFF image using .NET:

int numerator, denominator;

using (Bitmap bmp = (Bitmap)Bitmap.FromFile(@"C:\input.tif")) { // obtain the XResolution and YResolution TIFFTAG values PropertyItem piXRes = bmp.GetPropertyItem(282); PropertyItem piYRes = bmp.GetPropertyItem(283);

// values are stored as a rational number - numerator/denominator pair numerator = BitConverter.ToInt32(piXRes.Value, 0); denominator = BitConverter.ToInt32(piXRes.Value, 4); float xRes = numerator / denominator;

numerator = BitConverter.ToInt32(piYRes.Value, 0);
denominator = BitConverter.ToInt32(piYRes.Value, 4);
float yRes = numerator / denominator;

// now set the values
byte[] numeratorBytes = new byte[4];
byte[] denominatorBytes = new byte[4];

numeratorBytes = BitConverter.GetBytes(600); // specify resolution in numerator
denominatorBytes = BitConverter.GetBytes(1);

Array.Copy(numeratorBytes, 0, piXRes.Value, 0, 4); // set the XResolution value
Array.Copy(denominatorBytes, 0, piXRes.Value, 4, 4);

Array.Copy(numeratorBytes, 0, piYRes.Value, 0, 4); // set the YResolution value
Array.Copy(denominatorBytes, 0, piYRes.Value, 4, 4);

bmp.SetPropertyItem(piXRes); // finally set the image property resolution
bmp.SetPropertyItem(piYRes);

bmp.SetResolution(600, 600); // now set the bitmap resolution

bmp.Save(@"C:\output.tif"); // save the image

}

Thanks

brendan-duncan commented 2 years ago

I don't know if .NET would add the tags if missing from the image, defaulting to the 96DPI. I would guess not. Does SetResolution rescale according to the X_RESOLUTION property, which you had already set to 600 (and therefore not rescale the image); or does it resize to the DPI that it had parsed from the tags in the FromFile loader. I'm guessing the later. It's also not necessary to calculate xRes and yRes, given the old DPI isn't being used.

In any case, this would work, minus handing the missing properties if they are not present in the image.

brendan-duncan commented 2 years ago

Also it's not clear if you would want to rescale the image. If you had an image that is 300x300 pixels, but it had the default 96DPI, then it would be interpreted as being 3.125 inches square. But if you had intended it to be 300 DPI and 1", you'd want to set the DPI properties but not rescale the image by 3.125. So resizing the image would want to be a separate operation from setting the DPI of the image.

brendan-duncan commented 2 years ago

In any case, I don't have a lot of time these days, so unfortunately it might be a while before I'd be able to extend the TiffEncoder to add DPI support.

murat-ti commented 2 years ago

I will continue my researches.Thank you for your quick responses and your time. I got you.

murat-ti commented 2 years ago

Hi Brendan,

As example, I have converted jpg to tiff. Input jpg images has all needed tags.

After learnings your code, I found how to write manually tags to output image (x resolution, y resolution and resolution unit in my case). Later, I have started to look for how input image reads different tags data and can't understand how it works. May be you can show how to read by their codes (resolution unit =296, x resolution = 282, y resolution = 283 and etc)? Then I can put them in output image. Thanks.