static GtkWidget * lcms_icc_combo_box_new (GimpColorConfig *config, const gchar *filename) { GtkWidget *combo; GtkWidget *dialog; gchar *history; gchar *label; gchar *name; cmsHPROFILE profile; dialog = lcms_icc_file_chooser_dialog_new (); history = gimp_personal_rc_file ("profilerc"); combo = gimp_color_profile_combo_box_new (dialog, history); g_free (history); g_signal_connect (dialog, "response", G_CALLBACK (lcms_icc_file_chooser_dialog_response), combo); if (config->rgb_profile) profile = lcms_load_profile (config->rgb_profile, NULL); else profile = cmsCreate_sRGBProfile (); name = lcms_icc_profile_get_desc (profile); if (! name) name = lcms_icc_profile_get_name (profile); cmsCloseProfile (profile); label = g_strdup_printf (_("RGB workspace (%s)"), name); g_free (name); gimp_color_profile_combo_box_add (GIMP_COLOR_PROFILE_COMBO_BOX (combo), config->rgb_profile, label); g_free (label); if (filename) lcms_icc_combo_box_set_active (GIMP_COLOR_PROFILE_COMBO_BOX (combo), filename); else gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0); return combo; }
void GetMonitorProfile(wxString& profileName, cmsHPROFILE& profile) { if (profile != NULL) { cmsCloseProfile(profile); } profileName.Clear(); profile = NULL; detail::GetMonitorProfile(profileName, profile); // check if monitor profile could be successful loaded, if not switch back to default sRGB profile if (profile == NULL) { profile = cmsCreate_sRGBProfile(); profileName.Clear(); }; };
static PyObject * pycms_CreateRGBProfile(PyObject *self, PyObject *args) { cmsHPROFILE hProfile; cmsErrorAction(LCMS_ERROR_IGNORE); hProfile = cmsCreate_sRGBProfile(); if(hProfile==NULL) { Py_INCREF(Py_None); return Py_None; } return Py_BuildValue("O", PyCObject_FromVoidPtr((void *)hProfile, (void *)cmsCloseProfile)); }
/****************************************************************************** * CreateColorTransformW [MSCMS.@] * * Create a color transform. * * PARAMS * space [I] Input color space. * dest [I] Color profile of destination device. * target [I] Color profile of target device. * flags [I] Flags. * * RETURNS * Success: Handle to a transform. * Failure: NULL */ HTRANSFORM WINAPI CreateColorTransformW( LPLOGCOLORSPACEW space, HPROFILE dest, HPROFILE target, DWORD flags ) { HTRANSFORM ret = NULL; #ifdef HAVE_LCMS struct transform transform; struct profile *dst, *tgt = NULL; cmsHPROFILE cmsinput, cmsoutput, cmstarget = NULL; DWORD in_format, out_format, proofing = 0; int intent; TRACE( "( %p, %p, %p, 0x%08x )\n", space, dest, target, flags ); if (!space || !(dst = grab_profile( dest ))) return FALSE; if (target && !(tgt = grab_profile( target ))) { release_profile( dst ); return FALSE; } intent = space->lcsIntent > 3 ? INTENT_PERCEPTUAL : space->lcsIntent; TRACE( "lcsIntent: %x\n", space->lcsIntent ); TRACE( "lcsCSType: %s\n", MSCMS_dbgstr_tag( space->lcsCSType ) ); TRACE( "lcsFilename: %s\n", debugstr_w( space->lcsFilename ) ); in_format = TYPE_RGB_16; out_format = from_profile( dest ); cmsinput = cmsCreate_sRGBProfile(); /* FIXME: create from supplied color space */ if (target) { proofing = cmsFLAGS_SOFTPROOFING; cmstarget = tgt->cmsprofile; } cmsoutput = dst->cmsprofile; transform.cmstransform = cmsCreateProofingTransform(cmsinput, in_format, cmsoutput, out_format, cmstarget, intent, INTENT_ABSOLUTE_COLORIMETRIC, proofing); ret = create_transform( &transform ); if (tgt) release_profile( tgt ); release_profile( dst ); #endif /* HAVE_LCMS */ return ret; }
LCMS_ICCProfile* LCMS_ColorManager::GetDeviceProfile() { if (!m_srgb_profile) { m_srgb_profile = OP_NEW(LCMS_ICCProfile, ()); if (m_srgb_profile) { cmsHPROFILE profile = cmsCreate_sRGBProfile(); if (!profile) { OP_DELETE(m_srgb_profile); m_srgb_profile = NULL; } else { m_srgb_profile->m_profile = profile; } } }
static PyObject * createProfile(PyObject *self, PyObject *args) { char *sColorSpace; cmsHPROFILE hProfile; int iColorTemp = 0; LPcmsCIExyY whitePoint = NULL; LCMSBOOL result; if (!PyArg_ParseTuple(args, "s|i:createProfile", &sColorSpace, &iColorTemp)) return NULL; cmsErrorAction(LCMS_ERROR_IGNORE); if (strcmp(sColorSpace, "LAB") == 0) { if (iColorTemp > 0) { result = cmsWhitePointFromTemp(iColorTemp, whitePoint); if (!result) { PyErr_SetString(PyExc_ValueError,"ERROR: Could not calculate "\ "white point from color temperature provided, must be "\ "integer in degrees Kelvin"); return NULL; } hProfile = cmsCreateLabProfile(whitePoint); } else hProfile = cmsCreateLabProfile(NULL); } else if (strcmp(sColorSpace, "XYZ") == 0) hProfile = cmsCreateXYZProfile(); else if (strcmp(sColorSpace, "sRGB") == 0) hProfile = cmsCreate_sRGBProfile(); else hProfile = NULL; if (!hProfile) { PyErr_SetString(PyExc_ValueError, "failed to create requested color space"); return NULL; } return cms_profile_new(hProfile); }
static PyObject * createProfile(PyObject *self, PyObject *args) { char *sColorSpace; cmsHPROFILE hProfile; cmsFloat64Number dColorTemp = 0.0; cmsCIExyY whitePoint; cmsBool result; if (!PyArg_ParseTuple(args, "s|d:createProfile", &sColorSpace, &dColorTemp)) return NULL; if (strcmp(sColorSpace, "LAB") == 0) { if (dColorTemp > 0.0) { result = cmsWhitePointFromTemp(&whitePoint, dColorTemp); if (!result) { PyErr_SetString(PyExc_ValueError, "ERROR: Could not calculate white point from color temperature provided, must be float in degrees Kelvin"); return NULL; } hProfile = cmsCreateLab2Profile(&whitePoint); } else { hProfile = cmsCreateLab2Profile(NULL); } } else if (strcmp(sColorSpace, "XYZ") == 0) { hProfile = cmsCreateXYZProfile(); } else if (strcmp(sColorSpace, "sRGB") == 0) { hProfile = cmsCreate_sRGBProfile(); } else { hProfile = NULL; } if (!hProfile) { PyErr_SetString(PyExc_ValueError, "failed to create requested color space"); return NULL; } return cms_profile_new(hProfile); }
static void cdisplay_proof_changed (GimpColorDisplay *display) { CdisplayProof *proof = CDISPLAY_PROOF (display); cmsHPROFILE rgbProfile; cmsHPROFILE proofProfile; if (proof->transform) { cmsDeleteTransform (proof->transform); proof->transform = NULL; } if (! proof->profile) return; rgbProfile = cmsCreate_sRGBProfile (); proofProfile = cmsOpenProfileFromFile (proof->profile, "r"); if (proofProfile) { DWORD flags = cmsFLAGS_SOFTPROOFING; if (proof->bpc) flags |= cmsFLAGS_BLACKPOINTCOMPENSATION; proof->transform = cmsCreateProofingTransform (rgbProfile, TYPE_RGB_8, rgbProfile, TYPE_RGB_8, proofProfile, proof->intent, proof->intent, flags); cmsCloseProfile (proofProfile); } cmsCloseProfile (rgbProfile); }
ScColorProfile ScLcms2ColorMgmtEngineImpl::createProfile_sRGB(ScColorMgmtEngine& engine) { QString internalProfilePath("memprofile://Internal sRGB profile"); ScColorProfile profile = m_profileCache->profile(internalProfilePath); if (!profile.isNull()) return profile; cmsHPROFILE lcmsProf = cmsCreate_sRGBProfile(); if (lcmsProf) { ScLcms2ColorProfileImpl* profData = new ScLcms2ColorProfileImpl(engine, lcmsProf); profData->m_profilePath = internalProfilePath; profile = ScColorProfile(dynamic_cast<ScColorProfileData*>(profData)); m_profileCache->addProfile(profile); } if (profile.isNull() && lcmsProf) { cmsCloseProfile(lcmsProf); lcmsProf = NULL; } return profile; }
Profile::Ptr Profile::getMonitorProfile() { cmsHPROFILE hProfile = 0; // Get the profile from you config file if the user has set it. // if the user allows override through the atom, do this: #ifdef Q_WS_X11 // get the current screen... int screen = -1; Atom type; int format; unsigned long nitems; unsigned long bytes_after; quint8 *str; static Atom icc_atom = XInternAtom(QX11Info::display(), "_ICC_PROFILE", True); if (XGetWindowProperty(QX11Info::display(), QX11Info::appRootWindow(screen), icc_atom, 0, INT_MAX, False, XA_CARDINAL, &type, &format, &nitems, &bytes_after, (unsigned char **) &str) == Success ) { hProfile = cmsOpenProfileFromMem((void*)str, nitems); } #endif if (!hProfile) { hProfile = cmsCreate_sRGBProfile(); } return Profile::Ptr(new Profile(hProfile)); }
void TestKoLcmsColorProfile::testConversion() { const KoColorSpace *sRgb = KoColorSpaceRegistry::instance()->rgb16("sRGB built-in"); Q_ASSERT(sRgb); const KoColorSpace *linearRgb = KoColorSpaceRegistry::instance()->rgb16("scRGB (linear)"); Q_ASSERT(linearRgb); quint16 src[4]; src[0] = 257; src[1] = 257; src[2] = 257; src[3] = 65535; quint16 dst[4]; memset(&dst, 0, 8); linearRgb->convertPixelsTo((quint8 *)&src, (quint8 *)&dst, sRgb, 1, KoColorConversionTransformation::IntentRelativeColorimetric, KoColorConversionTransformation::BlackpointCompensation); quint16 dst2[4]; memset(&dst2, 0, 8); cmsHPROFILE sRgbProfile = cmsCreate_sRGBProfile(); QByteArray rawData = linearRgb->profile()->rawData(); cmsHPROFILE linearRgbProfile = cmsOpenProfileFromMem((void *)rawData.constData(), rawData.size()); cmsHTRANSFORM tf = cmsCreateTransform(linearRgbProfile, TYPE_BGRA_16, sRgbProfile, TYPE_BGRA_16, INTENT_RELATIVE_COLORIMETRIC, cmsFLAGS_NOOPTIMIZE); cmsDoTransform(tf, (quint8 *)&src, (quint8 *)&dst2, 1); Q_ASSERT(dst[0] == dst2[0]); }
static cmsHTRANSFORM cd_sensor_get_fake_transform (CdSensorDummyPrivate *priv) { cmsHTRANSFORM transform; cmsHPROFILE profile_srgb; cmsHPROFILE profile_xyz; profile_srgb = cmsCreate_sRGBProfile (); profile_xyz = cmsCreateXYZProfile (); transform = cmsCreateTransform (profile_srgb, TYPE_RGB_DBL, profile_xyz, TYPE_XYZ_DBL, INTENT_RELATIVE_COLORIMETRIC, cmsFLAGS_NOOPTIMIZE); if (transform == NULL) { g_warning ("failed to setup RGB -> XYZ transform"); goto out; } out: if (profile_srgb != NULL) cmsCloseProfile (profile_srgb); if (profile_xyz != NULL) cmsCloseProfile (profile_xyz); return transform; }
static cmsHPROFILE color_man_cache_load_profile(ColorManProfileType type, const gchar *file, guchar *data, guint data_len) { cmsHPROFILE profile = NULL; switch (type) { case COLOR_PROFILE_FILE: if (file) { gchar *pathl; pathl = path_from_utf8(file); profile = cmsOpenProfileFromFile(pathl, "r"); g_free(pathl); } break; case COLOR_PROFILE_SRGB: profile = cmsCreate_sRGBProfile(); break; case COLOR_PROFILE_ADOBERGB: profile = color_man_create_adobe_comp(); break; case COLOR_PROFILE_MEM: if (data) { profile = cmsOpenProfileFromMem(data, data_len); } break; case COLOR_PROFILE_NONE: default: break; } return profile; }
void CorrectImage(wxImage& image, const vigra::ImageImportInfo::ICCProfile& iccProfile, const cmsHPROFILE& monitorProfile) { cmsHPROFILE inputICC = NULL; if (!iccProfile.empty()) { inputICC = cmsOpenProfileFromMem(iccProfile.data(), iccProfile.size()); }; // check type of input profile if (inputICC != NULL) { if (cmsGetColorSpace(inputICC) != cmsSigRgbData) { cmsCloseProfile(inputICC); inputICC = NULL; }; }; // if there is no icc profile in file fall back to sRGB if (inputICC == NULL) { inputICC = cmsCreate_sRGBProfile(); }; // now build transform cmsHTRANSFORM transform = cmsCreateTransform(inputICC, TYPE_RGB_8, monitorProfile, TYPE_RGB_8, INTENT_PERCEPTUAL, cmsFLAGS_BLACKPOINTCOMPENSATION); unsigned char* imgData = image.GetData(); const int imgWidth = image.GetWidth(); const int imgHeight = image.GetHeight(); #pragma omp parallel for for (int y = 0; y < imgHeight; ++y) { cmsDoTransform(transform, imgData + 3 * y * imgWidth, imgData + 3 * y * imgWidth, imgWidth); }; cmsDeleteTransform(transform); cmsCloseProfile(inputICC); };
/****************************************************************************** * CreateMultiProfileTransform [MSCMS.@] * * Create a color transform from an array of color profiles. * * PARAMS * profiles [I] Array of color profiles. * nprofiles [I] Number of color profiles. * intents [I] Array of rendering intents. * flags [I] Flags. * cmm [I] Profile to take the CMM from. * * RETURNS * Success: Handle to a transform. * Failure: NULL */ HTRANSFORM WINAPI CreateMultiProfileTransform( PHPROFILE profiles, DWORD nprofiles, PDWORD intents, DWORD nintents, DWORD flags, DWORD cmm ) { HTRANSFORM ret = NULL; #ifdef HAVE_LCMS cmsHPROFILE *cmsprofiles, cmsconvert = NULL; struct transform transform; struct profile *profile0, *profile1; DWORD in_format, out_format; TRACE( "( %p, 0x%08x, %p, 0x%08x, 0x%08x, 0x%08x )\n", profiles, nprofiles, intents, nintents, flags, cmm ); if (!profiles || !nprofiles || !intents) return NULL; if (nprofiles > 2) { FIXME("more than 2 profiles not supported\n"); return NULL; } profile0 = grab_profile( profiles[0] ); if (!profile0) return NULL; profile1 = grab_profile( profiles[1] ); if (!profile1) { release_profile( profile0 ); return NULL; } in_format = from_profile( profiles[0] ); out_format = from_profile( profiles[nprofiles - 1] ); if (in_format != out_format) { /* insert a conversion profile for pairings that lcms doesn't handle */ if (out_format == TYPE_RGB_16) cmsconvert = cmsCreate_sRGBProfile(); if (out_format == TYPE_Lab_16) cmsconvert = cmsCreateLabProfile( NULL ); } cmsprofiles = HeapAlloc( GetProcessHeap(), 0, (nprofiles + 1) * sizeof(cmsHPROFILE) ); if (cmsprofiles) { cmsprofiles[0] = profile0->cmsprofile; if (cmsconvert) { cmsprofiles[1] = cmsconvert; cmsprofiles[2] = profile1->cmsprofile; nprofiles++; } else { cmsprofiles[1] = profile1->cmsprofile; } transform.cmstransform = cmsCreateMultiprofileTransform( cmsprofiles, nprofiles, in_format, out_format, *intents, 0 ); HeapFree( GetProcessHeap(), 0, cmsprofiles ); ret = create_transform( &transform ); } release_profile( profile0 ); release_profile( profile1 ); #endif /* HAVE_LCMS */ return ret; }
static gpointer jpeg_load_cmyk_transform (guint8 *profile_data, gsize profile_len) { #ifdef HAVE_LCMS GimpColorConfig *config = gimp_get_color_configuration (); cmsHPROFILE cmyk_profile = NULL; cmsHPROFILE rgb_profile = NULL; cmsUInt32Number flags = 0; cmsHTRANSFORM transform; /* try to load the embedded CMYK profile */ if (profile_data) { cmyk_profile = cmsOpenProfileFromMem (profile_data, profile_len); if (cmyk_profile) { #ifdef HAVE_LCMS1 if (cmsGetColorSpace (cmyk_profile) != icSigCmykData) #else if (cmsGetColorSpace (cmyk_profile) != cmsSigCmykData) #endif { cmsCloseProfile (cmyk_profile); cmyk_profile = NULL; } } } /* if that fails, try to load the CMYK profile configured in the prefs */ if (! cmyk_profile && config->cmyk_profile) { cmyk_profile = cmsOpenProfileFromFile (config->cmyk_profile, "r"); #ifdef HAVE_LCMS1 if (cmyk_profile && cmsGetColorSpace (cmyk_profile) != icSigCmykData) #else if (cmyk_profile && cmsGetColorSpace (cmyk_profile) != cmsSigCmykData) #endif { cmsCloseProfile (cmyk_profile); cmyk_profile = NULL; } } /* bail out if we can't load any CMYK profile */ if (! cmyk_profile) { g_object_unref (config); return NULL; } /* try to load the RGB profile configured in the prefs */ if (config->rgb_profile) { rgb_profile = cmsOpenProfileFromFile (config->rgb_profile, "r"); #ifdef HAVE_LCMS1 if (rgb_profile && cmsGetColorSpace (rgb_profile) != icSigRgbData) #else if (rgb_profile && cmsGetColorSpace (rgb_profile) != cmsSigRgbData) #endif { cmsCloseProfile (rgb_profile); rgb_profile = NULL; } } /* use the built-in sRGB profile as fallback */ if (! rgb_profile) { rgb_profile = cmsCreate_sRGBProfile (); } if (config->display_intent == GIMP_COLOR_RENDERING_INTENT_RELATIVE_COLORIMETRIC) { flags |= cmsFLAGS_BLACKPOINTCOMPENSATION; } transform = cmsCreateTransform (cmyk_profile, TYPE_CMYK_8_REV, rgb_profile, TYPE_RGB_8, config->display_intent, flags); cmsCloseProfile (cmyk_profile); cmsCloseProfile (rgb_profile); g_object_unref (config); return transform; #else /* HAVE_LCMS */ return NULL; #endif }
static GimpPDBStatusType lcms_icc_apply (GimpColorConfig *config, GimpRunMode run_mode, gint32 image, const gchar *filename, GimpColorRenderingIntent intent, gboolean bpc, gboolean *dont_ask) { GimpPDBStatusType status = GIMP_PDB_SUCCESS; cmsHPROFILE src_profile = NULL; cmsHPROFILE dest_profile = NULL; guchar src_md5[16]; guchar dest_md5[16]; g_return_val_if_fail (GIMP_IS_COLOR_CONFIG (config), GIMP_PDB_CALLING_ERROR); g_return_val_if_fail (image != -1, GIMP_PDB_CALLING_ERROR); if (! filename) filename = config->rgb_profile; if (filename) { dest_profile = lcms_load_profile (filename, dest_md5); if (! dest_profile) return GIMP_PDB_EXECUTION_ERROR; if (! lcms_icc_profile_is_rgb (dest_profile)) { g_message (_("Color profile '%s' is not for RGB color space."), gimp_filename_to_utf8 (filename)); cmsCloseProfile (dest_profile); return GIMP_PDB_EXECUTION_ERROR; } } src_profile = lcms_image_get_profile (config, image, src_md5); if (src_profile && ! lcms_icc_profile_is_rgb (src_profile)) { g_printerr ("lcms: attached color profile is not for RGB color space " "(skipping)\n"); cmsCloseProfile (src_profile); src_profile = NULL; } if (! src_profile && ! dest_profile) return GIMP_PDB_SUCCESS; if (! src_profile) { src_profile = cmsCreate_sRGBProfile (); lcms_sRGB_checksum (src_md5); } if (! dest_profile) { dest_profile = cmsCreate_sRGBProfile (); lcms_sRGB_checksum (dest_md5); } if (memcmp (src_md5, dest_md5, 16) == 0) { gchar *src_desc = lcms_icc_profile_get_desc (src_profile); gchar *dest_desc = lcms_icc_profile_get_desc (dest_profile); cmsCloseProfile (src_profile); cmsCloseProfile (dest_profile); g_printerr ("lcms: skipping conversion because profiles seem to be equal:\n"); g_printerr (" %s\n", src_desc); g_printerr (" %s\n", dest_desc); g_free (src_desc); g_free (dest_desc); return GIMP_PDB_SUCCESS; } if (run_mode == GIMP_RUN_INTERACTIVE && ! lcms_icc_apply_dialog (image, src_profile, dest_profile, dont_ask)) { status = GIMP_PDB_CANCEL; } if (status == GIMP_PDB_SUCCESS && ! lcms_image_apply_profile (image, src_profile, dest_profile, filename, intent, bpc)) { status = GIMP_PDB_EXECUTION_ERROR; } cmsCloseProfile (src_profile); cmsCloseProfile (dest_profile); return status; }
static GimpPDBStatusType lcms_dialog (GimpColorConfig *config, gint32 image, gboolean apply, LcmsValues *values) { GimpColorProfileComboBox *box; GtkWidget *dialog; GtkWidget *main_vbox; GtkWidget *frame; GtkWidget *label; GtkWidget *combo; cmsHPROFILE src_profile; gchar *name; gboolean success = FALSE; gboolean run; src_profile = lcms_image_get_profile (config, image, NULL); if (src_profile && ! lcms_icc_profile_is_rgb (src_profile)) { g_printerr ("lcms: attached color profile is not for RGB color space " "(skipping)\n"); cmsCloseProfile (src_profile); src_profile = NULL; } if (! src_profile) src_profile = cmsCreate_sRGBProfile (); gimp_ui_init (PLUG_IN_BINARY, FALSE); dialog = gimp_dialog_new (apply ? _("Convert to ICC Color Profile") : _("Assign ICC Color Profile"), PLUG_IN_ROLE, NULL, 0, gimp_standard_help_func, apply ? PLUG_IN_PROC_APPLY : PLUG_IN_PROC_SET, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, apply ? GTK_STOCK_CONVERT : _("_Assign"), GTK_RESPONSE_OK, NULL); gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog), GTK_RESPONSE_OK, GTK_RESPONSE_CANCEL, -1); gimp_window_set_transient (GTK_WINDOW (dialog)); main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12); gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), main_vbox, TRUE, TRUE, 0); gtk_widget_show (main_vbox); frame = gimp_frame_new (_("Current Color Profile")); gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, FALSE, 0); gtk_widget_show (frame); name = lcms_icc_profile_get_desc (src_profile); if (! name) name = lcms_icc_profile_get_name (src_profile); label = gtk_label_new (name); gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); gtk_container_add (GTK_CONTAINER (frame), label); gtk_widget_show (label); g_free (name); frame = gimp_frame_new (apply ? _("Convert to") : _("Assign")); gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, FALSE, 0); gtk_widget_show (frame); combo = lcms_icc_combo_box_new (config, NULL); gtk_container_add (GTK_CONTAINER (frame), combo); gtk_widget_show (combo); box = GIMP_COLOR_PROFILE_COMBO_BOX (combo); if (apply) { GtkWidget *vbox; GtkWidget *hbox; GtkWidget *toggle; vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6); gtk_box_pack_start (GTK_BOX (main_vbox), vbox, FALSE, FALSE, 0); gtk_widget_show (vbox); hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); gtk_widget_show (hbox); label = gtk_label_new_with_mnemonic (_("_Rendering Intent:")); gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); gtk_widget_show (label); combo = gimp_enum_combo_box_new (GIMP_TYPE_COLOR_RENDERING_INTENT); gtk_box_pack_start (GTK_BOX (hbox), combo, TRUE, TRUE, 0); gtk_widget_show (combo); gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (combo), values->intent, G_CALLBACK (gimp_int_combo_box_get_active), &values->intent); gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo); toggle = gtk_check_button_new_with_mnemonic (_("_Black Point Compensation")); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), values->bpc); gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0); gtk_widget_show (toggle); g_signal_connect (toggle, "toggled", G_CALLBACK (gimp_toggle_button_update), &values->bpc); } while ((run = gimp_dialog_run (GIMP_DIALOG (dialog))) == GTK_RESPONSE_OK) { gchar *filename = gimp_color_profile_combo_box_get_active (box); cmsHPROFILE dest_profile; gtk_widget_set_sensitive (dialog, FALSE); if (filename) { dest_profile = lcms_load_profile (filename, NULL); } else { dest_profile = cmsCreate_sRGBProfile (); } if (dest_profile) { if (lcms_icc_profile_is_rgb (dest_profile)) { if (apply) success = lcms_image_apply_profile (image, src_profile, dest_profile, filename, values->intent, values->bpc); else success = lcms_image_set_profile (image, dest_profile, filename, TRUE); } else { gimp_message (_("Destination profile is not for RGB color space.")); } cmsCloseProfile (dest_profile); } if (success) break; else gtk_widget_set_sensitive (dialog, TRUE); } gtk_widget_destroy (dialog); cmsCloseProfile (src_profile); return (run ? (success ? GIMP_PDB_SUCCESS : GIMP_PDB_EXECUTION_ERROR) : GIMP_PDB_CANCEL); }
// Open Image ptImage* ptImage::ptGMCOpenImage(const char* FileName, short ColorSpace, short Intent, short ScaleFactor, bool IsRAW, TImage8RawData* ImgData, bool& Success) { Success = 0; MagickWand* image = NewMagickWand(); ExceptionType MagickExcept; if (IsRAW) { MagickReadImageBlob(image, (const uchar*)ImgData->data(), (const size_t)ImgData->size()); } else { if (!QFile::exists(QString::fromLocal8Bit(FileName))) return this; MagickReadImage(image, FileName); } MagickGetException(image, &MagickExcept); if (MagickExcept != UndefinedException) { return this; } Success = 1; // Get the embedded profile cmsHPROFILE InProfile = NULL; if (MagickGetImageType(image) != GrayscaleType) { ulong ProfileLength = 0; uchar* IccProfile = MagickGetImageProfile(image, "ICC", &ProfileLength); if (ProfileLength > 0) { InProfile = cmsOpenProfileFromMem(IccProfile, ProfileLength); } } if (!InProfile) { InProfile = cmsCreate_sRGBProfile(); } MagickSetImageType(image, TrueColorType); MagickSetImageFormat(image, "RGB"); MagickSetImageDepth(image, 16); uint16_t NewWidth = MagickGetImageWidth(image); uint16_t NewHeight = MagickGetImageHeight(image); // Buffer for the data from Magick std::vector<std::array<float, 3> > ImageBuffer; ImageBuffer.resize((size_t) NewWidth*NewHeight); MagickGetImagePixels(image, 0, 0, NewWidth, NewHeight, "RGB", FloatPixel, (uchar*)ImageBuffer.data()); m_Width = NewWidth; DestroyMagickWand(image); // Image before color transform, may be binned std::vector<std::array<float, 3> > NewImage; if (ScaleFactor != 0) { // Binning NewHeight >>= ScaleFactor; NewWidth >>= ScaleFactor; short Step = 1 << ScaleFactor; int Average = pow(2,2 * ScaleFactor); NewImage.resize((size_t)NewWidth*NewHeight); #pragma omp parallel for schedule(static) for (uint16_t Row=0; Row < NewHeight*Step; Row+=Step) { for (uint16_t Col=0; Col < NewWidth*Step; Col+=Step) { float PixelValue[3] = {0.0f,0.0f,0.0f}; for (uint8_t sRow=0; sRow < Step; sRow++) { for (uint8_t sCol=0; sCol < Step; sCol++) { int32_t index = (Row+sRow)*m_Width+Col+sCol; for (short c=0; c < 3; c++) { PixelValue[c] += ImageBuffer[index][c]; } } } for (short c=0; c < 3; c++) { NewImage[Row/Step*NewWidth+Col/Step][c] = PixelValue[c] / Average; } } } } else {
void Color::LoadICCProfiles() { if(m_iccSearchPaths!= NULL){ delete m_iccSearchPaths; } const Int32 NUMSEARCHPATHS = 4; m_iccSearchPaths = new String[NUMSEARCHPATHS]; Filename cmykDir = GeGetPluginPath(); cmykDir += Filename(String("cmyk")); m_iccSearchPaths[0] = cmykDir.GetString(); m_iccSearchPaths[1] = "/Library/ColorSync/Profiles/"; m_iccSearchPaths[2] = "/Users/vidarn/Library/ColorSync"; m_iccSearchPaths[3] = "C:\\Windows\\System32\\Spool\\Drivers\\Color\\"; Logger::AddLine("Creating LAB profile",1); m_LABProfile = cmsCreateLab4Profile(NULL); Logger::AddLine("Creating default sRGB profile",1); m_displayProfile = cmsCreate_sRGBProfile(); m_RGBProfiles.Insert(vnColorProfile("sRGB",m_displayProfile),0); for(Int32 i=0;i<NUMSEARCHPATHS;++i){ BrowseFiles* bf = BrowseFiles::Alloc(); Filename dir(m_iccSearchPaths[i]); bf->Init(dir,FALSE); int RGBPos = m_RGBProfiles.GetCount(); int CMYKPos = m_CMYKProfiles.GetCount(); int spotPos = m_spotProfiles.GetCount(); if (bf) { while (bf->GetNext()) { Filename fileName = bf->GetFilename(); fileName.SetDirectory(dir); String str = fileName.GetString(); Char *buffer = new Char[str.GetCStringLen()+1]; str.GetCString(buffer,str.GetCStringLen()+1); Logger::AddLine(buffer,1); cmsHPROFILE profile = cmsOpenProfileFromFile(buffer, "r"); if(profile != NULL){ cmsColorSpaceSignature sig = cmsGetColorSpace(profile); Int32 length = cmsGetProfileInfoASCII(profile,cmsInfoDescription,"en","US",NULL,0); Char *buffer2 = new Char[length]; cmsGetProfileInfoASCII(profile,cmsInfoDescription,"en","US",buffer2,length); String info(buffer2); int pt = _cmsLCMScolorSpace(sig); if(PT_RGB == pt){ Logger::AddLine("RGB profile",1); m_RGBProfiles.Insert(vnColorProfile(info,profile),RGBPos); RGBPos++; } if(PT_CMYK == pt){ cmsHTRANSFORM xform = cmsCreateTransform(profile,TYPE_NAMED_COLOR_INDEX,m_displayProfile,TYPE_RGB_DBL,INTENT_PERCEPTUAL,0); if(xform != NULL){ cmsNAMEDCOLORLIST* colorList = cmsGetNamedColorList(xform); if(colorList != NULL){ m_spotProfiles.Insert(vnColorProfile(info,profile),spotPos); spotPos++; } else{ Logger::AddLine("CMYK profile",1); m_CMYKProfiles.Insert(vnColorProfile(info,profile),CMYKPos); CMYKPos++; } cmsDeleteTransform(xform); } } delete buffer2; } else { Logger::AddLine("Invalid",1); } delete buffer; } } BrowseFiles::Free(bf); } }
void color_apply_icc_profile(opj_image_t* image) { cmsHPROFILE out_prof; cmsUInt32Number in_type; cmsUInt32Number out_type; int* r; int* g; int* b; int max; cmsHPROFILE in_prof = cmsOpenProfileFromMem(image->icc_profile_buf, image->icc_profile_len); if (!in_prof) { return; } cmsColorSpaceSignature out_space = cmsGetColorSpace(in_prof); cmsUInt32Number intent = cmsGetHeaderRenderingIntent(in_prof); int max_w = (int)image->comps[0].w; int max_h = (int)image->comps[0].h; int prec = (int)image->comps[0].prec; OPJ_COLOR_SPACE oldspace = image->color_space; if (out_space == cmsSigRgbData) { if (prec <= 8) { in_type = TYPE_RGB_8; out_type = TYPE_RGB_8; } else { in_type = TYPE_RGB_16; out_type = TYPE_RGB_16; } out_prof = cmsCreate_sRGBProfile(); image->color_space = OPJ_CLRSPC_SRGB; } else if (out_space == cmsSigGrayData) { if (prec <= 8) { in_type = TYPE_GRAY_8; out_type = TYPE_RGB_8; } else { in_type = TYPE_GRAY_16; out_type = TYPE_RGB_16; } out_prof = cmsCreate_sRGBProfile(); image->color_space = OPJ_CLRSPC_SRGB; } else if (out_space == cmsSigYCbCrData) { in_type = TYPE_YCbCr_16; out_type = TYPE_RGB_16; out_prof = cmsCreate_sRGBProfile(); image->color_space = OPJ_CLRSPC_SRGB; } else { return; } cmsHTRANSFORM transform = cmsCreateTransform(in_prof, in_type, out_prof, out_type, intent, 0); cmsCloseProfile(in_prof); cmsCloseProfile(out_prof); if (!transform) { image->color_space = oldspace; return; } if (image->numcomps > 2) { if (prec <= 8) { unsigned char *inbuf, *outbuf, *in, *out; max = max_w * max_h; cmsUInt32Number nr_samples = max * 3 * sizeof(unsigned char); in = inbuf = FX_Alloc(unsigned char, nr_samples); out = outbuf = FX_Alloc(unsigned char, nr_samples); r = image->comps[0].data; g = image->comps[1].data; b = image->comps[2].data; for (int i = 0; i < max; ++i) { *in++ = (unsigned char)*r++; *in++ = (unsigned char)*g++; *in++ = (unsigned char)*b++; } cmsDoTransform(transform, inbuf, outbuf, (cmsUInt32Number)max); r = image->comps[0].data; g = image->comps[1].data; b = image->comps[2].data; for (int i = 0; i < max; ++i) { *r++ = (int)*out++; *g++ = (int)*out++; *b++ = (int)*out++; } FX_Free(inbuf); FX_Free(outbuf); } else {
PyObject * load_png_fast_progressive (char *filename, PyObject *get_buffer_callback) { // Note: we are not using the method that libpng calls "Reading PNG // files progressively". That method would involve feeding the data // into libpng piece by piece, which is not necessary if we can give // libpng a simple FILE pointer. png_structp png_ptr = NULL; png_infop info_ptr = NULL; PyObject * result = NULL; FILE *fp = NULL; uint32_t width, height; uint32_t rows_left; png_byte color_type; png_byte bit_depth; bool have_alpha; char *cm_processing = NULL; // ICC profile-based colour conversion data. png_charp icc_profile_name = NULL; int icc_compression_type = 0; #if PNG_LIBPNG_VER < 10500 // 1.5.0beta36, according to libpng CHANGES png_charp icc_profile = NULL; #else png_bytep icc_profile = NULL; #endif png_uint_32 icc_proflen = 0; // The sRGB flag has an intent field, which we ignore - // the target gamut is sRGB already. int srgb_intent = 0; // Generic RGB space conversion params. // The assumptions we're making are those of sRGB, // but they'll be overridden by gammas or primaries in the file if used. bool generic_rgb_have_gAMA = false; bool generic_rgb_have_cHRM = false; double generic_rgb_file_gamma = 45455 / PNG_gAMA_scale; double generic_rgb_white_x = 31270 / PNG_cHRM_scale; double generic_rgb_white_y = 32900 / PNG_cHRM_scale; double generic_rgb_red_x = 64000 / PNG_cHRM_scale; double generic_rgb_red_y = 33000 / PNG_cHRM_scale; double generic_rgb_green_x = 30000 / PNG_cHRM_scale; double generic_rgb_green_y = 60000 / PNG_cHRM_scale; double generic_rgb_blue_x = 15000 / PNG_cHRM_scale; double generic_rgb_blue_y = 6000 / PNG_cHRM_scale; // Indicates the case where no CM information was present in the file and we // treated it as sRGB. bool possible_legacy_png = false; // LCMS stuff cmsHPROFILE input_buffer_profile = NULL; cmsHPROFILE nparray_data_profile = cmsCreate_sRGBProfile(); cmsHTRANSFORM input_buffer_to_nparray = NULL; cmsToneCurve *gamma_transfer_func = NULL; cmsUInt32Number input_buffer_format = 0; cmsSetLogErrorHandler(log_lcms2_error); fp = fopen(filename, "rb"); if (!fp) { PyErr_SetFromErrno(PyExc_IOError); //PyErr_Format(PyExc_IOError, "Could not open PNG file for writing: %s", // filename); goto cleanup; } png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, (png_voidp)NULL, png_read_error_callback, NULL); if (!png_ptr) { PyErr_SetString(PyExc_MemoryError, "png_create_write_struct() failed"); goto cleanup; } info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { PyErr_SetString(PyExc_MemoryError, "png_create_info_struct() failed"); goto cleanup; } if (setjmp(png_jmpbuf(png_ptr))) { goto cleanup; } png_init_io(png_ptr, fp); png_read_info(png_ptr, info_ptr); // If there's an embedded ICC profile, use it in preference to any other // colour management information present. if (png_get_iCCP (png_ptr, info_ptr, &icc_profile_name, &icc_compression_type, &icc_profile, &icc_proflen)) { input_buffer_profile = cmsOpenProfileFromMem(icc_profile, icc_proflen); if (! input_buffer_profile) { PyErr_SetString(PyExc_MemoryError, "cmsOpenProfileFromMem() failed"); goto cleanup; } cm_processing = "iCCP (use embedded colour profile)"; } // Shorthand for sRGB. else if (png_get_sRGB (png_ptr, info_ptr, &srgb_intent)) { input_buffer_profile = cmsCreate_sRGBProfile(); cm_processing = "sRGB (explicit sRGB chunk)"; } else { // We might have generic RGB transformation information in the form of // the chromaticities for R, G and B and a generic gamma curve. if (png_get_cHRM (png_ptr, info_ptr, &generic_rgb_white_x, &generic_rgb_white_y, &generic_rgb_red_x, &generic_rgb_red_y, &generic_rgb_green_x, &generic_rgb_green_y, &generic_rgb_blue_x, &generic_rgb_blue_y)) { generic_rgb_have_cHRM = true; } if (png_get_gAMA(png_ptr, info_ptr, &generic_rgb_file_gamma)) { generic_rgb_have_gAMA = true; } if (generic_rgb_have_gAMA || generic_rgb_have_cHRM) { cmsCIExyYTRIPLE primaries = {{generic_rgb_red_x, generic_rgb_red_y}, {generic_rgb_green_x, generic_rgb_green_y}, {generic_rgb_blue_x, generic_rgb_blue_y}}; cmsCIExyY white_point = {generic_rgb_white_x, generic_rgb_white_y}; gamma_transfer_func = cmsBuildGamma(NULL, 1.0/generic_rgb_file_gamma); cmsToneCurve *transfer_funcs[3] = {gamma_transfer_func, gamma_transfer_func, gamma_transfer_func }; input_buffer_profile = cmsCreateRGBProfile(&white_point, &primaries, transfer_funcs); cm_processing = "cHRM and/or gAMA (generic RGB space)"; } // Possible legacy PNG, or rather one which might have been written with an // old version of MyPaint. Treat as sRGB, but flag the strangeness because // it might be important for PNGs in old OpenRaster files. else { possible_legacy_png = true; input_buffer_profile = cmsCreate_sRGBProfile(); cm_processing = "sRGB (no CM chunks present)"; } } if (png_get_interlace_type (png_ptr, info_ptr) != PNG_INTERLACE_NONE) { PyErr_SetString(PyExc_RuntimeError, "Interlaced PNG files are not supported!"); goto cleanup; } color_type = png_get_color_type(png_ptr, info_ptr); bit_depth = png_get_bit_depth(png_ptr, info_ptr); have_alpha = color_type & PNG_COLOR_MASK_ALPHA; if (color_type == PNG_COLOR_TYPE_PALETTE) { png_set_palette_to_rgb(png_ptr); } if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) { png_set_expand_gray_1_2_4_to_8(png_ptr); } if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha(png_ptr); have_alpha = true; } if (bit_depth < 8) { png_set_packing(png_ptr); } if (!have_alpha) { png_set_add_alpha(png_ptr, 0xFF, PNG_FILLER_AFTER); } if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { png_set_gray_to_rgb(png_ptr); } png_read_update_info(png_ptr, info_ptr); // Verify what we have done bit_depth = png_get_bit_depth(png_ptr, info_ptr); if (! (bit_depth == 8 || bit_depth == 16)) { PyErr_SetString(PyExc_RuntimeError, "Failed to convince libpng to convert " "to 8 or 16 bits per channel"); goto cleanup; } if (png_get_color_type(png_ptr, info_ptr) != PNG_COLOR_TYPE_RGB_ALPHA) { PyErr_SetString(PyExc_RuntimeError, "Failed to convince libpng to convert " "to RGBA (wrong color_type)"); goto cleanup; } if (png_get_channels(png_ptr, info_ptr) != 4) { PyErr_SetString(PyExc_RuntimeError, "Failed to convince libpng to convert " "to RGBA (wrong number of channels)"); goto cleanup; } // PNGs use network byte order, i.e. big-endian in descending order // of bit significance. LittleCMS uses whatever's detected for the compiler. // ref: http://www.w3.org/TR/2003/REC-PNG-20031110/#7Integers-and-byte-order if (bit_depth == 16) { #ifdef CMS_USE_BIG_ENDIAN input_buffer_format = TYPE_RGBA_16; #else input_buffer_format = TYPE_RGBA_16_SE; #endif } else { input_buffer_format = TYPE_RGBA_8; } input_buffer_to_nparray = cmsCreateTransform (input_buffer_profile, input_buffer_format, nparray_data_profile, TYPE_RGBA_8, INTENT_PERCEPTUAL, 0); width = png_get_image_width(png_ptr, info_ptr); height = png_get_image_height(png_ptr, info_ptr); rows_left = height; while (rows_left) { PyObject *pyarr = NULL; uint32_t rows = 0; uint32_t row = 0; const uint8_t input_buf_bytes_per_pixel = (bit_depth==8) ? 4 : 8; const uint32_t input_buf_row_stride = sizeof(png_byte) * width * input_buf_bytes_per_pixel; png_byte *input_buffer = NULL; png_bytep *input_buf_row_pointers = NULL; pyarr = PyObject_CallFunction(get_buffer_callback, "ii", width, height); if (! pyarr) { PyErr_Format(PyExc_RuntimeError, "Get-buffer callback failed"); goto cleanup; } #ifdef HEAVY_DEBUG //assert(PyArray_ISCARRAY(arr)); assert(PyArray_NDIM(pyarr) == 3); assert(PyArray_DIM(pyarr, 1) == width); assert(PyArray_DIM(pyarr, 2) == 4); assert(PyArray_TYPE(pyarr) == NPY_UINT8); assert(PyArray_ISBEHAVED(pyarr)); assert(PyArray_STRIDE(pyarr, 1) == 4*sizeof(uint8_t)); assert(PyArray_STRIDE(pyarr, 2) == sizeof(uint8_t)); #endif rows = PyArray_DIM(pyarr, 0); if (rows > rows_left) { PyErr_Format(PyExc_RuntimeError, "Attempt to read %d rows from the PNG, " "but only %d are left", rows, rows_left); goto cleanup; } input_buffer = (png_byte *) malloc(rows * input_buf_row_stride); input_buf_row_pointers = (png_bytep *)malloc(rows * sizeof(png_bytep)); for (row=0; row<rows; row++) { input_buf_row_pointers[row] = input_buffer + (row * input_buf_row_stride); } png_read_rows(png_ptr, input_buf_row_pointers, NULL, rows); rows_left -= rows; for (row=0; row<rows; row++) { uint8_t *pyarr_row = (uint8_t *)PyArray_DATA(pyarr) + row*PyArray_STRIDE(pyarr, 0); uint8_t *input_row = input_buf_row_pointers[row]; // Really minimal fake colour management. Just remaps to sRGB. cmsDoTransform(input_buffer_to_nparray, input_row, pyarr_row, width); // lcms2 ignores alpha, so copy that verbatim // If it's 8bpc RGBA, use A. // If it's 16bpc RrGgBbAa, use A. for (uint32_t i=0; i<width; ++i) { const uint32_t pyarr_alpha_byte = (i*4) + 3; const uint32_t buf_alpha_byte = (i*input_buf_bytes_per_pixel) + ((bit_depth==8) ? 3 : 6); pyarr_row[pyarr_alpha_byte] = input_row[buf_alpha_byte]; } } free(input_buf_row_pointers); free(input_buffer); Py_DECREF(pyarr); } png_read_end(png_ptr, NULL); result = Py_BuildValue("{s:b,s:i,s:i,s:s}", "possible_legacy_png", possible_legacy_png, "width", width, "height", height, "cm_conversions_applied", cm_processing); cleanup: if (info_ptr) png_destroy_read_struct (&png_ptr, &info_ptr, NULL); // libpng's style is to free internally allocated stuff like the icc // tables in png_destroy_*(). I think. if (fp) fclose(fp); if (input_buffer_profile) cmsCloseProfile(input_buffer_profile); if (nparray_data_profile) cmsCloseProfile(nparray_data_profile); if (input_buffer_to_nparray) cmsDeleteTransform(input_buffer_to_nparray); if (gamma_transfer_func) cmsFreeToneCurve(gamma_transfer_func); return result; }
bool write(const pfs::Frame &frame, const JpegWriterParams& params, const std::string& filename) { cmsUInt32Number cmsProfileSize = 0; utils::ScopedCmsProfile hsRGB( cmsCreate_sRGBProfile() ); cmsSaveProfileToMem(hsRGB.data(), NULL, &cmsProfileSize); // get the size std::vector<JOCTET> cmsOutputProfile(cmsProfileSize); cmsSaveProfileToMem(hsRGB.data(), cmsOutputProfile.data(), &cmsProfileSize); struct jpeg_compress_struct cinfo; struct jpeg_error_mgr errorHandler; jpeg_create_compress(&cinfo); cinfo.err = jpeg_std_error(&errorHandler); errorHandler.error_exit = my_writer_error_handler; errorHandler.output_message = my_writer_output_message; cinfo.image_width = frame.getWidth(); // image width and height, in pixels cinfo.image_height = frame.getHeight(); cinfo.input_components = cinfo.num_components = 3; // # of color components per pixel cinfo.in_color_space = JCS_RGB; // colorspace of input image cinfo.jpeg_color_space = JCS_YCbCr; cinfo.density_unit = 1; // dots/inch cinfo.X_density = cinfo.Y_density = 72; jpeg_set_defaults(&cinfo); jpeg_set_colorspace(&cinfo, JCS_YCbCr); // avoid subsampling on high quality factor jpeg_set_quality(&cinfo, params.quality_, 1); if ( params.quality_ >= 70 ) { for (int i = 0; i < cinfo.num_components; i++) { cinfo.comp_info[i].h_samp_factor = 1; cinfo.comp_info[i].v_samp_factor = 1; } } try { setupJpegDest(&cinfo, filename); jpeg_start_compress(&cinfo, true); const Channel* rChannel; const Channel* gChannel; const Channel* bChannel; frame.getXYZChannels(rChannel, gChannel, bChannel); write_icc_profile(&cinfo, cmsOutputProfile.data(), cmsProfileSize); // If an exception is raised, this buffer gets automatically destructed! std::vector<JSAMPLE> scanLineOut(cinfo.image_width * cinfo.num_components); JSAMPROW scanLineOutArray[1] = { scanLineOut.data() }; while (cinfo.next_scanline < cinfo.image_height) { // copy line from Frame into scanLineOut utils::transform( rChannel->row_begin(cinfo.next_scanline), rChannel->row_end(cinfo.next_scanline), gChannel->row_begin(cinfo.next_scanline), bChannel->row_begin(cinfo.next_scanline), FixedStrideIterator<JSAMPLE*, 3>(scanLineOut.data()), FixedStrideIterator<JSAMPLE*, 3>(scanLineOut.data() + 1), FixedStrideIterator<JSAMPLE*, 3>(scanLineOut.data() + 2), utils::chain( colorspace::Normalizer(params.minLuminance_, params.maxLuminance_), utils::CLAMP_F32, Remapper<JSAMPLE>(params.luminanceMapping_) ) ); jpeg_write_scanlines(&cinfo, scanLineOutArray, 1); } } catch (const std::runtime_error& err) { std::clog << err.what() << std::endl; jpeg_destroy_compress(&cinfo); return false; } jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo); close(); return true; }
Profile::Ptr Profile::getSRgbProfile() { return Profile::Ptr(new Profile(cmsCreate_sRGBProfile())); }
pngquant_error rwpng_read_image24_libpng(FILE *infile, png24_image *mainprog_ptr) { png_structp png_ptr = NULL; png_infop info_ptr = NULL; png_size_t rowbytes; int color_type, bit_depth; png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, mainprog_ptr, rwpng_error_handler, NULL); if (!png_ptr) { return PNG_OUT_OF_MEMORY_ERROR; /* out of memory */ } info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, NULL, NULL); return PNG_OUT_OF_MEMORY_ERROR; /* out of memory */ } /* setjmp() must be called in every function that calls a non-trivial * libpng function */ if (setjmp(mainprog_ptr->jmpbuf)) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return LIBPNG_FATAL_ERROR; /* fatal libpng error (via longjmp()) */ } struct rwpng_read_data read_data = {infile, 0}; png_set_read_fn(png_ptr, &read_data, user_read_data); png_read_info(png_ptr, info_ptr); /* read all PNG info up to image data */ /* alternatively, could make separate calls to png_get_image_width(), * etc., but want bit_depth and color_type for later [don't care about * compression_type and filter_type => NULLs] */ png_get_IHDR(png_ptr, info_ptr, &mainprog_ptr->width, &mainprog_ptr->height, &bit_depth, &color_type, NULL, NULL, NULL); /* expand palette images to RGB, low-bit-depth grayscale images to 8 bits, * transparency chunks to full alpha channel; strip 16-bit-per-sample * images to 8 bits per sample; and convert grayscale to RGB[A] */ /* GRR TO DO: preserve all safe-to-copy ancillary PNG chunks */ if (!(color_type & PNG_COLOR_MASK_ALPHA)) { #ifdef PNG_READ_FILLER_SUPPORTED png_set_expand(png_ptr); png_set_filler(png_ptr, 65535L, PNG_FILLER_AFTER); #else fprintf(stderr, "pngquant readpng: image is neither RGBA nor GA\n"); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); mainprog_ptr->retval = 26; return mainprog_ptr->retval; #endif } /* if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_expand(png_ptr); if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_expand(png_ptr); */ if (bit_depth == 16) png_set_strip_16(png_ptr); if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png_ptr); /* get and save the gamma info (if any) for writing */ double gamma; mainprog_ptr->gamma = png_get_gAMA(png_ptr, info_ptr, &gamma) ? gamma : 0.45455; png_set_interlace_handling(png_ptr); /* all transformations have been registered; now update info_ptr data, * get rowbytes and channels, and allocate image memory */ png_read_update_info(png_ptr, info_ptr); rowbytes = png_get_rowbytes(png_ptr, info_ptr); if ((mainprog_ptr->rgba_data = malloc(rowbytes*mainprog_ptr->height)) == NULL) { fprintf(stderr, "pngquant readpng: unable to allocate image data\n"); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return PNG_OUT_OF_MEMORY_ERROR; } png_bytepp row_pointers = rwpng_create_row_pointers(info_ptr, png_ptr, mainprog_ptr->rgba_data, mainprog_ptr->height, 0); /* now we can go ahead and just read the whole image */ png_read_image(png_ptr, row_pointers); /* and we're done! (png_read_end() can be omitted if no processing of * post-IDAT text/time/etc. is desired) */ png_read_end(png_ptr, NULL); #if USE_LCMS if (png_get_valid(png_ptr, info_ptr, PNG_INFO_iCCP)) { png_uint_32 ProfileLen; png_bytep ProfileData; int Compression; png_charp ProfileName; png_get_iCCP(png_ptr, info_ptr, &ProfileName, &Compression, &ProfileData, &ProfileLen); cmsHPROFILE hInProfile = cmsOpenProfileFromMem(ProfileData, ProfileLen); cmsHPROFILE hOutProfile = cmsCreate_sRGBProfile(); cmsHTRANSFORM hTransform = cmsCreateTransform(hInProfile, TYPE_RGBA_8, hOutProfile, TYPE_RGBA_8, INTENT_PERCEPTUAL, 0); // suprisingly, using the same input and output works cmsDoTransform(hTransform, mainprog_ptr->rgba_data, mainprog_ptr->rgba_data, mainprog_ptr->height * mainprog_ptr->width); cmsDeleteTransform(hTransform); cmsCloseProfile(hOutProfile); cmsCloseProfile(hInProfile); } #endif png_destroy_read_struct(&png_ptr, &info_ptr, NULL); mainprog_ptr->file_size = read_data.bytes_read; mainprog_ptr->row_pointers = (unsigned char **)row_pointers; return SUCCESS; }
cmsHPROFILE dkCmsCreate_sRGBProfile() { return cmsCreate_sRGBProfile(); }
/*#define DEBUG_PROFILE*/ void color_apply_icc_profile(opj_image_t *image) { cmsHPROFILE in_prof, out_prof; cmsHTRANSFORM transform; cmsColorSpaceSignature in_space, out_space; cmsUInt32Number intent, in_type, out_type, nr_samples; int *r, *g, *b; int prec, i, max, max_w, max_h; OPJ_COLOR_SPACE oldspace; in_prof = cmsOpenProfileFromMem(image->icc_profile_buf, image->icc_profile_len); #ifdef DEBUG_PROFILE FILE *icm = fopen("debug.icm","wb"); fwrite( image->icc_profile_buf,1, image->icc_profile_len,icm); fclose(icm); #endif if(in_prof == NULL) return; in_space = cmsGetPCS(in_prof); out_space = cmsGetColorSpace(in_prof); intent = cmsGetHeaderRenderingIntent(in_prof); max_w = (int)image->comps[0].w; max_h = (int)image->comps[0].h; prec = (int)image->comps[0].prec; oldspace = image->color_space; if(out_space == cmsSigRgbData) /* enumCS 16 */ { if( prec <= 8 ) { in_type = TYPE_RGB_8; out_type = TYPE_RGB_8; } else { in_type = TYPE_RGB_16; out_type = TYPE_RGB_16; } out_prof = cmsCreate_sRGBProfile(); image->color_space = OPJ_CLRSPC_SRGB; } else if(out_space == cmsSigGrayData) /* enumCS 17 */ { in_type = TYPE_GRAY_8; out_type = TYPE_RGB_8; out_prof = cmsCreate_sRGBProfile(); image->color_space = OPJ_CLRSPC_SRGB; } else if(out_space == cmsSigYCbCrData) /* enumCS 18 */ { in_type = TYPE_YCbCr_16; out_type = TYPE_RGB_16; out_prof = cmsCreate_sRGBProfile(); image->color_space = OPJ_CLRSPC_SRGB; } else { #ifdef DEBUG_PROFILE fprintf(stderr,"%s:%d: color_apply_icc_profile\n\tICC Profile has unknown " "output colorspace(%#x)(%c%c%c%c)\n\tICC Profile ignored.\n", __FILE__,__LINE__,out_space, (out_space>>24) & 0xff,(out_space>>16) & 0xff, (out_space>>8) & 0xff, out_space & 0xff); #endif return; } #ifdef DEBUG_PROFILE fprintf(stderr,"%s:%d:color_apply_icc_profile\n\tchannels(%d) prec(%d) w(%d) h(%d)" "\n\tprofile: in(%p) out(%p)\n",__FILE__,__LINE__,image->numcomps,prec, max_w,max_h, (void*)in_prof,(void*)out_prof); fprintf(stderr,"\trender_intent (%u)\n\t" "color_space: in(%#x)(%c%c%c%c) out:(%#x)(%c%c%c%c)\n\t" " type: in(%u) out:(%u)\n", intent, in_space, (in_space>>24) & 0xff,(in_space>>16) & 0xff, (in_space>>8) & 0xff, in_space & 0xff, out_space, (out_space>>24) & 0xff,(out_space>>16) & 0xff, (out_space>>8) & 0xff, out_space & 0xff, in_type,out_type ); #else (void)prec; (void)in_space; #endif /* DEBUG_PROFILE */ transform = cmsCreateTransform(in_prof, in_type, out_prof, out_type, intent, 0); #ifdef OPJ_HAVE_LIBLCMS2 /* Possible for: LCMS_VERSION >= 2000 :*/ cmsCloseProfile(in_prof); cmsCloseProfile(out_prof); #endif if(transform == NULL) { #ifdef DEBUG_PROFILE fprintf(stderr,"%s:%d:color_apply_icc_profile\n\tcmsCreateTransform failed. " "ICC Profile ignored.\n",__FILE__,__LINE__); #endif image->color_space = oldspace; #ifdef OPJ_HAVE_LIBLCMS1 cmsCloseProfile(in_prof); cmsCloseProfile(out_prof); #endif return; } if(image->numcomps > 2)/* RGB, RGBA */ { if( prec <= 8 ) { unsigned char *inbuf, *outbuf, *in, *out; max = max_w * max_h; nr_samples = (cmsUInt32Number)max * 3 * (cmsUInt32Number)sizeof(unsigned char); in = inbuf = (unsigned char*)malloc(nr_samples); out = outbuf = (unsigned char*)malloc(nr_samples); r = image->comps[0].data; g = image->comps[1].data; b = image->comps[2].data; for(i = 0; i < max; ++i) { *in++ = (unsigned char)*r++; *in++ = (unsigned char)*g++; *in++ = (unsigned char)*b++; } cmsDoTransform(transform, inbuf, outbuf, (cmsUInt32Number)max); r = image->comps[0].data; g = image->comps[1].data; b = image->comps[2].data; for(i = 0; i < max; ++i) { *r++ = (int)*out++; *g++ = (int)*out++; *b++ = (int)*out++; } free(inbuf); free(outbuf); } else { unsigned short *inbuf, *outbuf, *in, *out; max = max_w * max_h; nr_samples = (cmsUInt32Number)max * 3 * (cmsUInt32Number)sizeof(unsigned short); in = inbuf = (unsigned short*)malloc(nr_samples); out = outbuf = (unsigned short*)malloc(nr_samples); r = image->comps[0].data; g = image->comps[1].data; b = image->comps[2].data; for(i = 0; i < max; ++i) { *in++ = (unsigned short)*r++; *in++ = (unsigned short)*g++; *in++ = (unsigned short)*b++; } cmsDoTransform(transform, inbuf, outbuf, (cmsUInt32Number)max); r = image->comps[0].data; g = image->comps[1].data; b = image->comps[2].data; for(i = 0; i < max; ++i) { *r++ = (int)*out++; *g++ = (int)*out++; *b++ = (int)*out++; } free(inbuf); free(outbuf); } } else /* GRAY, GRAYA */ { unsigned char *in, *inbuf, *out, *outbuf; max = max_w * max_h; nr_samples = (cmsUInt32Number)max * 3 * sizeof(unsigned char); in = inbuf = (unsigned char*)malloc(nr_samples); out = outbuf = (unsigned char*)malloc(nr_samples); image->comps = (opj_image_comp_t*) realloc(image->comps, (image->numcomps+2)*sizeof(opj_image_comp_t)); if(image->numcomps == 2) image->comps[3] = image->comps[1]; image->comps[1] = image->comps[0]; image->comps[2] = image->comps[0]; image->comps[1].data = (int*)calloc((size_t)max, sizeof(int)); image->comps[2].data = (int*)calloc((size_t)max, sizeof(int)); image->numcomps += 2; r = image->comps[0].data; for(i = 0; i < max; ++i) { *in++ = (unsigned char)*r++; } cmsDoTransform(transform, inbuf, outbuf, (cmsUInt32Number)max); r = image->comps[0].data; g = image->comps[1].data; b = image->comps[2].data; for(i = 0; i < max; ++i) { *r++ = (int)*out++; *g++ = (int)*out++; *b++ = (int)*out++; } free(inbuf); free(outbuf); }/* if(image->numcomps */ cmsDeleteTransform(transform); #ifdef OPJ_HAVE_LIBLCMS1 cmsCloseProfile(in_prof); cmsCloseProfile(out_prof); #endif }/* color_apply_icc_profile() */
void SPImage::apply_profile(Inkscape::Pixbuf *pixbuf) { // TODO: this will prevent using MIME data when exporting. // Integrate color correction into loading. pixbuf->ensurePixelFormat(Inkscape::Pixbuf::PF_GDK); int imagewidth = pixbuf->width(); int imageheight = pixbuf->height(); int rowstride = pixbuf->rowstride();; guchar* px = pixbuf->pixels(); if ( px ) { DEBUG_MESSAGE( lcmsFive, "in <image>'s sp_image_update. About to call colorprofile_get_handle()" ); guint profIntent = Inkscape::RENDERING_INTENT_UNKNOWN; cmsHPROFILE prof = Inkscape::CMSSystem::getHandle( this->document, &profIntent, this->color_profile ); if ( prof ) { cmsProfileClassSignature profileClass = cmsGetDeviceClass( prof ); if ( profileClass != cmsSigNamedColorClass ) { int intent = INTENT_PERCEPTUAL; switch ( profIntent ) { case Inkscape::RENDERING_INTENT_RELATIVE_COLORIMETRIC: intent = INTENT_RELATIVE_COLORIMETRIC; break; case Inkscape::RENDERING_INTENT_SATURATION: intent = INTENT_SATURATION; break; case Inkscape::RENDERING_INTENT_ABSOLUTE_COLORIMETRIC: intent = INTENT_ABSOLUTE_COLORIMETRIC; break; case Inkscape::RENDERING_INTENT_PERCEPTUAL: case Inkscape::RENDERING_INTENT_UNKNOWN: case Inkscape::RENDERING_INTENT_AUTO: default: intent = INTENT_PERCEPTUAL; } cmsHPROFILE destProf = cmsCreate_sRGBProfile(); cmsHTRANSFORM transf = cmsCreateTransform( prof, TYPE_RGBA_8, destProf, TYPE_RGBA_8, intent, 0 ); if ( transf ) { guchar* currLine = px; for ( int y = 0; y < imageheight; y++ ) { // Since the types are the same size, we can do the transformation in-place cmsDoTransform( transf, currLine, currLine, imagewidth ); currLine += rowstride; } cmsDeleteTransform( transf ); } else { DEBUG_MESSAGE( lcmsSix, "in <image>'s sp_image_update. Unable to create LCMS transform." ); } cmsCloseProfile( destProf ); } else { DEBUG_MESSAGE( lcmsSeven, "in <image>'s sp_image_update. Profile type is named color. Can't transform." ); } } else { DEBUG_MESSAGE( lcmsEight, "in <image>'s sp_image_update. No profile found." ); } } }
void CLASS apply_profile (const char *input, const char *output) { char *prof; cmsHPROFILE hInProfile=0, hOutProfile=0; cmsHTRANSFORM hTransform; FILE *fp; unsigned size; #ifndef USE_LCMS2 cmsErrorAction (LCMS_ERROR_SHOW); #endif if (strcmp (input, "embed")) hInProfile = cmsOpenProfileFromFile (input, "r"); else if (profile_length) { #ifndef LIBRAW_LIBRARY_BUILD prof = (char *) malloc (profile_length); merror (prof, "apply_profile()"); fseek (ifp, profile_offset, SEEK_SET); fread (prof, 1, profile_length, ifp); hInProfile = cmsOpenProfileFromMem (prof, profile_length); free (prof); #else hInProfile = cmsOpenProfileFromMem (imgdata.color.profile, profile_length); #endif } else { #ifdef LIBRAW_LIBRARY_BUILD imgdata.process_warnings |= LIBRAW_WARN_NO_EMBEDDED_PROFILE; #endif #ifdef DCRAW_VERBOSE fprintf (stderr,_("%s has no embedded profile.\n"), ifname); #endif } if (!hInProfile) { #ifdef LIBRAW_LIBRARY_BUILD imgdata.process_warnings |= LIBRAW_WARN_NO_INPUT_PROFILE; #endif return; } if (!output) hOutProfile = cmsCreate_sRGBProfile(); else if ((fp = fopen (output, "rb"))) { fread (&size, 4, 1, fp); fseek (fp, 0, SEEK_SET); oprof = (unsigned *) malloc (size = ntohl(size)); merror (oprof, "apply_profile()"); fread (oprof, 1, size, fp); fclose (fp); if (!(hOutProfile = cmsOpenProfileFromMem (oprof, size))) { free (oprof); oprof = 0; } } #ifdef DCRAW_VERBOSE else fprintf (stderr,_("Cannot open file %s!\n"), output); #endif if (!hOutProfile) { #ifdef LIBRAW_LIBRARY_BUILD imgdata.process_warnings |= LIBRAW_WARN_BAD_OUTPUT_PROFILE; #endif goto quit; } #ifdef DCRAW_VERBOSE if (verbose) fprintf (stderr,_("Applying color profile...\n")); #endif #ifdef LIBRAW_LIBRARY_BUILD RUN_CALLBACK(LIBRAW_PROGRESS_APPLY_PROFILE,0,2); #endif hTransform = cmsCreateTransform (hInProfile, TYPE_RGBA_16, hOutProfile, TYPE_RGBA_16, INTENT_PERCEPTUAL, 0); cmsDoTransform (hTransform, image, image, width*height); raw_color = 1; /* Don't use rgb_cam with a profile */ cmsDeleteTransform (hTransform); cmsCloseProfile (hOutProfile); quit: cmsCloseProfile (hInProfile); #ifdef LIBRAW_LIBRARY_BUILD RUN_CALLBACK(LIBRAW_PROGRESS_APPLY_PROFILE,1,2); #endif }
static void cdisplay_lcms_changed (GimpColorDisplay *display) { CdisplayLcms *lcms = CDISPLAY_LCMS (display); GimpColorConfig *config = gimp_color_display_get_config (display); cmsHPROFILE src_profile = NULL; cmsHPROFILE dest_profile = NULL; cmsHPROFILE proof_profile = NULL; cmsUInt32Number flags = 0; cmsUInt16Number alarmCodes[cmsMAXCHANNELS] = { 0, }; if (lcms->transform) { cmsDeleteTransform (lcms->transform); lcms->transform = NULL; } if (! config) return; switch (config->mode) { case GIMP_COLOR_MANAGEMENT_OFF: return; case GIMP_COLOR_MANAGEMENT_SOFTPROOF: proof_profile = cdisplay_lcms_get_printer_profile (lcms); /* fallthru */ case GIMP_COLOR_MANAGEMENT_DISPLAY: src_profile = cdisplay_lcms_get_rgb_profile (lcms); dest_profile = cdisplay_lcms_get_display_profile (lcms); break; } if (config->display_intent == GIMP_COLOR_RENDERING_INTENT_RELATIVE_COLORIMETRIC) { flags |= cmsFLAGS_BLACKPOINTCOMPENSATION; } if (proof_profile) { if (! src_profile) src_profile = cmsCreate_sRGBProfile (); if (! dest_profile) dest_profile = cmsCreate_sRGBProfile (); flags |= cmsFLAGS_SOFTPROOFING; if (config->simulation_gamut_check) { guchar r, g, b; flags |= cmsFLAGS_GAMUTCHECK; gimp_rgb_get_uchar (&config->out_of_gamut_color, &r, &g, &b); alarmCodes[0] = (cmsUInt16Number) r * 256; alarmCodes[1] = (cmsUInt16Number) g * 256; alarmCodes[2] = (cmsUInt16Number) b * 256; cmsSetAlarmCodes (alarmCodes); } lcms->transform = cmsCreateProofingTransform (src_profile, TYPE_ARGB_8, dest_profile, TYPE_ARGB_8, proof_profile, config->simulation_intent, config->display_intent, flags); cmsCloseProfile (proof_profile); } else if (src_profile || dest_profile) { if (! src_profile) src_profile = cmsCreate_sRGBProfile (); if (! dest_profile) dest_profile = cmsCreate_sRGBProfile (); lcms->transform = cmsCreateTransform (src_profile, TYPE_ARGB_8, dest_profile, TYPE_ARGB_8, config->display_intent, flags); } if (dest_profile) cmsCloseProfile (dest_profile); if (src_profile) cmsCloseProfile (src_profile); }