问题
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