Set DPI value to Tiff Image in C#

China☆狼群 提交于 2019-12-12 19:40:35

问题


I'm trying to set dpi value of a TIFF Image in C# through code but somehow the values are not persisted after saving the Image.

using (var image = new Bitmap(@"c:\newimage.tif"))
{
    uint[] uintArray = { 300, 1}; //Setting DPI as 300
    byte[] bothArray = ConvertUintArrayToByteArray(uintArray);
    PropertyItem item = image.PropertyItems.Where(p => p.Id == 0x11A).Single();
    var val = BitConverter.ToUInt32(item.Value, 0);
    Console.WriteLine(val);
    item.Id = 0x11A;
    item.Value = bothArray;
    item.Type = 5;
    item.Len = item.Value.Length;
    image.SetPropertyItem(item);
    image.Save(@"c:\newimage1.tif"); //Save image to new File
}

What is wrong with this code? Any kind of help would be appreciated. TIFF file tag definitions


回答1:


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
}



回答2:


I suspect that the Bitmap resolution will override the property. Use Bitmap.SetResolution().




回答3:


disclaimer: I work for Atalasoft, which makes products for working with images through .NET.

You can do this is dotImage using the TiffDocument class with code like this:

private void RemoveIfContains(TiffTagCollection tags, int tagID)
{
    TiffTag tag = tags.LookupTag(tagID);
    if (tag != null)
       tags.Remove(tag);
}

public void SetTiffResolution(string tiffin, string tiffout, int page, double resolution ) {
    if (tiffin == tiffout)
       throw new ArgumentException(tiffout, "output path must be different from input path");
    TiffFile tf = new TiffFile();
    using (FileStream stm = new FileStream(tiffin, FileMode.Open, FileAccess.Read, FileShare.Read)) {
        tf.Read(stm);
        TiffDirectory image = tf.Images[page];
        RemoveIfContains(image.Tags, TiffTagID.ResolutionX);
        RemoveIfContains(image.Tags, TiffTagID.ResolutionY);
        RemoveIfContains(image.Tags, TiffTagID.ResolutionUnit);
        image.Tags.Add(new TiffTag(TiffTagID.ResolutionX, resolution);
        image.Tags.Add(new TiffTag(TiffTagID.ResolutionY, resolution);
        image.Tags.Add(new TiffTag(TiffTagID.ResolutionUnit, 2)); // 2 == dots per INCH
        tf.Save(tiffout);
    }
}           

The advantages are several - direct access to the tags lets you set things the way you want without re-encoding the image. If your initial image was compressed with JPEG inside the TIFF, you don't have to worry about issues with re-encoding JPEG data and losing information. Further, you don't have to worry about losing TIFF tag information that was already there. This code also works on multipage TIFFs. Finally, this is probably going to be a faster approach than decoding the entire image just to change a tag.

The disadvantage to this approach is that you really, really, need to understand the TIFF spec. Without that understanding, you risk creating files that may not always be parseable. DotImage and IrfanView, for example, are very lenient in consuming all manner of broken TIFFs. Adobe PhotoShop is notoriously strict.



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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!