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
|
#ifndef EXIT_WARNING
|
||||||
#define EXIT_WARNING 2
|
#define EXIT_WARNING 2
|
||||||
#endif
|
#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
|
.SH NAME
|
||||||
cjpeg \- compress an image file to a JPEG file
|
cjpeg \- compress an image file to a JPEG file
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@@ -176,8 +176,8 @@ unavailable when compressing or decompressing a lossless JPEG file:
|
|||||||
.IP
|
.IP
|
||||||
- Quality/quantization table selection
|
- Quality/quantization table selection
|
||||||
.IP
|
.IP
|
||||||
- Color conversion (the JPEG image will use the same color space as the input
|
- Color space conversion (the JPEG image will use the same color space as the
|
||||||
image)
|
input image)
|
||||||
.IP
|
.IP
|
||||||
- DCT/IDCT algorithm selection
|
- DCT/IDCT algorithm selection
|
||||||
.IP
|
.IP
|
||||||
|
|||||||
64
jccolor.c
64
jccolor.c
@@ -577,24 +577,20 @@ _jinit_color_converter(j_compress_ptr cinfo)
|
|||||||
break;
|
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) {
|
switch (cinfo->jpeg_color_space) {
|
||||||
case JCS_GRAYSCALE:
|
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)
|
if (cinfo->num_components != 1)
|
||||||
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
|
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
|
||||||
if (cinfo->in_color_space == JCS_GRAYSCALE)
|
if (cinfo->in_color_space == JCS_GRAYSCALE)
|
||||||
cconvert->pub._color_convert = grayscale_convert;
|
cconvert->pub._color_convert = grayscale_convert;
|
||||||
else if (cinfo->in_color_space == JCS_RGB ||
|
else if (IsExtRGB(cinfo->in_color_space)) {
|
||||||
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) {
|
|
||||||
#ifdef WITH_SIMD
|
#ifdef WITH_SIMD
|
||||||
if (jsimd_can_rgb_gray())
|
if (jsimd_can_rgb_gray())
|
||||||
cconvert->pub._color_convert = jsimd_rgb_gray_convert;
|
cconvert->pub._color_convert = jsimd_rgb_gray_convert;
|
||||||
@@ -611,6 +607,8 @@ _jinit_color_converter(j_compress_ptr cinfo)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case JCS_RGB:
|
case JCS_RGB:
|
||||||
|
if (cinfo->master->lossless && !IsExtRGB(cinfo->in_color_space))
|
||||||
|
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
|
||||||
if (cinfo->num_components != 3)
|
if (cinfo->num_components != 3)
|
||||||
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
|
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
|
||||||
if (rgb_red[cinfo->in_color_space] == 0 &&
|
if (rgb_red[cinfo->in_color_space] == 0 &&
|
||||||
@@ -623,36 +621,19 @@ _jinit_color_converter(j_compress_ptr cinfo)
|
|||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
cconvert->pub._color_convert = null_convert;
|
cconvert->pub._color_convert = null_convert;
|
||||||
} else if (cinfo->in_color_space == JCS_RGB ||
|
} else if (IsExtRGB(cinfo->in_color_space))
|
||||||
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)
|
|
||||||
cconvert->pub._color_convert = rgb_rgb_convert;
|
cconvert->pub._color_convert = rgb_rgb_convert;
|
||||||
else
|
else
|
||||||
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
|
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case JCS_YCbCr:
|
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)
|
if (cinfo->num_components != 3)
|
||||||
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
|
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
|
||||||
if (cinfo->in_color_space == JCS_RGB ||
|
if (IsExtRGB(cinfo->in_color_space)) {
|
||||||
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) {
|
|
||||||
#ifdef WITH_SIMD
|
#ifdef WITH_SIMD
|
||||||
if (jsimd_can_rgb_ycc())
|
if (jsimd_can_rgb_ycc())
|
||||||
cconvert->pub._color_convert = jsimd_rgb_ycc_convert;
|
cconvert->pub._color_convert = jsimd_rgb_ycc_convert;
|
||||||
@@ -674,6 +655,9 @@ _jinit_color_converter(j_compress_ptr cinfo)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case JCS_CMYK:
|
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)
|
if (cinfo->num_components != 4)
|
||||||
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
|
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
|
||||||
if (cinfo->in_color_space == JCS_CMYK) {
|
if (cinfo->in_color_space == JCS_CMYK) {
|
||||||
@@ -688,6 +672,9 @@ _jinit_color_converter(j_compress_ptr cinfo)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case JCS_YCCK:
|
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)
|
if (cinfo->num_components != 4)
|
||||||
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
|
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
|
||||||
if (cinfo->in_color_space == JCS_CMYK) {
|
if (cinfo->in_color_space == JCS_CMYK) {
|
||||||
@@ -716,13 +703,4 @@ _jinit_color_converter(j_compress_ptr cinfo)
|
|||||||
cconvert->pub._color_convert = null_convert;
|
cconvert->pub._color_convert = null_convert;
|
||||||
break;
|
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.
|
/* Set out_color_components and conversion method based on requested space.
|
||||||
* Also clear the component_needed flags for any unused components,
|
* Also clear the component_needed flags for any unused components,
|
||||||
* so that earlier pipeline stages can avoid useless computation.
|
* 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) {
|
switch (cinfo->out_color_space) {
|
||||||
case JCS_GRAYSCALE:
|
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;
|
cinfo->out_color_components = 1;
|
||||||
if (cinfo->jpeg_color_space == JCS_GRAYSCALE ||
|
if (cinfo->jpeg_color_space == JCS_GRAYSCALE ||
|
||||||
cinfo->jpeg_color_space == JCS_YCbCr) {
|
cinfo->jpeg_color_space == JCS_YCbCr) {
|
||||||
@@ -805,6 +810,8 @@ _jinit_color_deconverter(j_decompress_ptr cinfo)
|
|||||||
case JCS_EXT_BGRA:
|
case JCS_EXT_BGRA:
|
||||||
case JCS_EXT_ABGR:
|
case JCS_EXT_ABGR:
|
||||||
case JCS_EXT_ARGB:
|
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];
|
cinfo->out_color_components = rgb_pixelsize[cinfo->out_color_space];
|
||||||
if (cinfo->jpeg_color_space == JCS_YCbCr) {
|
if (cinfo->jpeg_color_space == JCS_YCbCr) {
|
||||||
#ifdef WITH_SIMD
|
#ifdef WITH_SIMD
|
||||||
@@ -831,6 +838,8 @@ _jinit_color_deconverter(j_decompress_ptr cinfo)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case JCS_RGB565:
|
case JCS_RGB565:
|
||||||
|
if (cinfo->master->lossless)
|
||||||
|
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
|
||||||
cinfo->out_color_components = 3;
|
cinfo->out_color_components = 3;
|
||||||
if (cinfo->dither_mode == JDITHER_NONE) {
|
if (cinfo->dither_mode == JDITHER_NONE) {
|
||||||
if (cinfo->jpeg_color_space == JCS_YCbCr) {
|
if (cinfo->jpeg_color_space == JCS_YCbCr) {
|
||||||
@@ -864,6 +873,9 @@ _jinit_color_deconverter(j_decompress_ptr cinfo)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case JCS_CMYK:
|
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;
|
cinfo->out_color_components = 4;
|
||||||
if (cinfo->jpeg_color_space == JCS_YCCK) {
|
if (cinfo->jpeg_color_space == JCS_YCCK) {
|
||||||
cconvert->pub._color_convert = ycck_cmyk_convert;
|
cconvert->pub._color_convert = ycck_cmyk_convert;
|
||||||
@@ -884,15 +896,6 @@ _jinit_color_deconverter(j_decompress_ptr cinfo)
|
|||||||
break;
|
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)
|
if (cinfo->quantize_colors)
|
||||||
cinfo->output_components = 1; /* single colormapped output component */
|
cinfo->output_components = 1; /* single colormapped output component */
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
* Lossless JPEG Modifications:
|
* Lossless JPEG Modifications:
|
||||||
* Copyright (C) 1999, Ken Murchison.
|
* Copyright (C) 1999, Ken Murchison.
|
||||||
* libjpeg-turbo Modifications:
|
* 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) 2015, Google, Inc.
|
||||||
* Copyright (C) 2021, Alex Richardson.
|
* Copyright (C) 2021, Alex Richardson.
|
||||||
* For conditions of distribution and use, see the accompanying README.ijg
|
* For conditions of distribution and use, see the accompanying README.ijg
|
||||||
@@ -74,6 +74,9 @@ typedef __UINTPTR_TYPE__ JUINTPTR;
|
|||||||
typedef size_t JUINTPTR;
|
typedef size_t JUINTPTR;
|
||||||
#endif
|
#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
|
* Left shift macro that handles a negative operand without causing any
|
||||||
* sanitizer warnings
|
* sanitizer warnings
|
||||||
|
|||||||
@@ -1010,8 +1010,8 @@ jpeg_enable_lossless (j_compress_ptr cinfo, int predictor_selection_value,
|
|||||||
* DCT/IDCT algorithm selection
|
* DCT/IDCT algorithm selection
|
||||||
* Smoothing
|
* Smoothing
|
||||||
* Downsampling/upsampling
|
* Downsampling/upsampling
|
||||||
* Color conversion (the JPEG image will use the same color space as
|
* Color space conversion (the JPEG image will use the same color
|
||||||
the input image)
|
space as the input image)
|
||||||
* IDCT scaling
|
* IDCT scaling
|
||||||
* Raw (downsampled) data input/output
|
* Raw (downsampled) data input/output
|
||||||
* Transcoding of DCT coefficients
|
* Transcoding of DCT coefficients
|
||||||
|
|||||||
@@ -177,8 +177,8 @@ Switches for advanced users:
|
|||||||
following features will be unavailable when compressing
|
following features will be unavailable when compressing
|
||||||
or decompressing a lossless JPEG file:
|
or decompressing a lossless JPEG file:
|
||||||
* Quality/quantization table selection
|
* Quality/quantization table selection
|
||||||
* Color conversion (the JPEG image will use the same
|
* Color space conversion (the JPEG image will use the
|
||||||
color space as the input image)
|
same color space as the input image)
|
||||||
* DCT/IDCT algorithm selection
|
* DCT/IDCT algorithm selection
|
||||||
* Smoothing
|
* Smoothing
|
||||||
* Downsampling/upsampling
|
* Downsampling/upsampling
|
||||||
|
|||||||
Reference in New Issue
Block a user