Support for chroma subsampling other than 4:2:0
I have tried compressing a raw 24 bpp image represented by an byte array, I have tried both the JpegImage API and the low level jpeg_compress_struct structure, I even tried changing the internal jpeg_set_colorspace_SET_COMP() values i either get 4:2:0 chroma image or "Not implemented exception" my input colorspace is RGB my output colorspace is YcBcR
Could you please provide a sample code and image to reproduce the issue?
Here's the code:
int[] LumTable = new int[]
{
16, 11, 10, 16, 24, 40, 51, 61,
12, 12, 14, 19, 26, 58, 60, 55,
14, 13, 16, 24, 40, 57, 69, 56,
14, 17, 22, 29, 51, 87, 80, 62,
18, 22, 37, 56, 68, 109, 103, 77,
24, 35, 55, 64, 81, 104, 113, 92,
49, 64, 78, 87, 103, 121, 120, 101,
72, 92, 95, 98, 112, 100, 103, 99
};
int[] ChromaTable = new int[]
{
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255
};
try
{
Bitmap bmp = new Bitmap(@"c:\temp\chromatestInput.jpg");
int width = bmp.Width;
int height = bmp.Height;
int bpp = 3; //bytes per pixel
byte[] testImage = new byte[height * width * bpp];
BitmapData bmData = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite,
bmp.PixelFormat);
Marshal.Copy(bmData.Scan0, testImage, 0, testImage.Length);
bmp.UnlockBits(bmData);
int quality = 100;
using (var fs = new FileStream(@"c:\temp\chromatestOutput.jpg", FileMode.Create))
{
BitMiracle.LibJpeg.Classic.jpeg_error_mgr err = new jpeg_error_mgr();
BitMiracle.LibJpeg.Classic.jpeg_compress_struct cmpStr = new jpeg_compress_struct(err);
cmpStr.jpeg_stdio_dest(fs);
cmpStr.Image_width = width;
cmpStr.Image_height = height;
cmpStr.Input_components = bpp;
cmpStr.jpeg_set_defaults();
cmpStr.In_color_space = J_COLOR_SPACE.JCS_RGB;
cmpStr.jpeg_set_colorspace(J_COLOR_SPACE.JCS_YCbCr);
cmpStr.jpeg_set_quality(quality, false);
cmpStr.Optimize_coding = false;
cmpStr.jpeg_add_quant_table(0, LumTable, 100, true);
cmpStr.jpeg_add_quant_table(1, ChromaTable, 100, true);
cmpStr.Dct_method = J_DCT_METHOD.JDCT_IFAST;
byte[][] rowlines = new byte[1][];
rowlines[0] = new byte[cmpStr.Image_width * bpp];
cmpStr.jpeg_start_compress(true);
for (int i = 0; i < height && cmpStr.Next_scanline < cmpStr.Image_height; i++)
{
Buffer.BlockCopy(testImage,i*cmpStr.Image_width*bpp,rowlines[0]
,0,cmpStr.Image_width*bpp);
cmpStr.jpeg_write_scanlines(rowlines, 1);
}
cmpStr.jpeg_finish_compress();
}
}
catch (Exception exception)
{
System.Console.WriteLine(exception);
throw;
}
and the test file (input)
the code generates an output file

@shibaev Any progress?
Did you attach the chromatestInput.jpg? It looks that the only attachment https://user-images.githubusercontent.com/42567361/88899292-8ba3a700-d256-11ea-9060-0719a61e9ada.jpg corresponds to chromatestOutput.jpg.
Also please clarify what is expected result for you? I.e. what is wrong with the https://user-images.githubusercontent.com/42567361/88899292-8ba3a700-d256-11ea-9060-0719a61e9ada.jpg image.
The attached image is an input image (it was meant to appear a line above) the code generates an output (not attached, it is generated by the code) the expected result is a 4:2:2 chroma subsampling (or any other than 4:2:0)
Thank you for your explanation. Currently, LibJpeg.Net only supports 2x2 (4:2:0) and 1x1 (4:4:4) subsampling levels. You can produce 1x1 output using these lines:
var comp0 = cmpStr.Component_info[0];
comp0.V_samp_factor = 1;
comp0.H_samp_factor = 1;
Other variations are currently not implemented. Look at jpeg_fdct_*x* methods in /LibJpeg/Classic/Internal/jpeg_forward_dct.cs
However, the original libjpeg supports other subsampling levels. You can look at the latest version from http://www.ijg.org/.
Unfortunately, this feature has a low priority for us. We would appreciate a pull request that:
- Migrates logic for some or all missing jpeg_fdct_*x* methods from the original libjpeg to our managed version. I cannot guarantee that migration of jpeg_fdct_*x* is enough, so be ready to migrate some other related code.
- Includes tests covering the migrated code