[讨论]气死人的Image.Save方法。

qldsrx 2010-04-12 05:37:24
  刚开始研究图片的基本操作,在图片保存位深度上折腾了2天都未果,找遍所有资料,都没有很好的解决png文件在保存时正确保存位深度。
  我想图片保存都是调用的Image.Save方法吧,Bitmap是继承Image的,所以一样。该方法的参数里虽然可以调整保存的位深度,但是使用无效。于是我想办法先将图片本身的位深度改变,然后保存。的确,这样保存是有效果的,因为文件大小不同了,但是查看图片属性的话,还是32位的,并没有变化,这样就存在一个问题:当我再次读取这个图片时,获取其位深度信息就是32位的,其实内部用到的颜色并非32位的,变成了我用高的位深度来存储低位深度保存的图片,再次保存就会使图片体积变大,很变态啊。
  后来找到了一个方法,参考如下:
MemoryStream ms = new MemoryStream();
img1.Save(ms, ImageFormat.Bmp);
var img2 = Image.FromStream(ms);

  先将img1以bmp格式保存到内存流,然后读取回来,用img2保存到文件中,这样文件的位深度就正确了。

  为什么要绕个弯呢,不能直接保存正确呢?我想可能是微软的BUG,于是我下载了微软免费绘图软件PAINT.NET,看看它保存的时候是不是也这样。结果果然被我猜中了,它保存为png文件时,第一次还是显示的32位的,不过第二次重新保存能够正常,虽然不知道这个第二次的原理为何物,但至少说明了这个Image.Save方法存在BUG。

  关于正确保存png文件的位深度,如有高见,亦可发表各自的建议。
...全文
3295 63 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
63 条回复
切换为时间正序
请发表友善的回复…
发表回复
autujuny 2011-08-25
  • 打赏
  • 举报
回复
学习之
Snafarod 2010-08-04
  • 打赏
  • 举报
回复
哈哈,楼主我顶你,最近我也遇到类似的诡异问题了
Bitmap bmp = new Bitmap(width,height,System.Drawing.Imaging.PixelFormat.Format32bppArgb);
Rectangle rect = new Rectangle(0, 0, width, height);
System.Drawing.Imaging.BitmapData bmpData = bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.WriteOnly, bmp.PixelFormat);
System.Runtime.InteropServices.Marshal.Copy(RGBData, 0, bmpData.Scan0, width* height * 4);
bmp.UnlockBits(bmpData);
//bmp.Save("b1.bmp", System.Drawing.Imaging.ImageFormat.Bmp);
//这里试着把bmp另存出来,直接在windows里浏览没有任何问题
pictureBox1.Image = bmp;
//但这里pictureBox1就愣是啥都不显示
MemoryStream ms = new MemoryStream();
bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
pictureBox1.Image = (Bitmap)Image.FromStream(ms);
//后来无奈又加了这么三句,绕了个弯就能正常显示了
qldsrx 2010-04-19
  • 打赏
  • 举报
回复
好像没有人想讨论了,算了,那东西已经超出这里的人可以处理的能力范围了——结贴。

其实就是为了压缩图片,不然不用考虑图像位数。反复测试下来,使用gif的8位保存和用jpg的80%压缩比起来,容量差不多,质量还是jpg的好,jpg只有24位一种,所以也可以不用考虑位深度。
qldsrx 2010-04-14
  • 打赏
  • 举报
回复
TO #48楼(zgke)
不好意思,我写错了,不是无法保存为32位的,是无法保存为8位的,明明创建的是8位图,但是保存后显示32位图的png,保存格式为bmp就正常。
porschev 2010-04-14
  • 打赏
  • 举报
回复
3Q..学习了........

zgke 2010-04-14
  • 打赏
  • 举报
回复
[Quote=引用 42 楼 qldsrx 的回复:]
又有新发现了,当我使用
public static Image FromFile(
string filename,
bool useEmbeddedColorManagement
)
的时候,读取的png文件重新保存会将位深度保存正确,但是如果我新创建一个图片,例如
Bitmap output = new Bitmap(width, height, PixelFormat.Forma……
[/Quote]
PixelFormat.Format8bppIndexed 已经指定了图形的方式。图形结构指定为 颜色表 和颜色的索引。
zhl198118_001 2010-04-14
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 qldsrx 的回复:]

引用 13 楼 chrisak 的回复:
有没有试过修改ColorDepth参数保存呢?

不提那个参数也罢,提了更加气人,System.Drawing.Imaging.Encoder.ColorDepth压根没用,不但对png没用,对bmp格式也无效,对tiff格式虽然有效,但它会自动将不存在的颜色给删除,最后就变成了一张空白图。颜色深度必须是看PixelFormat,而且微软没有提供这……
[/Quote]顶你,IMAGE里有很多问题的,如FROMFILE()不释放图片文件等等,
sunmin2008 2010-04-14
  • 打赏
  • 举报
回复
我和你做的一样的工作,不过没办法,谁让它是这样的呢
qldsrx 2010-04-14
  • 打赏
  • 举报
回复
[Quote=引用 53 楼 llszn 的回复:]
顶一下吧。我也是这样的问题,保存不了。8位恢度jpg
[/Quote]
jpg只有24位一种形式,所以你改不了,不过也正因为这样,使用jpg格式的人,可以无视位深度。

[Quote=引用 57 楼 yuxuanji 的回复:]
可能是BMP默认使用RGB8位通道也就是24位色深的问题
瞎猜的
[/Quote]
Bitmap类指的不是BMP一种形式,它包含了JPG、PNG、TIFF、BMP等多种图片格式,保存的时候才去选择保存格式的。
fuchunjun 2010-04-14
  • 打赏
  • 举报
回复
每天回帖只有10分?多回没用??
LutzMark 2010-04-14
  • 打赏
  • 举报
回复
可能是BMP默认使用RGB8位通道也就是24位色深的问题
瞎猜的
jiayp004 2010-04-14
  • 打赏
  • 举报
回复
Bitmap img = new Bitmap(spW, spH,PixelFormat.Format24bppRgb);
wangxiao2008 2010-04-14
  • 打赏
  • 举报
回复
每天回帖即可获得10分可用分!
taikonhmao67 2010-04-14
  • 打赏
  • 举报
回复
每天回帖即可获得10分可用分!
llszn 2010-04-14
  • 打赏
  • 举报
回复
顶一下吧。我也是这样的问题,保存不了。8位恢度jpg
mjp1234airen4385 2010-04-14
  • 打赏
  • 举报
回复
还是使用GDI+吧。绝对的好使。
@井九 2010-04-13
  • 打赏
  • 举报
回复
mark
qldsrx 2010-04-13
  • 打赏
  • 举报
回复
又有新发现了,当我使用
public static Image FromFile(
string filename,
bool useEmbeddedColorManagement
)
的时候,读取的png文件重新保存会将位深度保存正确,但是如果我新创建一个图片,例如
Bitmap output = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
然后将一个32位的png图片复制过去,用新的8位图保存,就无法存为32位图信息,这里面应该有个图片位深度的属性,不知该属性如何设置,有谁知道的吗?
June1991 2010-04-13
  • 打赏
  • 举报
回复
学习了~
加载更多回复(42)

111,098

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧