Merge branch 'ijg.lossless' into dev
Lossless: Accommodate LJT colorspace/SIMD exts In libjpeg-turbo, grayscale_convert() and null_convert() aren't the only lossless color conversion algorithms. We can also losslessly convert RGB to and from any of the extended RGB colorspaces, and some platforms have SIMD-accelerated null color conversion. This commit also disallows RGB565 output in lossless mode, and it moves the IsExtRGB() macro from cdjpeg.h to jpegint.h and repurposes it to make jinit_color_converter() and jinit_color_deconverter() more readable.
This commit is contained in:
3
cdjpeg.h
3
cdjpeg.h
@@ -164,6 +164,3 @@ EXTERN(FILE *) write_stdout(void);
|
||||
#ifndef EXIT_WARNING
|
||||
#define EXIT_WARNING 2
|
||||
#endif
|
||||
|
||||
#define IsExtRGB(cs) \
|
||||
(cs == JCS_RGB || (cs >= JCS_EXT_RGB && cs <= JCS_EXT_ARGB))
|
||||
|
||||
6
cjpeg.1
6
cjpeg.1
@@ -1,4 +1,4 @@
|
||||
.TH CJPEG 1 "14 November 2022"
|
||||
.TH CJPEG 1 "16 November 2022"
|
||||
.SH NAME
|
||||
cjpeg \- compress an image file to a JPEG file
|
||||
.SH SYNOPSIS
|
||||
@@ -176,8 +176,8 @@ unavailable when compressing or decompressing a lossless JPEG file:
|
||||
.IP
|
||||
- Quality/quantization table selection
|
||||
.IP
|
||||
- Color conversion (the JPEG image will use the same color space as the input
|
||||
image)
|
||||
- Color space conversion (the JPEG image will use the same color space as the
|
||||
input image)
|
||||
.IP
|
||||
- DCT/IDCT algorithm selection
|
||||
.IP
|
||||
|
||||
64
jccolor.c
64
jccolor.c
@@ -577,24 +577,20 @@ _jinit_color_converter(j_compress_ptr cinfo)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check num_components, set conversion method based on requested space */
|
||||
/* Check num_components, set conversion method based on requested space.
|
||||
* NOTE: We do not allow any lossy color conversion algorithms in lossless
|
||||
* mode.
|
||||
*/
|
||||
switch (cinfo->jpeg_color_space) {
|
||||
case JCS_GRAYSCALE:
|
||||
if (cinfo->master->lossless &&
|
||||
cinfo->in_color_space != cinfo->jpeg_color_space)
|
||||
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
|
||||
if (cinfo->num_components != 1)
|
||||
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
|
||||
if (cinfo->in_color_space == JCS_GRAYSCALE)
|
||||
cconvert->pub._color_convert = grayscale_convert;
|
||||
else if (cinfo->in_color_space == JCS_RGB ||
|
||||
cinfo->in_color_space == JCS_EXT_RGB ||
|
||||
cinfo->in_color_space == JCS_EXT_RGBX ||
|
||||
cinfo->in_color_space == JCS_EXT_BGR ||
|
||||
cinfo->in_color_space == JCS_EXT_BGRX ||
|
||||
cinfo->in_color_space == JCS_EXT_XBGR ||
|
||||
cinfo->in_color_space == JCS_EXT_XRGB ||
|
||||
cinfo->in_color_space == JCS_EXT_RGBA ||
|
||||
cinfo->in_color_space == JCS_EXT_BGRA ||
|
||||
cinfo->in_color_space == JCS_EXT_ABGR ||
|
||||
cinfo->in_color_space == JCS_EXT_ARGB) {
|
||||
else if (IsExtRGB(cinfo->in_color_space)) {
|
||||
#ifdef WITH_SIMD
|
||||
if (jsimd_can_rgb_gray())
|
||||
cconvert->pub._color_convert = jsimd_rgb_gray_convert;
|
||||
@@ -611,6 +607,8 @@ _jinit_color_converter(j_compress_ptr cinfo)
|
||||
break;
|
||||
|
||||
case JCS_RGB:
|
||||
if (cinfo->master->lossless && !IsExtRGB(cinfo->in_color_space))
|
||||
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
|
||||
if (cinfo->num_components != 3)
|
||||
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
|
||||
if (rgb_red[cinfo->in_color_space] == 0 &&
|
||||
@@ -623,36 +621,19 @@ _jinit_color_converter(j_compress_ptr cinfo)
|
||||
else
|
||||
#endif
|
||||
cconvert->pub._color_convert = null_convert;
|
||||
} else if (cinfo->in_color_space == JCS_RGB ||
|
||||
cinfo->in_color_space == JCS_EXT_RGB ||
|
||||
cinfo->in_color_space == JCS_EXT_RGBX ||
|
||||
cinfo->in_color_space == JCS_EXT_BGR ||
|
||||
cinfo->in_color_space == JCS_EXT_BGRX ||
|
||||
cinfo->in_color_space == JCS_EXT_XBGR ||
|
||||
cinfo->in_color_space == JCS_EXT_XRGB ||
|
||||
cinfo->in_color_space == JCS_EXT_RGBA ||
|
||||
cinfo->in_color_space == JCS_EXT_BGRA ||
|
||||
cinfo->in_color_space == JCS_EXT_ABGR ||
|
||||
cinfo->in_color_space == JCS_EXT_ARGB)
|
||||
} else if (IsExtRGB(cinfo->in_color_space))
|
||||
cconvert->pub._color_convert = rgb_rgb_convert;
|
||||
else
|
||||
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
|
||||
break;
|
||||
|
||||
case JCS_YCbCr:
|
||||
if (cinfo->master->lossless &&
|
||||
cinfo->in_color_space != cinfo->jpeg_color_space)
|
||||
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
|
||||
if (cinfo->num_components != 3)
|
||||
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
|
||||
if (cinfo->in_color_space == JCS_RGB ||
|
||||
cinfo->in_color_space == JCS_EXT_RGB ||
|
||||
cinfo->in_color_space == JCS_EXT_RGBX ||
|
||||
cinfo->in_color_space == JCS_EXT_BGR ||
|
||||
cinfo->in_color_space == JCS_EXT_BGRX ||
|
||||
cinfo->in_color_space == JCS_EXT_XBGR ||
|
||||
cinfo->in_color_space == JCS_EXT_XRGB ||
|
||||
cinfo->in_color_space == JCS_EXT_RGBA ||
|
||||
cinfo->in_color_space == JCS_EXT_BGRA ||
|
||||
cinfo->in_color_space == JCS_EXT_ABGR ||
|
||||
cinfo->in_color_space == JCS_EXT_ARGB) {
|
||||
if (IsExtRGB(cinfo->in_color_space)) {
|
||||
#ifdef WITH_SIMD
|
||||
if (jsimd_can_rgb_ycc())
|
||||
cconvert->pub._color_convert = jsimd_rgb_ycc_convert;
|
||||
@@ -674,6 +655,9 @@ _jinit_color_converter(j_compress_ptr cinfo)
|
||||
break;
|
||||
|
||||
case JCS_CMYK:
|
||||
if (cinfo->master->lossless &&
|
||||
cinfo->in_color_space != cinfo->jpeg_color_space)
|
||||
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
|
||||
if (cinfo->num_components != 4)
|
||||
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
|
||||
if (cinfo->in_color_space == JCS_CMYK) {
|
||||
@@ -688,6 +672,9 @@ _jinit_color_converter(j_compress_ptr cinfo)
|
||||
break;
|
||||
|
||||
case JCS_YCCK:
|
||||
if (cinfo->master->lossless &&
|
||||
cinfo->in_color_space != cinfo->jpeg_color_space)
|
||||
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
|
||||
if (cinfo->num_components != 4)
|
||||
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
|
||||
if (cinfo->in_color_space == JCS_CMYK) {
|
||||
@@ -716,13 +703,4 @@ _jinit_color_converter(j_compress_ptr cinfo)
|
||||
cconvert->pub._color_convert = null_convert;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Prevent lossy color conversion in lossless mode */
|
||||
if (cinfo->master->lossless) {
|
||||
if ((cinfo->jpeg_color_space == JCS_GRAYSCALE &&
|
||||
cinfo->in_color_space != JCS_GRAYSCALE) ||
|
||||
(cinfo->jpeg_color_space != JCS_GRAYSCALE &&
|
||||
cconvert->pub._color_convert != null_convert))
|
||||
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
|
||||
}
|
||||
}
|
||||
|
||||
21
jdcolor.c
21
jdcolor.c
@@ -776,10 +776,15 @@ _jinit_color_deconverter(j_decompress_ptr cinfo)
|
||||
/* Set out_color_components and conversion method based on requested space.
|
||||
* Also clear the component_needed flags for any unused components,
|
||||
* so that earlier pipeline stages can avoid useless computation.
|
||||
* NOTE: We do not allow any lossy color conversion algorithms in lossless
|
||||
* mode.
|
||||
*/
|
||||
|
||||
switch (cinfo->out_color_space) {
|
||||
case JCS_GRAYSCALE:
|
||||
if (cinfo->master->lossless &&
|
||||
cinfo->jpeg_color_space != cinfo->out_color_space)
|
||||
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
|
||||
cinfo->out_color_components = 1;
|
||||
if (cinfo->jpeg_color_space == JCS_GRAYSCALE ||
|
||||
cinfo->jpeg_color_space == JCS_YCbCr) {
|
||||
@@ -805,6 +810,8 @@ _jinit_color_deconverter(j_decompress_ptr cinfo)
|
||||
case JCS_EXT_BGRA:
|
||||
case JCS_EXT_ABGR:
|
||||
case JCS_EXT_ARGB:
|
||||
if (cinfo->master->lossless && cinfo->jpeg_color_space != JCS_RGB)
|
||||
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
|
||||
cinfo->out_color_components = rgb_pixelsize[cinfo->out_color_space];
|
||||
if (cinfo->jpeg_color_space == JCS_YCbCr) {
|
||||
#ifdef WITH_SIMD
|
||||
@@ -831,6 +838,8 @@ _jinit_color_deconverter(j_decompress_ptr cinfo)
|
||||
break;
|
||||
|
||||
case JCS_RGB565:
|
||||
if (cinfo->master->lossless)
|
||||
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
|
||||
cinfo->out_color_components = 3;
|
||||
if (cinfo->dither_mode == JDITHER_NONE) {
|
||||
if (cinfo->jpeg_color_space == JCS_YCbCr) {
|
||||
@@ -864,6 +873,9 @@ _jinit_color_deconverter(j_decompress_ptr cinfo)
|
||||
break;
|
||||
|
||||
case JCS_CMYK:
|
||||
if (cinfo->master->lossless &&
|
||||
cinfo->jpeg_color_space != cinfo->out_color_space)
|
||||
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
|
||||
cinfo->out_color_components = 4;
|
||||
if (cinfo->jpeg_color_space == JCS_YCCK) {
|
||||
cconvert->pub._color_convert = ycck_cmyk_convert;
|
||||
@@ -884,15 +896,6 @@ _jinit_color_deconverter(j_decompress_ptr cinfo)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Prevent lossy color conversion in lossless mode */
|
||||
if (cinfo->master->lossless) {
|
||||
if ((cinfo->out_color_space == JCS_GRAYSCALE &&
|
||||
cinfo->jpeg_color_space != JCS_GRAYSCALE) ||
|
||||
(cinfo->out_color_space != JCS_GRAYSCALE &&
|
||||
cconvert->pub._color_convert != null_convert))
|
||||
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
|
||||
}
|
||||
|
||||
if (cinfo->quantize_colors)
|
||||
cinfo->output_components = 1; /* single colormapped output component */
|
||||
else
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* libjpeg-turbo Modifications:
|
||||
* Copyright (C) 2015-2016, 2019, 2021-2022, D. R. Commander.
|
||||
* Copyright (C) 2015-2017, 2019, 2021-2022, D. R. Commander.
|
||||
* Copyright (C) 2015, Google, Inc.
|
||||
* Copyright (C) 2021, Alex Richardson.
|
||||
* For conditions of distribution and use, see the accompanying README.ijg
|
||||
@@ -74,6 +74,9 @@ typedef __UINTPTR_TYPE__ JUINTPTR;
|
||||
typedef size_t JUINTPTR;
|
||||
#endif
|
||||
|
||||
#define IsExtRGB(cs) \
|
||||
(cs == JCS_RGB || (cs >= JCS_EXT_RGB && cs <= JCS_EXT_ARGB))
|
||||
|
||||
/*
|
||||
* Left shift macro that handles a negative operand without causing any
|
||||
* sanitizer warnings
|
||||
|
||||
@@ -1010,8 +1010,8 @@ jpeg_enable_lossless (j_compress_ptr cinfo, int predictor_selection_value,
|
||||
* DCT/IDCT algorithm selection
|
||||
* Smoothing
|
||||
* Downsampling/upsampling
|
||||
* Color conversion (the JPEG image will use the same color space as
|
||||
the input image)
|
||||
* Color space conversion (the JPEG image will use the same color
|
||||
space as the input image)
|
||||
* IDCT scaling
|
||||
* Raw (downsampled) data input/output
|
||||
* Transcoding of DCT coefficients
|
||||
|
||||
@@ -177,8 +177,8 @@ Switches for advanced users:
|
||||
following features will be unavailable when compressing
|
||||
or decompressing a lossless JPEG file:
|
||||
* Quality/quantization table selection
|
||||
* Color conversion (the JPEG image will use the same
|
||||
color space as the input image)
|
||||
* Color space conversion (the JPEG image will use the
|
||||
same color space as the input image)
|
||||
* DCT/IDCT algorithm selection
|
||||
* Smoothing
|
||||
* Downsampling/upsampling
|
||||
|
||||
Reference in New Issue
Block a user