Bug 1965813 - Add the possibility to decode cmyk jpeg images coming from pdf files r=aosmond,necko-reviewers,valentin

Differential Revision: https://phabricator.services.mozilla.com/D248887
This commit is contained in:
Calixte Denizet
2025-05-13 14:40:32 +00:00
committed by cdenizet@mozilla.com
parent 932b430977
commit 4d77a2923c
5 changed files with 27 additions and 11 deletions

View File

@@ -5,6 +5,7 @@
#include "DecoderFactory.h" #include "DecoderFactory.h"
#include "ImageUtils.h"
#include "nsMimeTypes.h" #include "nsMimeTypes.h"
#include "mozilla/RefPtr.h" #include "mozilla/RefPtr.h"
@@ -57,6 +58,8 @@ DecoderType DecoderFactory::GetDecoderType(const char* aMimeType) {
type = DecoderType::JPEG; type = DecoderType::JPEG;
} else if (!strcmp(aMimeType, IMAGE_JPG)) { } else if (!strcmp(aMimeType, IMAGE_JPG)) {
type = DecoderType::JPEG; type = DecoderType::JPEG;
} else if (!strcmp(aMimeType, IMAGE_JPEG_PDF)) {
type = DecoderType::JPEG_PDF;
// BMP // BMP
} else if (!strcmp(aMimeType, IMAGE_BMP)) { } else if (!strcmp(aMimeType, IMAGE_BMP)) {
@@ -131,10 +134,12 @@ already_AddRefed<Decoder> DecoderFactory::GetDecoder(DecoderType aType,
decoder = new nsGIFDecoder2(aImage); decoder = new nsGIFDecoder2(aImage);
break; break;
case DecoderType::JPEG: case DecoderType::JPEG:
case DecoderType::JPEG_PDF:
// If we have all the data we don't want to waste cpu time doing // If we have all the data we don't want to waste cpu time doing
// a progressive decode. // a progressive decode.
decoder = new nsJPEGDecoder( decoder = new nsJPEGDecoder(
aImage, aIsRedecode ? Decoder::SEQUENTIAL : Decoder::PROGRESSIVE); aImage, aIsRedecode ? Decoder::SEQUENTIAL : Decoder::PROGRESSIVE,
aType == DecoderType::JPEG_PDF);
break; break;
case DecoderType::BMP: case DecoderType::BMP:
decoder = new nsBMPDecoder(aImage); decoder = new nsBMPDecoder(aImage);

View File

@@ -37,6 +37,7 @@ enum class DecoderType {
PNG, PNG,
GIF, GIF,
JPEG, JPEG,
JPEG_PDF,
BMP, BMP,
BMP_CLIPBOARD, BMP_CLIPBOARD,
ICO, ICO,

View File

@@ -36,7 +36,7 @@ extern "C" {
#endif #endif
static void cmyk_convert_bgra(uint32_t* aInput, uint32_t* aOutput, static void cmyk_convert_bgra(uint32_t* aInput, uint32_t* aOutput,
int32_t aWidth); int32_t aWidth, bool aIsInverted);
using mozilla::gfx::SurfaceFormat; using mozilla::gfx::SurfaceFormat;
@@ -72,7 +72,7 @@ METHODDEF(void) progress_monitor(j_common_ptr info);
#define MAX_JPEG_MARKER_LENGTH (((uint32_t)1 << 16) - 1) #define MAX_JPEG_MARKER_LENGTH (((uint32_t)1 << 16) - 1)
nsJPEGDecoder::nsJPEGDecoder(RasterImage* aImage, nsJPEGDecoder::nsJPEGDecoder(RasterImage* aImage,
Decoder::DecodeStyle aDecodeStyle) Decoder::DecodeStyle aDecodeStyle, bool aIsPDF)
: Decoder(aImage), : Decoder(aImage),
mLexer(Transition::ToUnbuffered(State::FINISHED_JPEG_DATA, mLexer(Transition::ToUnbuffered(State::FINISHED_JPEG_DATA,
State::JPEG_DATA, SIZE_MAX), State::JPEG_DATA, SIZE_MAX),
@@ -80,7 +80,8 @@ nsJPEGDecoder::nsJPEGDecoder(RasterImage* aImage,
mProfile(nullptr), mProfile(nullptr),
mProfileLength(0), mProfileLength(0),
mCMSLine(nullptr), mCMSLine(nullptr),
mDecodeStyle(aDecodeStyle) { mDecodeStyle(aDecodeStyle),
mIsPDF(aIsPDF) {
this->mErr.pub.error_exit = nullptr; this->mErr.pub.error_exit = nullptr;
this->mErr.pub.emit_message = nullptr; this->mErr.pub.emit_message = nullptr;
this->mErr.pub.output_message = nullptr; this->mErr.pub.output_message = nullptr;
@@ -692,7 +693,7 @@ WriteState nsJPEGDecoder::OutputScanlines() {
case JCS_CMYK: case JCS_CMYK:
// Convert from CMYK to BGRA // Convert from CMYK to BGRA
MOZ_ASSERT(mCMSLine); MOZ_ASSERT(mCMSLine);
cmyk_convert_bgra(mCMSLine, aPixelBlock, aBlockSize); cmyk_convert_bgra(mCMSLine, aPixelBlock, aBlockSize, mIsPDF);
break; break;
} }
@@ -961,7 +962,7 @@ term_source(j_decompress_ptr jd) {
/// @param aOutput Points to row buffer to write BGRA to. /// @param aOutput Points to row buffer to write BGRA to.
/// @param aWidth Number of pixels in the row. /// @param aWidth Number of pixels in the row.
static void cmyk_convert_bgra(uint32_t* aInput, uint32_t* aOutput, static void cmyk_convert_bgra(uint32_t* aInput, uint32_t* aOutput,
int32_t aWidth) { int32_t aWidth, bool aIsInverted) {
uint8_t* input = reinterpret_cast<uint8_t*>(aInput); uint8_t* input = reinterpret_cast<uint8_t*>(aInput);
for (int32_t i = 0; i < aWidth; ++i) { for (int32_t i = 0; i < aWidth; ++i) {
@@ -984,10 +985,16 @@ static void cmyk_convert_bgra(uint32_t* aInput, uint32_t* aOutput,
// B = 1 - Y => 1 - (1 - iY*iK) => iY*iK // B = 1 - Y => 1 - (1 - iY*iK) => iY*iK
// Convert from Inverted CMYK (0..255) to RGB (0..255) // Convert from Inverted CMYK (0..255) to RGB (0..255)
const uint32_t iC = input[0]; uint32_t iC = input[0];
const uint32_t iM = input[1]; uint32_t iM = input[1];
const uint32_t iY = input[2]; uint32_t iY = input[2];
const uint32_t iK = input[3]; uint32_t iK = input[3];
if (MOZ_UNLIKELY(aIsInverted)) {
iC = 255 - iC;
iM = 255 - iM;
iY = 255 - iY;
iK = 255 - iK;
}
const uint8_t r = iC * iK / 255; const uint8_t r = iC * iK / 255;
const uint8_t g = iM * iK / 255; const uint8_t g = iM * iK / 255;

View File

@@ -69,7 +69,8 @@ class nsJPEGDecoder : public Decoder {
friend class DecoderFactory; friend class DecoderFactory;
// Decoders should only be instantiated via DecoderFactory. // Decoders should only be instantiated via DecoderFactory.
nsJPEGDecoder(RasterImage* aImage, Decoder::DecodeStyle aDecodeStyle); nsJPEGDecoder(RasterImage* aImage, Decoder::DecodeStyle aDecodeStyle,
bool aIsPDF = false);
enum class State { JPEG_DATA, FINISHED_JPEG_DATA }; enum class State { JPEG_DATA, FINISHED_JPEG_DATA };
@@ -104,6 +105,7 @@ class nsJPEGDecoder : public Decoder {
bool mReading; bool mReading;
const Decoder::DecodeStyle mDecodeStyle; const Decoder::DecodeStyle mDecodeStyle;
bool mIsPDF;
SurfacePipe mPipe; SurfacePipe mPipe;
}; };

View File

@@ -141,6 +141,7 @@
#define IMAGE_JPEG "image/jpeg" #define IMAGE_JPEG "image/jpeg"
#define IMAGE_JPG "image/jpg" #define IMAGE_JPG "image/jpg"
#define IMAGE_PJPEG "image/pjpeg" #define IMAGE_PJPEG "image/pjpeg"
#define IMAGE_JPEG_PDF "image/x-jpeg-pdf"
#define IMAGE_PNG "image/png" #define IMAGE_PNG "image/png"
#define IMAGE_APNG "image/apng" #define IMAGE_APNG "image/apng"
#define IMAGE_X_PNG "image/x-png" #define IMAGE_X_PNG "image/x-png"