How to disable subsampling with .NET / GDI+?

落花浮王杯 提交于 2019-12-09 13:25:04

问题


I am trying to save a JPEG image using the Bitmap class. I noticed that sharp edges were always blury regardless of the quality level that I specify. I figured out that it is due to subsampling of one or more of the channels. How do I disable subsampling when saving the image?

I am currently using this code:

EncoderParameters parameters = new EncoderParameters(1);
parameters.Param[0] = new EncoderParameter(Encoder.Quality, 85L);

ImageCodecInfo codec = GetEncoderInfo("image/jpeg");
image.Save(path, codec, parameters);

NOTE

I know that JPEG is lossy, but that's not the issue here. If I use ImageMagick and save the image with the default options, I get similar results. However, if I specify 1:1:1 subsampling, the blurring disappears.

I do not want to use PNG because I need better compression. If I save the image as BMP and then convert it manually to JPEG, I get excellent results, without blurring. Therefore, the format is not the issue here.


回答1:


JPEG is an image format which uses lossy compression. It will cause degredation of your image, no matter what quality setting you choose.

Try using a better format for this, such as .PNG. Since .PNG files use a lossless compression algorithm, you will not get the artifacts you are seeing.


The problem (after reading your edits) is probably due to the fact that GDI+ uses 4:1:1 subsampling for JPG files in it's default Encoder.

I believe you could either install another encoder (not sure how to do this). Otherwise, I'd recommend using something like MagickNet to handle saving your JPG files. (It's a .net wrapper for ImageMagick - there are a couple of them out there.)


Edit 2: After further looking into this, it looks like you may be able to have some effect on this by tweaking the Encoder Luminance Table and Chrominance Table.




回答2:


I've been trying to figure out how to do this for 2 days, it just blows my mind that M$ wouldn't have included such a simple feature in GDI+. As an alternative, I implemented my own Bitmap -> Jpeg compressor by writing a small wrapper function around libjpeg. The critical step is to turn off subsampling like this:

struct jpeg_compress_struct cinfo;
...
jpeg_set_defaults(&cinfo);
cinfo.comp_info[0].h_samp_factor = 1;
cinfo.comp_info[0].v_samp_factor = 1;
cinfo.comp_info[1].h_samp_factor = 1;
cinfo.comp_info[1].v_samp_factor = 1;
cinfo.comp_info[2].h_samp_factor = 1;

However, this introduced another problem for me: libjpeg doesn't support writing exif tags, which I also need. Of course GDI+ won't add tags without reencoding the jpg, which completely defeats the purpose. I looked at libexif, but couldn't get it to compile under visual studio. If anyone did figure out a way to disable subsampling in GDI+, I'd still love to hear about it...




回答3:


Did you change SmoothingMode property for your Graphics object? In my experimentation, I have found that specifying SmoothingMode value to be anything other than the default blurs the sharp edges. Try it and see if that helps.



来源:https://stackoverflow.com/questions/745610/how-to-disable-subsampling-with-net-gdi

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!