Win7下Bitmap.Clone方法处理CMYK图片OutOfMemory异常的解决办法

简介:

Winform下的图像处理比较郁闷,动不动就蹦出这个 OutOfMemory 异常而不给具体原因。刚才谈新客户,他发给我几张jpg图片,让我处理一下给效果图出来,我用自己的图像处理程序一打开,蹦的一下,蹦出来了个 OutOfMemory 异常。跟踪进去发现,PixelFormat值为 8207,见下图:

image

我的程序是将所有的图像都转化为 Format24bppRgb 或 Format32bppArgb  格式的图像,然后再进行处理,对于不是 Format24bppRgb 或 Format32bppArgb  这两种格式的图像,则使用 Bitmap.Clone()方法进行转化,而这个方法,在处理 PixelFormat 值为 8207 的图像时抛出了异常。

搜索表明,8027是CMYK格式的图像,这是一个在Win7下独有的bug,在xp下,.Net FW会自动把该格式的转换为 RGB 格式的图片(未验证),而Win7下不会[ Image has wrong Image.PixelFormat on Windows 7, not on XP]:

John Farrow:

The problem is that there are some values missing from the Image.PixelFormat enumeration.  8207 is pixel format PixelFormat32bppCMYK (based on GdiPlusHeaders.h).  For some reason this value is not part of the PixelFormat enumeration.

When the problem image is loaded on Windows XP, the .NET framework converts it from CMYK to RGB and thus it matches a value in the enumeration such as PixelFormat32bppRGB but when the image is loaded on Windows 7 it is not converted to RGB, but remains in CMYK format.

So the solution is for the application to explicitly test for the 8207 value and treat the image as having PixelFormat32bppCMYK.

也就是说,8207 是一个未定义的 PixelFormat 枚举值,它应该是 PixelFormat32bppCMYK 格式的图像。

还是在该页面,JohnWein给了个解决办法:

private static Bitmap DownsampleImage(Bitmap srcImg, int destW, int destH, float dstDPI) 

    Bitmap bmPhoto = new Bitmap(destW, destH,PixelFormat.Format32bppRgb); 
    bmPhoto.SetResolution(dstDPI, dstDPI); 
    Graphics grPhoto = Graphics.FromImage(bmPhoto); 
    grPhoto.InterpolationMode = InterpolationMode.HighQualityBicubic; 
    grPhoto.DrawImage(srcImg, 
                      new System.Drawing.Rectangle(0, 0, bmPhoto.Width, bmPhoto.Height), 
                      new System.Drawing.Rectangle(0, 0, srcImg.Width, srcImg.Height), 
                      GraphicsUnit.Pixel); 
    grPhoto.Dispose(); 
    return bmPhoto; 
}

据测试,该方法可行,问题解决。下面是我修改后的代码:

private unsafe void CreateFromBitmap(Bitmap map) 

    int height = map.Height; 
    int width = map.Width;

    const int PixelFormat32bppCMYK = 8207;

    PixelFormat format = map.PixelFormat;

    if (this.Width != width || this.Height != height) 
    { 
        return; 
    }

    Bitmap newMap = map; 
    Int32 step = SizeOfT();

    switch (format) 
    { 
        case PixelFormat.Format24bppRgb: 
            break; 
        case PixelFormat.Format32bppArgb: 
            break; 
        default: 
            if ((int)format == PixelFormat32bppCMYK) 
            { 
                format = PixelFormat.Format24bppRgb; 
                newMap = new Bitmap(width, height, format); 
                using (Graphics g = Graphics.FromImage(newMap)) 
                { 
                    g.DrawImage(map, new Point()); 
                } 
            } 
            else 
            { 
                format = PixelFormat.Format32bppArgb; 
                newMap = map.Clone(new Rectangle(0, 0, width, height), PixelFormat.Format32bppArgb); 
            } 
            break; 
    }

    BitmapData data = newMap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, format); 
    Byte* line = (Byte*)data.Scan0;

    ……

}

本文转自xiaotie博客园博客,原文链接http://www.cnblogs.com/xiaotie/archive/2011/03/09/1978121.html如需转载请自行联系原作者


xiaotie 集异璧实验室(GEBLAB)

相关文章
|
JavaScript
js中字符串转base64以及base64转字符串原理及实现
今天刷codewars的题目的时候碰到一个通过js来实现字符串转base64的题目,base64虽然在js或nodejs中经常用,但是我还真没有仔细去看过原理以及如何实现,这回绕不过去了,赶紧找了找资料看了下。
js中字符串转base64以及base64转字符串原理及实现
|
Windows
Winform控件优化之背景透明那些事1:Button控件等背景透明
WinForm不支持真正的透明,其控件透明的实现都是背景颜色设置和对应位置的父控件背景相同。 Winform中控件的背景透明只有三种:Button控件的透明、其他控件的透明...
3490 0
Winform控件优化之背景透明那些事1:Button控件等背景透明
|
机器学习/深度学习 监控 算法
信用风险评估评分卡建模方法及原理| 学习笔记
快速学习信用风险评估评分卡建模方法及原理。
信用风险评估评分卡建模方法及原理| 学习笔记
|
C# 图形学 Windows
Winform控件优化之背景透明那些事2:窗体背景透明、镂空穿透、SetStyle、GDI透明效果等
两行代码就能实现Form窗体的(背景)透明效果,它不是Opacity属性的整个窗体透明,`TransparencyKey`实现窗体的透明、窗体中间部分镂空效果...
4048 0
Winform控件优化之背景透明那些事2:窗体背景透明、镂空穿透、SetStyle、GDI透明效果等
|
8月前
|
人工智能 编解码 算法
全球顶级赛事实践:视频云制播在奥运赛事的关键技术与创新
本次分享主题为“全球顶级赛事实践:视频云制播在奥运等体育赛事的关键技术与创新”。内容涵盖视频云制播的整体技术框架、AI技术重构体育赛事全链路、视频云制播+AI的技术创新与应用、未来展望,以及央视频在奥运等赛事中的成功实践。通过阿里云和央视频的合作,展示了多语种解说、多视角同步、智能媒资管理等技术创新,提升了观众的观赛体验,并推动了体育赛事转播的智能化发展。
333 0
|
缓存 NoSQL Java
【亮剑】分布式锁是保证多服务实例同步的关键机制,常用于互斥访问共享资源、控制访问顺序和系统保护,如何使用注解来实现 Redis 分布式锁的功能?
【4月更文挑战第30天】分布式锁是保证多服务实例同步的关键机制,常用于互斥访问共享资源、控制访问顺序和系统保护。基于 Redis 的分布式锁利用 SETNX 或 SET 命令实现,并考虑自动过期、可重入及原子性以确保可靠性。在 Java Spring Boot 中,可通过 `@EnableCaching`、`@Cacheable` 和 `@CacheEvict` 注解轻松实现 Redis 分布式锁功能。
239 0
|
网络安全 C#
C# HttpWebRequest 获取 HTTPS 网页内容
C# HttpWebRequest 获取 HTTPS 网页内容
1566 0
|
JavaScript 前端开发 安全
【TypeScript技术专栏】TypeScript在Electron桌面应用中的实践
【4月更文挑战第30天】本文介绍了如何在Electron桌面应用中采用TypeScript以提升代码质量和可维护性。Electron利用Chromium和Node.js让前端开发者能创建桌面应用,而TypeScript的强类型系统和高级语言特性有助于管理复杂项目。通过初始化项目、安装依赖、配置TypeScript、编写主进程和渲染进程代码,开发者可以在Electron中实践TypeScript。一个简单的文本编辑器案例展示了TypeScript在确保类型安全方面的优势。尽管有学习成本,但TypeScript对大型Electron项目来说是值得的。
1031 0
|
C++
VS、ReSharper 设置修改代码颜色、提高代码辨识度!附VS超实用快捷!
ReSharper 配置代码颜色 本文提供全流程,中文翻译。 Chinar 坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 —— 高分辨率用户请根据需求调整网页缩放比例) ...
5098 0