void createColorTransform(const ColorProfile& colorProfile, bool hasAlpha, bool sRGB) { clearColorTransform(); if (colorProfile.isEmpty() && !sRGB) return; qcms_profile* deviceProfile = ImageDecoder::qcmsOutputDeviceProfile(); if (!deviceProfile) return; qcms_profile* inputProfile = 0; if (!colorProfile.isEmpty()) inputProfile = qcms_profile_from_memory(colorProfile.data(), colorProfile.size()); else inputProfile = qcms_profile_sRGB(); if (!inputProfile) return; // We currently only support color profiles for RGB and RGBA images. ASSERT(rgbData == qcms_profile_get_color_space(inputProfile)); if (qcms_profile_match(inputProfile, deviceProfile)) { qcms_profile_release(inputProfile); return; } // FIXME: Don't force perceptual intent if the image profile contains an intent. qcms_data_type dataFormat = hasAlpha ? QCMS_DATA_RGBA_8 : QCMS_DATA_RGB_8; m_transform = qcms_transform_create(inputProfile, dataFormat, deviceProfile, dataFormat, QCMS_INTENT_PERCEPTUAL); qcms_profile_release(inputProfile); }
TESTFUNC_TYPE LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { qcms_enable_iccv4(); qcms_profile* profile = qcms_profile_from_memory(data, size); if (!profile) { return 0; } qcms_profile* srgb_profile = qcms_profile_sRGB(); if (!srgb_profile) { qcms_profile_release(profile); return 0; } transform(profile, srgb_profile, size); // Firefox only checks the display (destination) profile. if (qcms_profile_is_bogus(profile)) { goto release_profiles; }; transform(srgb_profile, profile, size); release_profiles: qcms_profile_release(profile); qcms_profile_release(srgb_profile); return 0; }
/* Shuts down various transforms and profiles for CMS. */ static void ShutdownCMS() { if (gCMSRGBTransform) { qcms_transform_release(gCMSRGBTransform); gCMSRGBTransform = nsnull; } if (gCMSInverseRGBTransform) { qcms_transform_release(gCMSInverseRGBTransform); gCMSInverseRGBTransform = nsnull; } if (gCMSRGBATransform) { qcms_transform_release(gCMSRGBATransform); gCMSRGBATransform = nsnull; } if (gCMSOutputProfile) { qcms_profile_release(gCMSOutputProfile); // handle the aliased case if (gCMSsRGBProfile == gCMSOutputProfile) gCMSsRGBProfile = nsnull; gCMSOutputProfile = nsnull; } if (gCMSsRGBProfile) { qcms_profile_release(gCMSsRGBProfile); gCMSsRGBProfile = nsnull; } // Reset the state variables gCMSIntent = -2; gCMSMode = eCMSMode_Off; gCMSInitialized = PR_FALSE; }
// ----------------------------------------------------------------------------- // Color profile handling static int ApplyColorProfile(const WebPData* const profile, WebPDecBuffer* const rgba) { #ifdef WEBP_HAVE_QCMS int i, ok = 0; uint8_t* line; uint8_t major_revision; qcms_profile* input_profile = NULL; qcms_profile* output_profile = NULL; qcms_transform* transform = NULL; const qcms_data_type input_type = QCMS_DATA_RGBA_8; const qcms_data_type output_type = QCMS_DATA_RGBA_8; const qcms_intent intent = QCMS_INTENT_DEFAULT; if (profile == NULL || rgba == NULL) return 0; if (profile->bytes == NULL || profile->size < 10) return 1; major_revision = profile->bytes[8]; qcms_enable_iccv4(); input_profile = qcms_profile_from_memory(profile->bytes, profile->size); // qcms_profile_is_bogus() is broken with ICCv4. if (input_profile == NULL || (major_revision < 4 && qcms_profile_is_bogus(input_profile))) { fprintf(stderr, "Color profile is bogus!\n"); goto Error; } output_profile = qcms_profile_sRGB(); if (output_profile == NULL) { fprintf(stderr, "Error creating output color profile!\n"); goto Error; } qcms_profile_precache_output_transform(output_profile); transform = qcms_transform_create(input_profile, input_type, output_profile, output_type, intent); if (transform == NULL) { fprintf(stderr, "Error creating color transform!\n"); goto Error; } line = rgba->u.RGBA.rgba; for (i = 0; i < rgba->height; ++i, line += rgba->u.RGBA.stride) { qcms_transform_data(transform, line, line, rgba->width); } ok = 1; Error: if (input_profile != NULL) qcms_profile_release(input_profile); if (output_profile != NULL) qcms_profile_release(output_profile); if (transform != NULL) qcms_transform_release(transform); return ok; #else (void)profile; (void)rgba; return 1; #endif // WEBP_HAVE_QCMS }
qcms_profile * gfxPlatform::GetCMSOutputProfile() { if (!gCMSOutputProfile) { NS_TIME_FUNCTION; nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID); if (prefs) { nsresult rv; /* Determine if we're using the internal override to force sRGB as an output profile for reftests. See Bug 452125. Note that we don't normally (outside of tests) set a default value of this preference, which means GetBoolPref will typically throw (and leave its out-param untouched). */ PRBool doSRGBOverride; rv = prefs->GetBoolPref(CMForceSRGBPrefName, &doSRGBOverride); if (NS_SUCCEEDED(rv) && doSRGBOverride) gCMSOutputProfile = GetCMSsRGBProfile(); if (!gCMSOutputProfile) { nsXPIDLCString fname; rv = prefs->GetCharPref(CMProfilePrefName, getter_Copies(fname)); if (NS_SUCCEEDED(rv) && !fname.IsEmpty()) { gCMSOutputProfile = qcms_profile_from_path(fname); } } } if (!gCMSOutputProfile) { gCMSOutputProfile = gfxPlatform::GetPlatform()->GetPlatformCMSOutputProfile(); } /* Determine if the profile looks bogus. If so, close the profile * and use sRGB instead. See bug 460629, */ if (gCMSOutputProfile && qcms_profile_is_bogus(gCMSOutputProfile)) { NS_ASSERTION(gCMSOutputProfile != GetCMSsRGBProfile(), "Builtin sRGB profile tagged as bogus!!!"); qcms_profile_release(gCMSOutputProfile); gCMSOutputProfile = nsnull; } if (!gCMSOutputProfile) { gCMSOutputProfile = GetCMSsRGBProfile(); } /* Precache the LUT16 Interpolations for the output profile. See bug 444661 for details. */ qcms_profile_precache_output_transform(gCMSOutputProfile); } return gCMSOutputProfile; }
void do_test(void) { unsigned char srct[4] = { 221, 79, 129, 92}; unsigned char outt[4]; qcms_transform *transform; qcms_profile *input_profile, *output_profile, *rgb; qcms_CIE_xyY white_point = { 0, 0, 1.}; qcms_CIE_xyYTRIPLE primaries = { {.9, .3, 1.}, {.2, .4, 1.}, {.7, .4, 1.}}; rgb = qcms_profile_create_rgb_with_gamma(white_point, primaries, 1.8); input_profile = qcms_profile_sRGB(); output_profile = qcms_profile_sRGB(); if (output_profile) { test_gray(output_profile); test_gray_precache(output_profile); qcms_profile_release(output_profile); } if (input_profile) qcms_profile_release(input_profile); if (rgb) qcms_profile_release(rgb); rgb = qcms_profile_from_path("sample-trunc.icc"); if (rgb) qcms_profile_release(rgb); }
nsJPEGDecoder::~nsJPEGDecoder() { // Step 8: Release JPEG decompression object mInfo.src = nullptr; jpeg_destroy_decompress(&mInfo); PR_FREEIF(mBackBuffer); if (mTransform) qcms_transform_release(mTransform); if (mInProfile) qcms_profile_release(mInProfile); PR_LOG(gJPEGDecoderAccountingLog, PR_LOG_DEBUG, ("nsJPEGDecoder::~nsJPEGDecoder: Destroying JPEG decoder %p", this)); }
void test_gray(qcms_profile *output_profile) { unsigned char srct[3] = { 221, 79, 129}; unsigned char outt[3]; qcms_transform *transform; qcms_profile *gray_profile = qcms_profile_from_memory(gray_icc, sizeof(gray_icc)); if (gray_profile) { transform = qcms_transform_create(gray_profile, QCMS_DATA_GRAY_8, output_profile, QCMS_DATA_RGB_8, QCMS_INTENT_PERCEPTUAL); if (transform) { qcms_transform_data(transform, srct, outt, 1); qcms_transform_release(transform); } qcms_profile_release(gray_profile); } }
nsPNGDecoder::~nsPNGDecoder() { if (mPNG) png_destroy_read_struct(&mPNG, mInfo ? &mInfo : nullptr, nullptr); if (mCMSLine) nsMemory::Free(mCMSLine); if (interlacebuf) nsMemory::Free(interlacebuf); if (mInProfile) { qcms_profile_release(mInProfile); /* mTransform belongs to us only if mInProfile is non-null */ if (mTransform) qcms_transform_release(mTransform); } }
nsPNGDecoder::~nsPNGDecoder() { if (mPNG) { png_destroy_read_struct(&mPNG, mInfo ? &mInfo : nullptr, nullptr); } if (mCMSLine) { free(mCMSLine); } if (interlacebuf) { free(interlacebuf); } if (mInProfile) { qcms_profile_release(mInProfile); // mTransform belongs to us only if mInProfile is non-null if (mTransform) { qcms_transform_release(mTransform); } } }
void createColorTransform(const ColorProfile& colorProfile, bool hasAlpha) { if (m_transform) qcms_transform_release(m_transform); m_transform = 0; if (colorProfile.isEmpty()) return; qcms_profile* deviceProfile = ImageDecoder::qcmsOutputDeviceProfile(); if (!deviceProfile) return; qcms_profile* inputProfile = qcms_profile_from_memory(colorProfile.data(), colorProfile.size()); if (!inputProfile) return; // We currently only support color profiles for RGB profiled images. ASSERT(icSigRgbData == qcms_profile_get_color_space(inputProfile)); qcms_data_type dataFormat = hasAlpha ? QCMS_DATA_RGBA_8 : QCMS_DATA_RGB_8; // FIXME: Don't force perceptual intent if the image profile contains an intent. m_transform = qcms_transform_create(inputProfile, dataFormat, deviceProfile, dataFormat, QCMS_INTENT_PERCEPTUAL); qcms_profile_release(inputProfile); }
bool WEBPImageDecoder::createColorTransform(const char* data, size_t size) { clearColorTransform(); qcms_profile* deviceProfile = ImageDecoder::qcmsOutputDeviceProfile(); if (!deviceProfile) return false; qcms_profile* inputProfile = qcms_profile_from_memory(data, size); if (!inputProfile) return false; // We currently only support color profiles for RGB profiled images. ASSERT(icSigRgbData == qcms_profile_get_color_space(inputProfile)); // The input image pixels are RGBA format. qcms_data_type format = QCMS_DATA_RGBA_8; // FIXME: Don't force perceptual intent if the image profile contains an intent. m_transform = qcms_transform_create(inputProfile, format, deviceProfile, QCMS_DATA_RGBA_8, QCMS_INTENT_PERCEPTUAL); qcms_profile_release(inputProfile); return !!m_transform; }
static int qcms_test_internal_srgb(size_t width, size_t height, int iterations, const char *in_path, const char *out_path, const int force_software) { qcms_profile *profile = qcms_profile_sRGB(); s15Fixed16Number sRGB_internal[3][3]; s15Fixed16Number diff = 0; int i, j; printf("Test qcms internal sRGB colorant matrix against official sRGB IEC61966-2.1 color (D50) primaries\n"); sRGB_internal[0][0] = profile->redColorant.X; sRGB_internal[1][0] = profile->redColorant.Y; sRGB_internal[2][0] = profile->redColorant.Z; sRGB_internal[0][1] = profile->greenColorant.X; sRGB_internal[1][1] = profile->greenColorant.Y; sRGB_internal[2][1] = profile->greenColorant.Z; sRGB_internal[0][2] = profile->blueColorant.X; sRGB_internal[1][2] = profile->blueColorant.Y; sRGB_internal[2][2] = profile->blueColorant.Z; for (i = 0; i < 3; i++) { for (j = 0; j < 3; j++) { s15Fixed16Number tmp = sRGB_internal[i][j] - sRGB_reference[i][j]; printf("\t%d", tmp); diff += abs(tmp); } printf("\n"); } qcms_profile_release(profile); printf("Total error = 0x%x [%.6f]\n", diff, diff / 65536.0); return diff; }
// Adapted from http://www.littlecms.com/pngchrm.c example code static qcms_profile* PNGGetColorProfile(png_structp png_ptr, png_infop info_ptr, int color_type, qcms_data_type* inType, uint32_t* intent) { qcms_profile* profile = nullptr; *intent = QCMS_INTENT_PERCEPTUAL; // Our default // First try to see if iCCP chunk is present if (png_get_valid(png_ptr, info_ptr, PNG_INFO_iCCP)) { png_uint_32 profileLen; png_bytep profileData; png_charp profileName; int compression; png_get_iCCP(png_ptr, info_ptr, &profileName, &compression, &profileData, &profileLen); profile = qcms_profile_from_memory((char*)profileData, profileLen); if (profile) { uint32_t profileSpace = qcms_profile_get_color_space(profile); bool mismatch = false; if (color_type & PNG_COLOR_MASK_COLOR) { if (profileSpace != icSigRgbData) { mismatch = true; } } else { if (profileSpace == icSigRgbData) { png_set_gray_to_rgb(png_ptr); } else if (profileSpace != icSigGrayData) { mismatch = true; } } if (mismatch) { qcms_profile_release(profile); profile = nullptr; } else { *intent = qcms_profile_get_rendering_intent(profile); } } } // Check sRGB chunk if (!profile && png_get_valid(png_ptr, info_ptr, PNG_INFO_sRGB)) { profile = qcms_profile_sRGB(); if (profile) { int fileIntent; png_set_gray_to_rgb(png_ptr); png_get_sRGB(png_ptr, info_ptr, &fileIntent); uint32_t map[] = { QCMS_INTENT_PERCEPTUAL, QCMS_INTENT_RELATIVE_COLORIMETRIC, QCMS_INTENT_SATURATION, QCMS_INTENT_ABSOLUTE_COLORIMETRIC }; *intent = map[fileIntent]; } } // Check gAMA/cHRM chunks if (!profile && png_get_valid(png_ptr, info_ptr, PNG_INFO_gAMA) && png_get_valid(png_ptr, info_ptr, PNG_INFO_cHRM)) { qcms_CIE_xyYTRIPLE primaries; qcms_CIE_xyY whitePoint; png_get_cHRM(png_ptr, info_ptr, &whitePoint.x, &whitePoint.y, &primaries.red.x, &primaries.red.y, &primaries.green.x, &primaries.green.y, &primaries.blue.x, &primaries.blue.y); whitePoint.Y = primaries.red.Y = primaries.green.Y = primaries.blue.Y = 1.0; double gammaOfFile; png_get_gAMA(png_ptr, info_ptr, &gammaOfFile); profile = qcms_profile_create_rgb_with_gamma(whitePoint, primaries, 1.0/gammaOfFile); if (profile) { png_set_gray_to_rgb(png_ptr); } } if (profile) { uint32_t profileSpace = qcms_profile_get_color_space(profile); if (profileSpace == icSigGrayData) { if (color_type & PNG_COLOR_MASK_ALPHA) { *inType = QCMS_DATA_GRAYA_8; } else { *inType = QCMS_DATA_GRAY_8; } } else { if (color_type & PNG_COLOR_MASK_ALPHA || png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { *inType = QCMS_DATA_RGBA_8; } else { *inType = QCMS_DATA_RGB_8; } } } return profile; }