In typical computer APIs, βYUVβ actually means YCbCr, and βYUYVβ means βYCbCr 4: 2: 2,β stored as Y0, Cb01, Y1, Cr01, Y2 ...
Thus, if you have a "YUV" image, you can save it to libjpeg using the JCS_YCbCr color space.
When you have image 422 (YUYV), you must duplicate the Cb / Cr values ββby the two pixels they need before writing the scan line to libjpeg. So this write loop will do it for you:
// "base" is an unsigned char const * with the YUYV data // jrow is a libjpeg row of samples array of 1 row pointer cinfo.image_width = width & -1; cinfo.image_height = height & -1; cinfo.input_components = 3; cinfo.in_color_space = JCS_YCbCr; jpeg_set_defaults(&cinfo); jpeg_set_quality(&cinfo, 92, TRUE); jpeg_start_compress(&cinfo, TRUE); unsigned char *buf = new unsigned char[width * 3]; while (cinfo.next_scanline < height) { for (int i = 0; i < cinfo.image_width; i += 2) { buf[i*3] = base[i*2]; buf[i*3+1] = base[i*2+1]; buf[i*3+2] = base[i*2+3]; buf[i*3+3] = base[i*2+2]; buf[i*3+4] = base[i*2+1]; buf[i*3+5] = base[i*2+3]; } jrow[0] = buf; base += width * 2; jpeg_write_scanlines(&cinfo, jrow, 1); } jpeg_finish_compress(&cinfo); delete[] buf;
Use your favorite auto-ptr to avoid a buf leak if your error or write function might call / longjmp.
Providing YCbCr in libjpeg directly is preferable to convert to RGB, because it will store it directly in this format, thereby saving a lot of conversion work. When an image comes from a webcam or other video source, it is also usually most effective to get some kind of YCbCr (for example, YUYV.)
Finally, βUβ and βVβ mean something a little different from analog component video, so the name YUV in computer APIs, which really means YCbCr, is very confusing.