static cmsHPROFILE _create_profile(gchar *iccprofile) { cmsHPROFILE profile = NULL; if(!strcmp(iccprofile, "sRGB")) { // default: sRGB profile = dt_colorspaces_create_srgb_profile(); } else if(!strcmp(iccprofile, "linear_rec709_rgb") || !strcmp(iccprofile, "linear_rgb")) { profile = dt_colorspaces_create_linear_rec709_rgb_profile(); } else if(!strcmp(iccprofile, "linear_rec2020_rgb")) { profile = dt_colorspaces_create_linear_rec2020_rgb_profile(); } else if(!strcmp(iccprofile, "adobergb")) { profile = dt_colorspaces_create_adobergb_profile(); } else if(!strcmp(iccprofile, "X profile")) { // x default pthread_rwlock_rdlock(&darktable.control->xprofile_lock); if(darktable.control->xprofile_data) profile = cmsOpenProfileFromMem(darktable.control->xprofile_data, darktable.control->xprofile_size); pthread_rwlock_unlock(&darktable.control->xprofile_lock); } else { // else: load file name char filename[PATH_MAX]; dt_colorspaces_find_profile(filename, sizeof(filename), iccprofile, "out"); profile = cmsOpenProfileFromFile(filename, "r"); } /* if no match lets fallback to srgb profile */ if (!profile) profile = dt_colorspaces_create_srgb_profile(); return profile; }
/* * Class: sun_java2d_cmm_lcms_LCMS * Method: loadProfile * Signature: ([B)J */ JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_loadProfile (JNIEnv *env, jobject obj, jbyteArray data) { jbyte* dataArray; jint dataSize; storeID_t sProf; dataArray = (*env)->GetByteArrayElements (env, data, 0); dataSize = (*env)->GetArrayLength (env, data); sProf.pf = cmsOpenProfileFromMem((LPVOID)dataArray, (DWORD) dataSize); (*env)->ReleaseByteArrayElements (env, data, dataArray, 0); if (sProf.pf == NULL) { JNU_ThrowIllegalArgumentException(env, "Invalid profile data"); } return sProf.j; }
static PyObject* cms_profile_fromstring(PyObject* self, PyObject* args) { cmsHPROFILE hProfile; char* pProfile; int nProfile; if (!PyArg_ParseTuple(args, "s#:profile_fromstring", &pProfile, &nProfile)) return NULL; cmsErrorAction(LCMS_ERROR_IGNORE); hProfile = cmsOpenProfileFromMem(pProfile, nProfile); if (!hProfile) { PyErr_SetString(PyExc_IOError, "cannot open profile from string"); return NULL; } return cms_profile_new(hProfile); }
ScColorProfile ScLcms2ColorMgmtEngineImpl::openProfileFromMem(ScColorMgmtEngine& engine, const QByteArray& data) { ScColorProfile profile; cmsHPROFILE lcmsProf = cmsOpenProfileFromMem((const void *) data.data(), data.size()); if (lcmsProf) { ScLcms2ColorProfileImpl* profData = new ScLcms2ColorProfileImpl(engine, lcmsProf); QString desc = profData->productDescription(); if (!desc.isEmpty()) profData->m_profilePath = QString("memprofile://%1").arg(desc); profData->m_profileData = data; profile = ScColorProfile(dynamic_cast<ScColorProfileData*>(profData)); } if (profile.isNull() && lcmsProf) { cmsCloseProfile(lcmsProf); lcmsProf = NULL; } return profile; }
static cmsHPROFILE lcms_load_profile (const gchar *filename, guchar *checksum) { cmsHPROFILE profile; GMappedFile *file; gchar *data; gsize len; GError *error = NULL; g_return_val_if_fail (filename != NULL, NULL); file = g_mapped_file_new (filename, FALSE, &error); if (! file) { g_message ("%s", error->message); g_error_free (error); return NULL; } data = g_mapped_file_get_contents (file); len = g_mapped_file_get_length (file); profile = cmsOpenProfileFromMem (data, len); if (profile) { lcms_calculate_checksum (data, len, checksum); } else { g_message (_("Could not load ICC profile from '%s'"), gimp_filename_to_utf8 (filename)); } g_mapped_file_unref (file); return profile; }
/** * gimp_color_profile_new_from_lcms_profile: * @lcms_profile: an LCMS cmsHPROFILE pointer * @error: return location for #GError * * This function creates a GimpColorProfile from a cmsHPROFILE. On * error, %NULL is returned and @error is set. The passed * @lcms_profile pointer is not retained by the created * #GimpColorProfile. * * Return value: the #GimpColorProfile, or %NULL. * * Since: 2.10 **/ GimpColorProfile * gimp_color_profile_new_from_lcms_profile (gpointer lcms_profile, GError **error) { cmsUInt32Number size; g_return_val_if_fail (lcms_profile != NULL, NULL); g_return_val_if_fail (error == NULL || *error == NULL, NULL); if (cmsSaveProfileToMem (lcms_profile, NULL, &size)) { guint8 *data = g_malloc (size); if (cmsSaveProfileToMem (lcms_profile, data, &size)) { gsize length = size; lcms_profile = cmsOpenProfileFromMem (data, length); if (lcms_profile) { GimpColorProfile *profile; profile = g_object_new (GIMP_TYPE_COLOR_PROFILE, NULL); profile->priv->lcms_profile = lcms_profile; profile->priv->data = data; profile->priv->length = length; return profile; } } g_free (data); } g_set_error_literal (error, gimp_color_profile_error_quark (), 0, _("Could not save color profile to memory")); return NULL; }
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 HAVE_X11 if (QX11Info::isPlatformX11()) { // 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) { return getSRgbProfile(); } return Profile::Ptr(new Profile(hProfile)); }
static cmsHPROFILE cdisplay_lcms_get_rgb_profile (CdisplayLcms *lcms) { GimpColorConfig *config; GimpColorManaged *managed; cmsHPROFILE profile = NULL; managed = gimp_color_display_get_managed (GIMP_COLOR_DISPLAY (lcms)); if (managed) { gsize len; const guint8 *data = gimp_color_managed_get_icc_profile (managed, &len); if (data) profile = cmsOpenProfileFromMem ((gpointer) data, len); if (profile && ! gimp_lcms_profile_is_rgb (profile)) { cmsCloseProfile (profile); profile = NULL; } } if (! profile) { config = gimp_color_display_get_config (GIMP_COLOR_DISPLAY (lcms)); if (config->rgb_profile) profile = cmsOpenProfileFromFile (config->rgb_profile, "r"); if (profile && ! gimp_lcms_profile_is_rgb (profile)) { cmsCloseProfile (profile); profile = NULL; } } return profile; }
static cmsHPROFILE _create_profile(gchar *iccprofile) { cmsHPROFILE profile = NULL; if(!strcmp(iccprofile, "sRGB")) { // default: sRGB profile = dt_colorspaces_create_srgb_profile(); } else if(!strcmp(iccprofile, "linear_rgb")) { profile = dt_colorspaces_create_linear_rgb_profile(); } else if(!strcmp(iccprofile, "adobergb")) { profile = dt_colorspaces_create_adobergb_profile(); } else if(!strcmp(iccprofile, "X profile")) { // x default if(darktable.control->xprofile_data) profile = cmsOpenProfileFromMem(darktable.control->xprofile_data, darktable.control->xprofile_size); else profile = NULL; } else { // else: load file name char filename[1024]; dt_colorspaces_find_profile(filename, 1024, iccprofile, "out"); profile = cmsOpenProfileFromFile(filename, "r"); } /* if no match lets fallback to srgb profile */ if (!profile) profile = dt_colorspaces_create_srgb_profile(); return profile; }
static cmsHPROFILE lcms_image_get_profile (GimpColorConfig *config, gint32 image, guchar *checksum) { GimpParasite *parasite; cmsHPROFILE profile = NULL; g_return_val_if_fail (image != -1, NULL); parasite = gimp_image_get_parasite (image, "icc-profile"); if (parasite) { profile = cmsOpenProfileFromMem ((gpointer) gimp_parasite_data (parasite), gimp_parasite_data_size (parasite)); if (profile) { lcms_calculate_checksum (gimp_parasite_data (parasite), gimp_parasite_data_size (parasite), checksum); } else { g_message (_("Data attached as 'icc-profile' does not appear to " "be an ICC color profile")); } gimp_parasite_free (parasite); } else if (config->rgb_profile) { profile = lcms_load_profile (config->rgb_profile, checksum); } return profile; }
static PyObject* cms_profile_fromstring(PyObject* self, PyObject* args) { cmsHPROFILE hProfile; char* pProfile; int nProfile; #if PY_VERSION_HEX >= 0x03000000 if (!PyArg_ParseTuple(args, "y#:profile_frombytes", &pProfile, &nProfile)) return NULL; #else if (!PyArg_ParseTuple(args, "s#:profile_fromstring", &pProfile, &nProfile)) return NULL; #endif hProfile = cmsOpenProfileFromMem(pProfile, nProfile); if (!hProfile) { PyErr_SetString(PyExc_IOError, "cannot open profile from string"); return NULL; } return cms_profile_new(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]); }
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); };
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; }
static gboolean lcms_image_set_profile (gint32 image, cmsHPROFILE profile, const gchar *filename, gboolean undo_group) { g_return_val_if_fail (image != -1, FALSE); if (filename) { GimpParasite *parasite; GMappedFile *file; GError *error = NULL; file = g_mapped_file_new (filename, FALSE, &error); if (! file) { g_message ("%s", error->message); g_error_free (error); return FALSE; } /* check that this file is actually an ICC profile */ if (! profile) { profile = cmsOpenProfileFromMem (g_mapped_file_get_contents (file), g_mapped_file_get_length (file)); if (profile) { cmsCloseProfile (profile); } else { g_message (_("'%s' does not appear to be an ICC color profile"), gimp_filename_to_utf8 (filename)); return FALSE; } } if (undo_group) gimp_image_undo_group_start (image); parasite = gimp_parasite_new ("icc-profile", GIMP_PARASITE_PERSISTENT | GIMP_PARASITE_UNDOABLE, g_mapped_file_get_length (file), g_mapped_file_get_contents (file)); g_mapped_file_unref (file); gimp_image_attach_parasite (image, parasite); gimp_parasite_free (parasite); } else { if (undo_group) gimp_image_undo_group_start (image); gimp_image_detach_parasite (image, "icc-profile"); } gimp_image_detach_parasite (image, "icc-profile-name"); if (undo_group) gimp_image_undo_group_end (image); return TRUE; }
// Get the display ICC profile of the monitor associated with the widget. // For X display, uses the ICC profile specifications version 0.2 from // http://burtonini.com/blog/computers/xicc // Based on code from Gimp's modules/cdisplay_lcms.c void dt_ctl_set_display_profile() { if(!dt_control_running()) return; // make sure that no one gets a broken profile // FIXME: benchmark if the try is really needed when moving/resizing the window. Maybe we can just lock it and block if(pthread_rwlock_trywrlock(&darktable.control->xprofile_lock)) return; // we are already updating the profile. Or someone is reading right now. Too bad we can't distinguish that. Whatever ... GtkWidget *widget = dt_ui_center(darktable.gui->ui); guint8 *buffer = NULL; gint buffer_size = 0; gchar *profile_source = NULL; #if defined GDK_WINDOWING_X11 // we will use the xatom no matter what configured when compiled without colord gboolean use_xatom = TRUE; #if defined USE_COLORDGTK gboolean use_colord = TRUE; gchar *display_profile_source = dt_conf_get_string("ui_last/display_profile_source"); if(display_profile_source) { if(!strcmp(display_profile_source, "xatom")) use_colord = FALSE; else if(!strcmp(display_profile_source, "colord")) use_xatom = FALSE; g_free(display_profile_source); } #endif /* let's have a look at the xatom, just in case ... */ if(use_xatom) { GdkScreen *screen = gtk_widget_get_screen(widget); if ( screen==NULL ) screen = gdk_screen_get_default(); int monitor = gdk_screen_get_monitor_at_window (screen, gtk_widget_get_window(widget)); char *atom_name; if (monitor > 0) atom_name = g_strdup_printf("_ICC_PROFILE_%d", monitor); else atom_name = g_strdup("_ICC_PROFILE"); profile_source = g_strdup_printf("xatom %s", atom_name); GdkAtom type = GDK_NONE; gint format = 0; gdk_property_get(gdk_screen_get_root_window(screen), gdk_atom_intern(atom_name, FALSE), GDK_NONE, 0, 64 * 1024 * 1024, FALSE, &type, &format, &buffer_size, &buffer); g_free(atom_name); } #ifdef USE_COLORDGTK /* also try to get the profile from colord. this will set the value asynchronously! */ if(use_colord) { CdWindow *window = cd_window_new(); GtkWidget *center_widget = dt_ui_center(darktable.gui->ui); cd_window_get_profile(window, center_widget, NULL, dt_ctl_get_display_profile_colord_callback, NULL); } #endif #elif defined GDK_WINDOWING_QUARTZ GdkScreen *screen = gtk_widget_get_screen(widget); if ( screen==NULL ) screen = gdk_screen_get_default(); int monitor = gdk_screen_get_monitor_at_window(screen, gtk_widget_get_window(widget)); CGDirectDisplayID ids[monitor + 1]; uint32_t total_ids; CMProfileRef prof = NULL; if(CGGetOnlineDisplayList(monitor + 1, &ids[0], &total_ids) == kCGErrorSuccess && total_ids == monitor + 1) CMGetProfileByAVID(ids[monitor], &prof); if ( prof!=NULL ) { CFDataRef data; data = CMProfileCopyICCData(NULL, prof); CMCloseProfile(prof); UInt8 *tmp_buffer = (UInt8 *) g_malloc(CFDataGetLength(data)); CFDataGetBytes(data, CFRangeMake(0, CFDataGetLength(data)), tmp_buffer); buffer = (guint8 *) tmp_buffer; buffer_size = CFDataGetLength(data); CFRelease(data); } profile_source = g_strdup("osx color profile api"); #elif defined G_OS_WIN32 (void)widget; HDC hdc = GetDC (NULL); if ( hdc!=NULL ) { DWORD len = 0; GetICMProfile (hdc, &len, NULL); gchar *path = g_new (gchar, len); if (GetICMProfile (hdc, &len, path)) { gsize size; g_file_get_contents(path, (gchar**)&buffer, &size, NULL); buffer_size = size; } g_free (path); ReleaseDC (NULL, hdc); } profile_source = g_strdup("windows color profile api"); #endif int profile_changed = buffer_size > 0 && (darktable.control->xprofile_size != buffer_size || memcmp(darktable.control->xprofile_data, buffer, buffer_size) != 0); if(profile_changed) { cmsHPROFILE profile = NULL; char name[512]; // thanks to ufraw for this! g_free(darktable.control->xprofile_data); darktable.control->xprofile_data = buffer; darktable.control->xprofile_size = buffer_size; profile = cmsOpenProfileFromMem(buffer, buffer_size); if(profile) { dt_colorspaces_get_profile_name(profile, "en", "US", name, sizeof(name)); cmsCloseProfile(profile); } dt_print(DT_DEBUG_CONTROL, "[color profile] we got a new screen profile `%s' from the %s (size: %d)\n", *name?name:"(unknown)", profile_source, buffer_size); } pthread_rwlock_unlock(&darktable.control->xprofile_lock); if(profile_changed) dt_control_signal_raise(darktable.signals, DT_SIGNAL_CONTROL_PROFILE_CHANGED); g_free(profile_source); }
/** * gimp_color_profile_new_from_file: * @file: a #GFile * @error: return location for #GError * * This function opens an ICC color profile from @file. * * Return value: the #GimpColorProfile, or %NULL. On error, %NULL is * returned and @error is set. * * Since: 2.10 **/ GimpColorProfile * gimp_color_profile_new_from_file (GFile *file, GError **error) { GimpColorProfile *profile = NULL; cmsHPROFILE lcms_profile = NULL; guint8 *data = NULL; gsize length = 0; gchar *path; g_return_val_if_fail (G_IS_FILE (file), NULL); g_return_val_if_fail (error == NULL || *error == NULL, NULL); path = g_file_get_path (file); if (path) { GMappedFile *mapped; mapped = g_mapped_file_new (path, FALSE, error); if (! mapped) return NULL; length = g_mapped_file_get_length (mapped); data = g_memdup (g_mapped_file_get_contents (mapped), length); lcms_profile = cmsOpenProfileFromMem (data, length); g_mapped_file_unref (mapped); } else { GFileInfo *info; info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_SIZE, G_FILE_QUERY_INFO_NONE, NULL, error); if (info) { GInputStream *input; length = g_file_info_get_size (info); data = g_malloc (length); g_object_unref (info); input = G_INPUT_STREAM (g_file_read (file, NULL, error)); if (input) { gsize bytes_read; if (g_input_stream_read_all (input, data, length, &bytes_read, NULL, error) && bytes_read == length) { lcms_profile = cmsOpenProfileFromMem (data, length); } g_object_unref (input); } } } if (lcms_profile) { profile = g_object_new (GIMP_TYPE_COLOR_PROFILE, NULL); profile->priv->lcms_profile = lcms_profile; profile->priv->data = data; profile->priv->length = length; } else { if (data) g_free (data); if (error && *error == NULL) { g_set_error (error, gimp_color_profile_error_quark (), 0, _("'%s' does not appear to be an ICC color profile"), gimp_file_get_utf8_name (file)); } } return profile; }
static int TransformImage(char *cDefInpProf, char *cOutProf) { cmsHPROFILE hIn, hOut, hProof; cmsHTRANSFORM xform; cmsUInt32Number wInput, wOutput; int OutputColorSpace; cmsUInt32Number dwFlags = 0; cmsUInt32Number EmbedLen; cmsUInt8Number* EmbedBuffer; cmsSetAdaptationState(ObserverAdaptationState); if (BlackPointCompensation) { dwFlags |= cmsFLAGS_BLACKPOINTCOMPENSATION; } switch (PrecalcMode) { case 0: dwFlags |= cmsFLAGS_NOOPTIMIZE; break; case 2: dwFlags |= cmsFLAGS_HIGHRESPRECALC; break; case 3: dwFlags |= cmsFLAGS_LOWRESPRECALC; break; default:; } if (GamutCheck) { dwFlags |= cmsFLAGS_GAMUTCHECK; cmsSetAlarmCodes(Alarm); } // Take input color space wInput = GetInputPixelType(); if (lIsDeviceLink) { hIn = cmsOpenProfileFromFile(cDefInpProf, "r"); hOut = NULL; hProof = NULL; } else { if (!IgnoreEmbedded && read_icc_profile(&Decompressor, &EmbedBuffer, &EmbedLen)) { hIn = cmsOpenProfileFromMem(EmbedBuffer, EmbedLen); if (Verbose) { fprintf(stdout, " (Embedded profile found)\n"); PrintProfileInformation(hIn); fflush(stdout); } if (hIn != NULL && SaveEmbedded != NULL) SaveMemoryBlock(EmbedBuffer, EmbedLen, SaveEmbedded); free(EmbedBuffer); } else { // Default for ITU/Fax if (cDefInpProf == NULL && T_COLORSPACE(wInput) == PT_Lab) cDefInpProf = "*Lab"; if (cDefInpProf != NULL && cmsstrcasecmp(cDefInpProf, "*lab") == 0) hIn = CreateITU2PCS_ICC(); else hIn = OpenStockProfile(0, cDefInpProf); } if (cOutProf != NULL && cmsstrcasecmp(cOutProf, "*lab") == 0) hOut = CreatePCS2ITU_ICC(); else hOut = OpenStockProfile(0, cOutProf); hProof = NULL; if (cProofing != NULL) { hProof = OpenStockProfile(0, cProofing); if (hProof == NULL) { FatalError("Proofing profile couldn't be read."); } dwFlags |= cmsFLAGS_SOFTPROOFING; } } if (!hIn) FatalError("Input profile couldn't be read."); if (!hOut) FatalError("Output profile couldn't be read."); // Assure both, input profile and input JPEG are on same colorspace if (cmsGetColorSpace(hIn) != _cmsICCcolorSpace(T_COLORSPACE(wInput))) FatalError("Input profile is not operating in proper color space"); // Output colorspace is given by output profile if (lIsDeviceLink) { OutputColorSpace = GetDevicelinkColorSpace(hIn); } else { OutputColorSpace = GetProfileColorSpace(hOut); } jpeg_copy_critical_parameters(&Decompressor, &Compressor); WriteOutputFields(OutputColorSpace); wOutput = ComputeOutputFormatDescriptor(wInput, OutputColorSpace); xform = cmsCreateProofingTransform(hIn, wInput, hOut, wOutput, hProof, Intent, ProofingIntent, dwFlags); if (xform == NULL) FatalError("Cannot transform by using the profiles"); DoTransform(xform, OutputColorSpace); jcopy_markers_execute(&Decompressor, &Compressor); cmsDeleteTransform(xform); cmsCloseProfile(hIn); cmsCloseProfile(hOut); if (hProof) cmsCloseProfile(hProof); return 1; }
mng_cmsprof mnglcms_creatememprofile (mng_uint32 iProfilesize, mng_ptr pProfile) { return cmsOpenProfileFromMem (pProfile, iProfilesize); }
static cmsHPROFILE cdisplay_lcms_get_display_profile (CdisplayLcms *lcms) { GimpColorConfig *config; cmsHPROFILE profile = NULL; config = gimp_color_display_get_config (GIMP_COLOR_DISPLAY (lcms)); #if defined GDK_WINDOWING_X11 if (config->display_profile_from_gdk) { GdkScreen *screen; GdkAtom type = GDK_NONE; gint format = 0; gint nitems = 0; gint monitor = 0; gchar *atom_name; guchar *data = NULL; screen = cdisplay_lcms_get_screen (lcms, &monitor); if (monitor > 0) atom_name = g_strdup_printf ("_ICC_PROFILE_%d", monitor); else atom_name = g_strdup ("_ICC_PROFILE"); if (gdk_property_get (gdk_screen_get_root_window (screen), gdk_atom_intern (atom_name, FALSE), GDK_NONE, 0, 64 * 1024 * 1024, FALSE, &type, &format, &nitems, &data) && nitems > 0) { profile = cmsOpenProfileFromMem (data, nitems); g_free (data); } g_free (atom_name); } #elif defined GDK_WINDOWING_QUARTZ if (config->display_profile_from_gdk) { CMProfileRef prof = NULL; gint monitor = 0; cdisplay_lcms_get_screen (lcms, &monitor); CMGetProfileByAVID (monitor, &prof); if (prof) { CFDataRef data; data = CMProfileCopyICCData (NULL, prof); CMCloseProfile (prof); if (data) { UInt8 *buffer = g_malloc (CFDataGetLength (data)); /* We cannot use CFDataGetBytesPtr(), because that returns * a const pointer where cmsOpenProfileFromMem wants a * non-const pointer. */ CFDataGetBytes (data, CFRangeMake (0, CFDataGetLength (data)), buffer); profile = cmsOpenProfileFromMem (buffer, CFDataGetLength (data)); g_free (buffer); CFRelease (data); } } } #elif defined G_OS_WIN32 if (config->display_profile_from_gdk) { HDC hdc = GetDC (NULL); if (hdc) { gchar *path; gint32 len = 0; GetICMProfile (hdc, &len, NULL); path = g_new (gchar, len); if (GetICMProfile (hdc, &len, path)) profile = cmsOpenProfileFromFile (path, "r"); g_free (path); ReleaseDC (NULL, hdc); } } #endif if (! profile && config->display_profile) profile = cmsOpenProfileFromFile (config->display_profile, "r"); return profile; }
static cmsHPROFILE GetTIFFProfile(TIFF* in) { cmsCIExyYTRIPLE Primaries; float* chr; cmsCIExyY WhitePoint; float* wp; int i; LPGAMMATABLE Gamma[3]; LPWORD gmr, gmg, gmb; cmsHPROFILE hProfile; DWORD EmbedLen; LPBYTE EmbedBuffer; if (IgnoreEmbedded) return NULL; if (TIFFGetField(in, TIFFTAG_ICCPROFILE, &EmbedLen, &EmbedBuffer)) { hProfile = cmsOpenProfileFromMem(EmbedBuffer, EmbedLen); if (Verbose) { fprintf(stdout, " (Embedded profile found)\n"); fprintf(stdout, "Product name: %s\n", cmsTakeProductName(hProfile)); fprintf(stdout, "Description : %s\n", cmsTakeProductDesc(hProfile)); fflush(stdout); } if (hProfile != NULL && SaveEmbedded != NULL) SaveMemoryBlock(EmbedBuffer, EmbedLen, SaveEmbedded); if (hProfile) return hProfile; } // Try to see if "colorimetric" tiff if (TIFFGetField(in, TIFFTAG_PRIMARYCHROMATICITIES, &chr)) { Primaries.Red.x = chr[0]; Primaries.Red.y = chr[1]; Primaries.Green.x = chr[2]; Primaries.Green.y = chr[3]; Primaries.Blue.x = chr[4]; Primaries.Blue.y = chr[5]; Primaries.Red.Y = Primaries.Green.Y = Primaries.Blue.Y = 1.0; if (TIFFGetField(in, TIFFTAG_WHITEPOINT, &wp)) { WhitePoint.x = wp[0]; WhitePoint.y = wp[1]; WhitePoint.Y = 1.0; // Transferfunction is a bit harder.... for (i=0; i < 3; i++) Gamma[i] = cmsAllocGamma(256); TIFFGetFieldDefaulted(in, TIFFTAG_TRANSFERFUNCTION, &gmr, &gmg, &gmb); CopyMemory(Gamma[0]->GammaTable, gmr, 256*sizeof(WORD)); CopyMemory(Gamma[1]->GammaTable, gmg, 256*sizeof(WORD)); CopyMemory(Gamma[2]->GammaTable, gmb, 256*sizeof(WORD)); hProfile = cmsCreateRGBProfile(&WhitePoint, &Primaries, Gamma); for (i=0; i < 3; i++) cmsFreeGamma(Gamma[i]); if (Verbose) { fprintf(stdout, " (Colorimetric TIFF)\n"); } return hProfile; } } return NULL; }
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; }
cmsHPROFILE dt_colorspaces_create_output_profile(const int imgid) { char profile[1024]; profile[0] = '\0'; // db lookup colorout params, and dt_conf_() for override gchar *overprofile = dt_conf_get_string("plugins/lighttable/export/iccprofile"); if(!overprofile || !strcmp(overprofile, "image")) { const dt_iop_colorout_params_t *params; // sqlite: sqlite3_stmt *stmt; DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select op_params from history where imgid=?1 and operation='colorout'", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid); if(sqlite3_step(stmt) == SQLITE_ROW) { params = sqlite3_column_blob(stmt, 0); g_strlcpy(profile, params->iccprofile, 1024); } sqlite3_finalize(stmt); } if(!overprofile && profile[0] == '\0') { g_strlcpy(profile, "sRGB", 1024); } else if(profile[0] == '\0') { g_strlcpy(profile, overprofile, 1024); } if(overprofile) { g_free(overprofile); } cmsHPROFILE output = NULL; if(!strcmp(profile, "sRGB")) output = dt_colorspaces_create_srgb_profile(); else if(!strcmp(profile, "linear_rgb")) output = dt_colorspaces_create_linear_rgb_profile(); else if(!strcmp(profile, "XYZ")) output = dt_colorspaces_create_xyz_profile(); else if(!strcmp(profile, "adobergb")) output = dt_colorspaces_create_adobergb_profile(); else if(!strcmp(profile, "X profile")) { pthread_rwlock_rdlock(&darktable.control->xprofile_lock); if(darktable.control->xprofile_data) output = cmsOpenProfileFromMem(darktable.control->xprofile_data, darktable.control->xprofile_size); pthread_rwlock_unlock(&darktable.control->xprofile_lock); } else { // else: load file name char filename[DT_MAX_PATH_LEN]; dt_colorspaces_find_profile(filename, DT_MAX_PATH_LEN, profile, "out"); output = cmsOpenProfileFromFile(filename, "r"); } if(!output) output = dt_colorspaces_create_srgb_profile(); return output; }
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 int TransformImage(char *cDefInpProf, char *cOutProf) { cmsHPROFILE hIn, hOut, hProof; cmsHTRANSFORM xform; DWORD wInput, wOutput; int OutputColorSpace; DWORD dwFlags = 0; DWORD EmbedLen; LPBYTE EmbedBuffer; if (BlackPointCompensation) { dwFlags |= cmsFLAGS_BLACKPOINTCOMPENSATION; } switch (PrecalcMode) { case 0: dwFlags |= cmsFLAGS_NOTPRECALC; break; case 2: dwFlags |= cmsFLAGS_HIGHRESPRECALC; break; case 3: dwFlags |= cmsFLAGS_LOWRESPRECALC; break; default:; } if (GamutCheck) dwFlags |= cmsFLAGS_GAMUTCHECK; if (lIsDeviceLink) { hIn = cmsOpenProfileFromFile(cDefInpProf, "r"); hOut = NULL; hProof = NULL; } else { if (!IgnoreEmbedded && read_icc_profile(&Decompressor, &EmbedBuffer, &EmbedLen)) { hIn = cmsOpenProfileFromMem(EmbedBuffer, EmbedLen); if (Verbose) { fprintf(stdout, " (Embedded profile found)\n"); fprintf(stdout, "Product name: %s\n", cmsTakeProductName(hIn)); fprintf(stdout, "Description : %s\n", cmsTakeProductDesc(hIn)); fflush(stdout); } if (hIn != NULL && SaveEmbedded != NULL) SaveMemoryBlock(EmbedBuffer, EmbedLen, SaveEmbedded); free(EmbedBuffer); } else { hIn = OpenStockProfile(cDefInpProf); } hOut = OpenStockProfile(cOutProf); hProof = NULL; if (cProofing != NULL) { hProof = OpenStockProfile(cProofing); } } // Take input color space wInput = GetInputPixelType(); // Assure both, input profile and input JPEG are on same colorspace if (cmsGetColorSpace(hIn) != _cmsICCcolorSpace(T_COLORSPACE(wInput))) FatalError("Input profile is not operating in proper color space"); // Output colorspace is given by output profile if (lIsDeviceLink) { OutputColorSpace = T_COLORSPACE(wInput); } else { OutputColorSpace = GetProfileColorSpace(hOut); } jpeg_copy_critical_parameters(&Decompressor, &Compressor); WriteOutputFields(OutputColorSpace); wOutput = ComputeOutputFormatDescriptor(wInput, OutputColorSpace); xform = cmsCreateProofingTransform(hIn, wInput, hOut, wOutput, hProof, Intent, ProofingIntent, dwFlags); // Handle tile by tile or strip by strip strtok DoTransform(xform); jcopy_markers_execute(&Decompressor, &Compressor); cmsDeleteTransform(xform); cmsCloseProfile(hIn); cmsCloseProfile(hOut); if (hProof) cmsCloseProfile(hProof); return 1; }
static gpointer jpeg_load_cmyk_transform (guint8 *profile_data, gsize profile_len) { 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) { if (! gimp_lcms_profile_is_cmyk (cmyk_profile)) { 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"); if (cmyk_profile && ! gimp_lcms_profile_is_cmyk (cmyk_profile)) { 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"); if (rgb_profile && ! gimp_lcms_profile_is_rgb (rgb_profile)) { cmsCloseProfile (rgb_profile); rgb_profile = NULL; } } /* make the real sRGB profile as a fallback */ if (! rgb_profile) { rgb_profile = gimp_lcms_create_srgb_profile (); } 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; }
cmsHPROFILE dkCmsOpenProfileFromMem(LPVOID MemPtr, DWORD dwSize) { return cmsOpenProfileFromMem(MemPtr, static_cast<cmsUInt32Number>( dwSize )); }
bool LcmsColorProfileContainer::init() { if (d->profile) { cmsCloseProfile(d->profile); } d->profile = cmsOpenProfileFromMem((void *)d->data->rawData().constData(), d->data->rawData().size()); #ifndef NDEBUG if (d->data->rawData().size() == 4096) { qWarning() << "Profile has a size of 4096, which is suspicious and indicates a possible misuse of QIODevice::read(int), check your code."; } #endif if (d->profile) { wchar_t buffer[_BUFFER_SIZE_]; d->colorSpaceSignature = cmsGetColorSpace(d->profile); d->deviceClass = cmsGetDeviceClass(d->profile); cmsGetProfileInfo(d->profile, cmsInfoDescription, cmsNoLanguage, cmsNoCountry, buffer, _BUFFER_SIZE_); d->name = QString::fromWCharArray(buffer); //apparantly this should give us a localised string??? Not sure about this. cmsGetProfileInfo(d->profile, cmsInfoModel, cmsNoLanguage, cmsNoCountry, buffer, _BUFFER_SIZE_); d->productDescription = QString::fromWCharArray(buffer); cmsGetProfileInfo(d->profile, cmsInfoManufacturer, cmsNoLanguage, cmsNoCountry, buffer, _BUFFER_SIZE_); d->manufacturer = QString::fromWCharArray(buffer); cmsGetProfileInfo(d->profile, cmsInfoCopyright, cmsNoLanguage, cmsNoCountry, buffer, _BUFFER_SIZE_); d->copyright = QString::fromWCharArray(buffer); cmsProfileClassSignature profile_class; profile_class = cmsGetDeviceClass(d->profile); d->valid = (profile_class != cmsSigNamedColorClass); //This is where obtain the whitepoint, and convert it to the actual white point of the profile in the case a Chromatic adaption tag is //present. This is necessary for profiles following the v4 spec. cmsCIEXYZ baseMediaWhitePoint;//dummy to hold copy of mediawhitepoint if this is modified by chromatic adaption. if (cmsIsTag(d->profile, cmsSigMediaWhitePointTag)) { d->mediaWhitePoint = *((cmsCIEXYZ *)cmsReadTag(d->profile, cmsSigMediaWhitePointTag)); baseMediaWhitePoint = d->mediaWhitePoint; cmsXYZ2xyY(&d->whitePoint, &d->mediaWhitePoint); if (cmsIsTag(d->profile, cmsSigChromaticAdaptationTag)) { //the chromatic adaption tag represent a matrix from the actual white point of the profile to D50. cmsCIEXYZ *CAM1 = (cmsCIEXYZ *)cmsReadTag(d->profile, cmsSigChromaticAdaptationTag); //We first put all our data into structures we can manipulate. double d3dummy [3] = {d->mediaWhitePoint.X, d->mediaWhitePoint.Y, d->mediaWhitePoint.Z}; QGenericMatrix<1, 3, double> whitePointMatrix(d3dummy); QTransform invertDummy(CAM1[0].X, CAM1[0].Y, CAM1[0].Z, CAM1[1].X, CAM1[1].Y, CAM1[1].Z, CAM1[2].X, CAM1[2].Y, CAM1[2].Z); //we then abuse QTransform's invert function because it probably does matrix invertion 20 times better than I can program. //if the matrix is uninvertable, invertedDummy will be an identity matrix, which for us means that it won't give any noticeble //effect when we start multiplying. QTransform invertedDummy = invertDummy.inverted(); //we then put the QTransform into a generic 3x3 matrix. double d9dummy [9] = {invertedDummy.m11(), invertedDummy.m12(), invertedDummy.m13(), invertedDummy.m21(), invertedDummy.m22(), invertedDummy.m23(), invertedDummy.m31(), invertedDummy.m32(), invertedDummy.m33() }; QGenericMatrix<3, 3, double> chromaticAdaptionMatrix(d9dummy); //multiplying our inverted adaption matrix with the whitepoint gives us the right whitepoint. QGenericMatrix<1, 3, double> result = chromaticAdaptionMatrix * whitePointMatrix; //and then we pour the matrix into the whitepoint variable. Generic matrix does row/column for indices even though it //uses column/row for initialising. d->mediaWhitePoint.X = result(0, 0); d->mediaWhitePoint.Y = result(1, 0); d->mediaWhitePoint.Z = result(2, 0); cmsXYZ2xyY(&d->whitePoint, &d->mediaWhitePoint); } } //This is for RGB profiles, but it only works for matrix profiles. Need to design it to work with non-matrix profiles. if (cmsIsTag(d->profile, cmsSigRedColorantTag)) { cmsCIEXYZTRIPLE tempColorants; tempColorants.Red = *((cmsCIEXYZ *)cmsReadTag(d->profile, cmsSigRedColorantTag)); tempColorants.Green = *((cmsCIEXYZ *)cmsReadTag(d->profile, cmsSigGreenColorantTag)); tempColorants.Blue = *((cmsCIEXYZ *)cmsReadTag(d->profile, cmsSigBlueColorantTag)); //convert to d65, this is useless. cmsAdaptToIlluminant(&d->colorants.Red, &baseMediaWhitePoint, &d->mediaWhitePoint, &tempColorants.Red); cmsAdaptToIlluminant(&d->colorants.Green, &baseMediaWhitePoint, &d->mediaWhitePoint, &tempColorants.Green); cmsAdaptToIlluminant(&d->colorants.Blue, &baseMediaWhitePoint, &d->mediaWhitePoint, &tempColorants.Blue); //d->colorants = tempColorants; d->hasColorants = true; } else { //qDebug()<<d->name<<": has no colorants"; d->hasColorants = false; } //retrieve TRC. if (cmsIsTag(d->profile, cmsSigRedTRCTag) && cmsIsTag(d->profile, cmsSigBlueTRCTag) && cmsIsTag(d->profile, cmsSigGreenTRCTag)) { d->redTRC = ((cmsToneCurve *)cmsReadTag (d->profile, cmsSigRedTRCTag)); d->greenTRC = ((cmsToneCurve *)cmsReadTag (d->profile, cmsSigGreenTRCTag)); d->blueTRC = ((cmsToneCurve *)cmsReadTag (d->profile, cmsSigBlueTRCTag)); d->redTRCReverse = cmsReverseToneCurve(d->redTRC); d->greenTRCReverse = cmsReverseToneCurve(d->greenTRC); d->blueTRCReverse = cmsReverseToneCurve(d->blueTRC); d->hasTRC = true; } else if (cmsIsTag(d->profile, cmsSigGrayTRCTag)) { d->grayTRC = ((cmsToneCurve *)cmsReadTag (d->profile, cmsSigGrayTRCTag)); d->grayTRCReverse = cmsReverseToneCurve(d->grayTRC); d->hasTRC = true; } else { d->hasTRC = false; } // Check if the profile can convert (something->this) d->suitableForOutput = cmsIsMatrixShaper(d->profile) || (cmsIsCLUT(d->profile, INTENT_PERCEPTUAL, LCMS_USED_AS_INPUT) && cmsIsCLUT(d->profile, INTENT_PERCEPTUAL, LCMS_USED_AS_OUTPUT)); d->version = cmsGetProfileVersion(d->profile); d->defaultIntent = cmsGetHeaderRenderingIntent(d->profile); d->isMatrixShaper = cmsIsMatrixShaper(d->profile); d->isPerceptualCLUT = cmsIsCLUT(d->profile, INTENT_PERCEPTUAL, LCMS_USED_AS_INPUT); d->isSaturationCLUT = cmsIsCLUT(d->profile, INTENT_SATURATION, LCMS_USED_AS_INPUT); d->isAbsoluteCLUT = cmsIsCLUT(d->profile, INTENT_SATURATION, LCMS_USED_AS_INPUT); d->isRelativeCLUT = cmsIsCLUT(d->profile, INTENT_RELATIVE_COLORIMETRIC, LCMS_USED_AS_INPUT); return true; } return false; }
/* Get ICC Profile handle from buffer */ gcmmhprofile_t gscms_get_profile_handle_mem(unsigned char *buffer, unsigned int input_size) { cmsSetErrorHandler((cmsErrorHandlerFunction) gscms_error); return(cmsOpenProfileFromMem(buffer,input_size)); }
static cmsHPROFILE color_man_create_adobe_comp(void) { /* ClayRGB1998 is AdobeRGB compatible */ #include "ClayRGB1998_icc.h" return cmsOpenProfileFromMem(ClayRGB1998_icc, ClayRGB1998_icc_len); }