简体   繁体   English

在C#中将DPI值设置为Tiff图像

[英]Set DPI value to Tiff Image in C#

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. 我正在尝试通过代码在C#中设置TIFF图像的dpi值,但是在保存图像后以某种方式无法保留这些值。

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 TIFF文件标签定义

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). 我相信原始文件必须具有用于X和Y分辨率的标签,不确定如果.NET不存在,.NET是否将添加这些标签(必须进行测试)。

Here's an example of reading and writing the X and Y resolution a TIFF image using .NET: 这是使用.NET读取和写入TIFF图像的X和Y分辨率的示例:

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
}

I suspect that the Bitmap resolution will override the property. 我怀疑位图分辨率将覆盖该属性。 Use Bitmap.SetResolution(). 使用Bitmap.SetResolution()。

disclaimer: I work for Atalasoft , which makes products for working with images through .NET. 免责声明:我为Atalasoft工作,该公司生产用于通过.NET处理图像的产品。

You can do this is dotImage using the TiffDocument class with code like this: 您可以使用TiffDocument类和以下代码通过dotImage做到这一点:

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. 如果您的原始图像是在TIFF中用JPEG压缩的,则不必担心重新编码JPEG数据和丢失信息的问题。 Further, you don't have to worry about losing TIFF tag information that was already there. 此外,您不必担心丢失已经存在的TIFF标签信息。 This code also works on multipage TIFFs. 此代码也适用于多页TIFF。 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. 这种方法的缺点是您确实需要了解TIFF规范。 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. 例如,DotImage和IrfanView在使用各种损坏的TIFF时非常宽容。 Adobe PhotoShop is notoriously strict. 众所周知,Adobe PhotoShop非常严格。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM