为什么使用System.Drawing创建的JPEG图像比原始位图大?

3
我遇到了一个奇怪的问题 - 我有大约1450万个位图图像,据说是未压缩的。我需要将这些位图转换为JPG格式并存储在数据库中。
当我使用.NET System.Drawing库中提供的类将位图保存为ImageFormat.Jpeg时,生成的JPEG文件大小约为原始位图的两倍。以下是代码:
byte[] bitmapBytes = //get from the db
using(MemoryStream bitmapStream = new MemoryStream(bitmapBytes))
{
   using(Bitmap bitmap = (Bitmap)Bitmap.FromStream(bitmapStream))
   {
       bitmap.Save("jpg.jpg", ImageFormat.Jpeg);
   }
}

我查看了几个图像的HEX代码,发现压缩设置为“none”。因此我认为它们是未经压缩的。此外,原始文件的HEX代码具有“BMP”代码,而结果文件具有预期的“JFIF”代码。
这些图像是黑白的,没有颜色。
您有什么想法,为什么会出现这种情况?希望能给出正确方向的指针...
编辑:
- 我尝试使用允许您指定质量的替代重载保存。但没有看到任何好处。 - 我也应该说明,我在某种程度上被JPEG所困。这是一个传统系统,系统的其他部分需要JPEG。
图像属性:
- 位图尺寸:152x48 - 位图文件大小:1022字节 - JPEG:相同的尺寸 - JPEG大小:2.2 kb - 位图信息:索引,1层(2种颜色) - 位图分辨率:96.012x96.012 ppi

2
另一个想法 - 如果您的图像确实是纯黑白色,没有灰度,那么JPEG格式将对此非常不利。你在这里的目标是什么? - Reed Copsey
最终目标是将它们转换成JPEG格式,原因是1:人们认为这比未压缩的位图更小,2:因为系统的其他部分期望JPEG格式。 - Sam Schutte
1
你考虑过/是否可以使用PNG格式? - Dead account
1
如果您能发布集合中典型图像的尺寸以及其在磁盘上所占空间的大小,那会很有帮助。如有可能,请包括颜色模式,这可以通过在GIMP或其他高级成像工具中打开图像轻松确定。此信息将使原始图像是否已压缩变得明显。 - PeterAllenWebb
我上传了文件信息 - 我需要安装一些东西来查看颜色模式,因为显然Paint.Net无法提供它给我。 - Sam Schutte
显示剩余2条评论
8个回答

6

这可能是因为你保存的JPEG图像现在是24位RGB彩色图像,而位图是1bpp的黑白图像。

如果位图是1bpp,那么将它们转换成JPEG格式可能不是最佳选择。


嗯...没错 - 没有想到过那个。我的问题之一是,由于系统的其他部分希望它是 JPEG (传统系统),所以我有点卡在了 JPEG 上。 - Sam Schutte
是的,1BPP意味着每个字节有8个水平像素。它本身作为“压缩”相当不错。 - Nyerguds

5

黑白或灰度?

来自http://www.faqs.org/faqs/compression-faq/part2/section-6.html

"JPEG可以处理全彩色或灰度图像;但它不能很好地处理双调(黑白)图像。它也不能处理颜色映射图像;你需要将它们预先扩展成未映射的全彩色表示。JPEG最适合处理“连续色调”图像。颜色值突然跳变很多的图像无法压缩得很好。”


非常好。这可能是问题的一部分。有趣的是,这已经是系统工作的方式至少7年了(虽然使用不同的代码方式,但仍转换为JPG)。 - Sam Schutte

4

2
你需要切换到使用这个Bitmap.Save重载方法,这样你就可以指定EncoderParameter
至于为什么你的文件变得更大了,可能是因为你的BMP文件使用了行程编码或使用了较小的(不是24位)位图。

我尝试了EncoderParameter,我尝试在十六进制编辑器中查看BMP文件以查看是否进行了运行长度编码,但似乎没有。对我来说很难确定,因为我不是一个精通于以十六进制方式读取位图的人。:) 但是24位可能也是值得关注的东西... - Sam Schutte
1
如果空间是一个问题,并且它是纯黑白的,将其保存为1bpp或4bpp的RLE位图可能比任何jpeg选项都要小。这对您的要求有用吗? - Reed Copsey
很难说。由于系统的其他部分需要JPEG,我可能需要进行一些测试。但根据大家的说法,位图肯定会更小。 - Sam Schutte

2
一张2色的61x64像素图片大小比较如下:
- Fax-4 tiff格式:268字节 - 2色bmp格式(如上所述):550字节 - 8位jpeg格式:1502字节 - 32位jpeg格式(如System.Drawing所创建):2015字节
因此,如果必须使用jpeg格式,请先将其转换为8位。在.NET中这样做可能有些麻烦,但是在CodeProject等网站上可以找到示例代码。

1

我想跟进一下我的解决方案。我成功地让系统支持PNG格式的图形,所以我将位图转换为PNG图形,并将它们变成每像素1位的黑白图像。这使它们变得小巧高效。

因此,问题在于JPG无法很好地处理少色彩的图像。



0
只是一个想法:你说你的系统的一部分需要文件是JPEG格式的。这是真的吗,还是只需要文件具有JPG扩展名? 如果是这样,你可以 - 尽管很丑陋 - 只需重命名文件扩展名,因为在你的情况下BMP文件更小。 例如,在Windows中,你可以将BMP文件的扩展名更改为JPG,当你打开它时,Windows不会在意并正确显示它。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接