void ColorCodecBench::onDelayedSetup() { SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(fEncoded)); fSrcData = codec->getICCData(); sk_sp<SkData> dstData = SkData::MakeFromFileName( GetResourcePath("icc_profiles/HP_ZR30w.icc").c_str()); SkASSERT(dstData); fDstSpace = nullptr; #if defined(SK_TEST_QCMS) if (FLAGS_qcms) { fDstSpaceQCMS.reset(FLAGS_srgb ? qcms_profile_sRGB() : qcms_profile_from_memory(dstData->data(), dstData->size())); SkASSERT(fDstSpaceQCMS); // This call takes a non-trivial amount of time, but I think it's the most fair to // treat it as overhead. It only needs to happen once. qcms_profile_precache_output_transform(fDstSpaceQCMS); } else #endif { fDstSpace = FLAGS_srgb ? SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named) : SkColorSpace::MakeICC(dstData->data(), dstData->size()); SkASSERT(fDstSpace); } fSrcInfo = codec->getInfo().makeColorType(kRGBA_8888_SkColorType); fDstInfo = fSrcInfo; if (FLAGS_half) { fDstInfo = fDstInfo.makeColorType(kRGBA_F16_SkColorType); SkASSERT(SkColorSpace_Base::Type::kXYZ == as_CSB(fDstSpace)->type()); fDstSpace = static_cast<SkColorSpace_XYZ*>(fDstSpace.get())->makeLinearGamma(); } if (FLAGS_nonstd) { SkColorSpaceTransferFn gamma; gamma.fA = 1.0f; gamma.fB = gamma.fC = gamma.fD = gamma.fE = gamma.fF = 0.0f; gamma.fG = 4.0f; SkMatrix44 matrix = SkMatrix44(SkMatrix44::kUninitialized_Constructor); matrix.set3x3(0.30f, 0.31f, 0.28f, 0.32f, 0.33f, 0.29f, 0.27f, 0.30f, 0.30f); fDstSpace = SkColorSpace::MakeRGB(gamma, matrix); } fDstInfo = fDstInfo.makeColorSpace(fDstSpace); fDst.reset(fDstInfo.getSafeSize(fDstInfo.minRowBytes())); if (FLAGS_xform_only) { fSrc.reset(fSrcInfo.getSafeSize(fSrcInfo.minRowBytes())); codec->getPixels(fSrcInfo, fSrc.get(), fSrcInfo.minRowBytes()); } #if defined(SK_TEST_QCMS) else if (FLAGS_qcms) { // Set-up a row buffer to decode into before transforming to dst. fSrc.reset(fSrcInfo.minRowBytes()); } #endif }
// ----------------------------------------------------------------------------- // 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; }
static void transform(qcms_profile* src_profile, qcms_profile* dst_profile, size_t size) { // qcms supports GRAY and RGB profiles as input, and RGB as output. uint32_t src_color_space = qcms_profile_get_color_space(src_profile); qcms_data_type src_type = size & 1 ? QCMS_DATA_RGBA_8 : QCMS_DATA_RGB_8; if (src_color_space == icSigGrayData) { src_type = size & 1 ? QCMS_DATA_GRAYA_8 : QCMS_DATA_GRAY_8; } else if (src_color_space != icSigRgbData) { return; } uint32_t dst_color_space = qcms_profile_get_color_space(dst_profile); if (dst_color_space != icSigRgbData) { return; } qcms_data_type dst_type = size & 2 ? QCMS_DATA_RGBA_8 : QCMS_DATA_RGB_8; qcms_intent intent = qcms_profile_get_rendering_intent(src_profile); // Firefox calls this on the display profile to increase performance. // Skip with low probability to increase coverage. if (size % 15) { qcms_profile_precache_output_transform(dst_profile); } qcms_transform* transform = qcms_transform_create(src_profile, src_type, dst_profile, dst_type, intent); if (!transform) { return; } static uint8_t src[] = { 0x7F, 0x7F, 0x7F, 0x00, 0x00, 0x7F, 0x7F, 0xFF, 0x7F, 0x10, 0x20, 0x30, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xB0, 0xBF, 0xEF, 0x6F, 0x3F, 0xC0, 0x9F, 0xE0, 0x90, 0xCF, 0x40, 0xAF, 0x0F, 0x01, 0x60, 0xF0, }; static uint8_t dst[sizeof(src) * 4]; // 4x in case of GRAY to RGBA int src_bytes_per_pixel = 4; // QCMS_DATA_RGBA_8 if (src_type == QCMS_DATA_RGB_8) { src_bytes_per_pixel = 3; } else if (src_type == QCMS_DATA_GRAYA_8) { src_bytes_per_pixel = 2; } else if (src_type == QCMS_DATA_GRAY_8) { src_bytes_per_pixel = 1; } qcms_transform_data(transform, src, dst, sizeof(src) / src_bytes_per_pixel); qcms_transform_release(transform); }
void test_gray_precache(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)); qcms_profile_precache_output_transform(output_profile); 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); } }