简体   繁体   English

位图保存在.Net中是否以不正确的格式保存图像?

[英]Bitmap Save in .Net is saving the image in an incorrect format?

We have a piece of code which saves a .Net System.Drawing.Bitmap to file. 我们有一段代码将.Net System.Drawing.Bitmap保存到文件中。 The Save call is specifying the file location as well as the ImageFormat which we are expecting to save the image data as a Jpeg so out code looks like this: Save调用指定文件位置以及我们期望将图像数据保存为Jpeg的ImageFormat,因此输出代码如下所示:

public MediaFile IngestImage(System.Drawing.Bitmap imgSrc, string name){
     ... // left out because it is not relevant to this question
     imgSrc.Save(fullPath, System.Drawing.Imaging.ImageFormat.Jpeg);
     ... // left out because it is not relevant to this question
}

For some reason every now and then this method generates PNG images as .jpg files. 出于某种原因,此方法偶尔会将PNG图像生成为.jpg文件。 Most of the time it is not a big deal however another piece of the project has issues with these files not being actual jpegs (Windows Media Services). 大多数情况下,这并不是什么大问题,但是项目的另一部分存在问题,这些文件不是真正的jpeg(Windows Media Services)。

Any help is appreciated, has anyone ever seen this? 任何帮助表示赞赏,有没有人见过这个?

Note: full path is something like "\\servcer\\share\\file.jpg". 注意:完整路径类似于“\\ servcer \\ share \\ file.jpg”。 We are saving jpg's with the extension "jpg". 我们正在使用扩展名“jpg”保存jpg。 Hence the issue... Later we are creating publishing points on a Windows Media Server to play a SMIL playlist we then have to "Announce" the files and formats to the publishing point when the publishing point starts playing it expects a Jpg file because that is the extension of the file and the content is actually a PNG 因此问题......后来我们在Windows Media Server上创建发布点来播放SMIL播放列表,然后我们必须在发布点开始播放时“宣布”文件和格式到发布点它需要一个Jpg文件,因为那样是文件的扩展名,内容实际上是PNG

Here is the actual code creating the BitpMap object that is passed into the above method... 这是创建BitpMap对象的实际代码,它传递给上面的方法...

        public static Bitmap CreateBitmap(string text, int height, int width, Color foregroundColor, Color backgroundColor, string fontName, int fontSize, bool antialias)
    {
        // Initialize graphics
        Bitmap bmp = new Bitmap(width, height, PixelFormat.Format24bppRgb);
        using (Graphics g = Graphics.FromImage(bmp))
        {
            g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
            //g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
            g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
            if (antialias)
            {
                g.SmoothingMode = SmoothingMode.AntiAlias;
                g.TextRenderingHint = TextRenderingHint.AntiAlias;
            }

            // Set colors
            SolidBrush fgBrush = new SolidBrush(foregroundColor);
            SolidBrush bgBrush = new SolidBrush(backgroundColor);

            // paint background
            RectangleF rectF = new RectangleF(0, 0, width, height);
            g.FillRectangle(bgBrush, rectF);

            // Load font
            FontFamily fontFamily = FontFamily.GenericSerif;
            Font font = new Font(fontFamily, fontSize, FontStyle.Regular, GraphicsUnit.Pixel);
            try
            {
                fontFamily = new FontFamily(fontName);
                font = new Font(fontFamily, fontSize, FontStyle.Regular, GraphicsUnit.Pixel);
            }
            catch { }

            // Set font direction & alignment
            StringFormat format = new StringFormat();
            format.Alignment = StringAlignment.Center;
            format.LineAlignment = StringAlignment.Center;

            // Finally, draw the text
            g.DrawString(text, font, fgBrush, rectF, format);

            return bmp;
        }
    }

I'd approach this by: 我通过以下方式解决这个问题:

  1. paring down CreateBitmap() . 削减CreateBitmap() For instance, does the problem appear if you remove everything except line that calls new and the return line? 例如,如果删除除调用newreturn行的行之外的所有内容,是否会出现问题? I'd assume it would, but it's worth checking. 我认为它会,但值得检查。 If on the odd chance the problem disappears with this modification, then use a binary search to see if you can track it down to a particular line. 如果在奇怪的情况下问题随着此修改而消失,则使用二进制搜索来查看是否可以将其跟踪到特定行。

  2. wrapping the Save call with try / catch to see if somewhere a ExternalException is being silently eaten. 使用try / catch包装Save调用以查看某个地方是否正在静默地使用ExternalException Bitmap.Save() (inherited from Image.Save() ) says the following about ExternalException : Bitmap.Save() (继承自Image.Save() )说下面的ExternalException

The image was saved with the wrong image format. 图像以错误的图像格式保存。

-or- -要么-

The image was saved to the same file it was created from. 图像已保存到创建它的同一文件中。

Is is possible that the files that fail already exist at fullPath in PNG format with the .jpg extension? 有可能失败的文件已经存在于具有.jpg扩展名的PNG格式的fullPath中吗?

I am also experiencing this issue in a cropping application. 我也在裁剪应用程序中遇到此问题。 The source image file is a JPG. 源图像文件是JPG。 I have attempted several different ImageFormat types, and in all instances the format saved is a PNG with a JPG file extension. 我尝试了几种不同的ImageFormat类型,并且在所有情况下保存的格式都是带有JPG文件扩展名的PNG。 Photoshop then complains 'Invalid JPEG marker type'. Photoshop然后抱怨'无效的JPEG标记类型'。 If I rename the file to .png it opens fine in Photoshop. 如果我将文件重命名为.png,它在Photoshop中打开正常。

Attempting this with a different image, produces a correct JPG format with JPG extension. 尝试使用不同的图像,生成JPG扩展名的正确JPG格式。

I suspect the format of the original file could possibly be to blame. 我怀疑原始文件的格式可能是罪魁祸首。 I will post my findings when this issue is resolved. 当这个问题得到解决时,我会发布我的发现。

Well, I gave it shot and tried to repro the issue with the code given above. 好吧,我试了一下,试图用上面给出的代码重新解决这个问题。 Here is roughly what I did: 这大致是我做的:

    Random r = new Random();
    for (int i = 0; i < max; i++)
    {
        System.Diagnostics.Debugger.Break()
        int size = 1 + i;
        int width = 1 + i;
        SaveBitmap(@"C:\Projects\test.jpg", ImageFormat.Jpeg, "hello", size, width, Color.Black, Color.White, "Arial", size, true);
        SaveBitmap(@"C:\Projects\test.png", ImageFormat.Jpeg, "hello", size, width, Color.Black, Color.White, "Arial", size, true);
        SaveBitmap(@"C:\Projects\test.jpg", ImageFormat.Jpeg, "hello", size, width, Color.Black, Color.White, "Arial", size, false);
        SaveBitmap(@"C:\Projects\test.png", ImageFormat.Jpeg, "hello", size, width, Color.Black, Color.White, "Arial", size, false);
    }

    public static void SaveBitmap(string filename, ImageFormat format, string text, int height, int width, Color foregroundColor, Color backgroundColor, string fontName, int fontSize, bool antialias)
    {
        using (Image source = CreateBitmap(text, height, width, foregroundColor, backgroundColor, fontName, fontSize, antialias))
            source.Save(filename, format);

        using (Image imgLoaded = Bitmap.FromFile(filename))
        {
            if (imgLoaded.RawFormat.Guid != format.Guid)
                throw new InvalidOperationException();
        }
    }

This runs without issue and the test for if (imgLoaded.RawFormat.Guid != format.Guid) never breaks into the debugger. 这运行没有问题,if(imgLoaded.RawFormat.Guid!= format.Guid)的测试永远不会进入调试器。 I'm guessing you have a little more code than the CreateBitmap routine posted above. 我猜你有比上面发布的CreateBitmap例程更多的代码。

My Recommendation: 我的建议:

Modify your code and insert the verification statement in the above SaveBitmap() just after your call to Image.Save(). 在调用Image.Save()之后修改代码并在上面的SaveBitmap()中插入验证语句。 Then go break it as see how you got there... 然后去看看它是如何到达那里的......

Maybe this is an issue with the filename you or the user is specifiing. 也许这是您或用户指定的文件名的问题。 it could be that if it ends with .png then jpegformat is ignored and a PNG file is generated. 可能是如果以.png结尾,则忽略jpegformat并生成PNG文件。

you may try this to save file 你可以尝试这个来保存文件

public bool ResizeImage(string OriginalFilepath, string NewFilepath)
    {
        Bitmap original = (Bitmap)Image.FromFile(OriginalFilepath);
        Bitmap resized = new Bitmap(original, new Size(width,height));
        resized.Save(NewFilepath.jpeg);

    }

Have you tried setting the ImageCodecInfo explicitly? 您是否尝试过显式设置ImageCodecInfo?

Dim enc = ImageCodecInfo.GetImageEncoders().ToList().Find(Function(e) e.MimeType = "image/png")
objBitMap.Save(stream, enc, params)

C# Win7(64bit) VS 2010 Bitmap.Save("wnd.bmp") saves in png format. C#Win7(64位)VS 2010 Bitmap.Save(“wnd.bmp”)保存为png格式。 MainWnd is a C# Form I capture and attempt to save to file as bitmap. MainWnd是一个C#表单我捕获并尝试将其保存为文件位图。

        Bitmap bmp = new Bitmap(MainWnd.ActiveForm.Width, MainWnd.ActiveForm.Height);
        Rectangle crec = MainWnd.ActiveForm.ClientRectangle;
        Rectangle r = this.ClientRectangle;
        MainWnd.ActiveForm.DrawToBitmap(bmp, r);
        bmp.Save("wnd.bmp");  // saves as PNG not BMP !!

00000000 89 50 4E 47 0D 0A 1A 0A - 00 00 00 0D 49 48 44 52 ‰PNG........IHDR 00000010 00 00 04 0B 00 00 02 E6 - 08 06 00 00 00 24 30 1D .......æ.....$0. 00000000 89 50 4E 47 0D 0A 1A 0A - 00 00 00 0D 49 48 44 52‰PNG ........ IHDR 00000010 00 00 04 0B 00 00 02 E6 - 08 06 00 00 00 24 30 1D ... ....æ..... $ 0 00000020 D1 00 00 00 01 73 52 47 - 42 00 AE CE 1C E9 00 00 Ñ....sRGB.®Î.é.. 00000020 D1 00 00 00 01 73 52 47 - 42 00 AE CE 1C E9 0000Ñ....sRGB.®... ..

It looks like your fullPath might be saving the file with a png extension, and you're telling imgSrc to compress the image using Jpeg compression. 看起来你的fullPath可能正在使用png扩展名保存文件,并且你告诉imgSrc使用Jpeg压缩来压缩图像。

I would verify that the fullPath's extension is jpeg or jpg, and not png. 我会验证fullPath的扩展名是jpeg或jpg,而不是png。

Here's the msdn doc on the Save. 这是Save上的msdn doc

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

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