.NET - Bitmap.Save忽略Bitmap.SetResolution在Windows 7 [英] .NET - Bitmap.Save ignores Bitmap.SetResolution on Windows 7

查看:659
本文介绍了.NET - Bitmap.Save忽略Bitmap.SetResolution在Windows 7的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在写一个.NET 4的应用程序,进口并保存图像进行打印。该保存的图像分辨率(DPI不能更改像素尺寸)来设定的值,我们指定,使他们正确打印是很重要的。

I'm writing a .NET 4 application that imports and saves images for printing. It's important that the saved images resolution (DPI not pixel dimensions) be set to the value we specify so they print correctly.

一些我们进口来没有分辨率的图像值(当生成他们不好EXIF),所以我们必须纠正写在他们面前。我们使用Bitmap.SetResolution了点。它工作正常在XP和Windows 8,但是当我们写(Bitmap.Save)在Windows 7上的图像,它们始终与原始分辨率元信息写入,忽略SetResolution。

Some of the images we import come without the resolution value (bad EXIF when they were generated), so we have to correct that before writing them. We use Bitmap.SetResolution for that. It works fine on XP and Windows 8, but when we write (Bitmap.Save) the images on Windows 7, they are always written with the original resolution meta info, ignoring SetResolution.

下面是我们做了一个测试,适用于XP和8,而不是7

Here's a test we made, works on XP and 8, not on 7.

string originalFile = @"D:\temp\img\original_img.jpg";
string newFile = @"D:\temp\img\new_img.jpg";

Bitmap bitmap = (Bitmap)Image.FromFile(originalFile);
bitmap.SetResolution(200, 200);
bitmap.Save(newFile, ImageFormat.Jpeg);

Image image = Image.FromFile(newFile);
int dpiX = (int)Math.Round(image.HorizontalResolution, MidpointRounding.ToEven);
int dpiY = (int)Math.Round(image.VerticalResolution, MidpointRounding.ToEven);
Console.WriteLine("DPI is {0} x {1}", dpiX, dpiY);



保存前,调试始终显示SetResolution分配正确的分辨率,所保存的图像是哪里出了问题

Before saving, debug always shows the correct resolution assigned by SetResolution, the saved image is where the problem is.

这可能就是被报道在这里:
http://social.msdn.microsoft.com/Forums / vstudio / EN-US / 62368caa-05f4-4798-9c59-5d82f881a97c / systemdrawingbitmapsetresolution-IS-完全破碎式窗口-7?论坛= netfxbcl

This is probably what was reported here: http://social.msdn.microsoft.com/Forums/vstudio/en-US/62368caa-05f4-4798-9c59-5d82f881a97c/systemdrawingbitmapsetresolution-is-completely-broken-on-windows-7?forum=netfxbcl

但问题似乎仍然没有得到解决。难道真的没有办法只是使它工作?我必须使用额外的库呢?

But the issue there seems to remain unsolved. Is there really no way to just make it work? Do I have to use extra libraries for this?

推荐答案

Hmya,这是一个Windows组件中的错误。 Windows组总是非常不愿意让虫子像这样固定的,打破更改推迟到下一个Windows版本。它没有得到固定在Windows 8.不要认为它是多么不寻常的你在做什么,图像的DPI应始终由记录图像的设备进行设置。像相机或扫描仪,他们从来没有得到这个错误。那里只是不在身边,有一个200点每英寸的分辨率的设备。

Hmya, this is a bug in a Windows component. The Windows group is always very reluctant to get bugs like this fixed, breaking changes are postponed to a next Windows version. It did get fixed in Windows 8. Do consider how unusual it is what you are doing, the DPI of an image should always be set by the device that recorded the image. Like the camera or scanner, they never get this wrong. There just isn't any device around that has a 200 dots-per-inch resolution.

如果你有足够的急于找到一种解决方法,那么你可以考虑修补文件本身。不难为JPEG文件做的,在文件头中的字段是很容易得到:

If you are desperate enough to find a workaround then you could consider patching the file itself. Not hard to do for a JPEG file, the fields in the file header are pretty easy to get to:

using System.IO;
...
    public static void SetJpegResolution(string path, int dpi) {
        using (var jpg = new FileStream(path, FileMode.Open, FileAccess.ReadWrite, FileShare.None)) 
        using (var br = new BinaryReader(jpg)) {
            bool ok = br.ReadUInt16() == 0xd8ff;        // Check header
            ok = ok && br.ReadUInt16() == 0xe0ff;
            br.ReadInt16();                             // Skip length
            ok = ok && br.ReadUInt32() == 0x4649464a;   // Should be JFIF
            ok = ok && br.ReadByte() == 0;
            ok = ok && br.ReadByte() == 0x01;           // Major version should be 1
            br.ReadByte();                              // Skip minor version
            byte density = br.ReadByte();
            ok = ok && (density == 1 || density == 2);
            if (!ok) throw new Exception("Not a valid JPEG file");
            if (density == 2) dpi = (int)Math.Round(dpi / 2.56);
            var bigendian = BitConverter.GetBytes((short)dpi);
            Array.Reverse(bigendian);
            jpg.Write(bigendian, 0, 2);
            jpg.Write(bigendian, 0, 2);
        }
    }

这篇关于.NET - Bitmap.Save忽略Bitmap.SetResolution在Windows 7的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆