summaryrefslogtreecommitdiffstats
path: root/src/libs/widgets/iccprofiles
diff options
context:
space:
mode:
authorMichele Calgaro <michele.calgaro@yahoo.it>2024-11-22 18:41:30 +0900
committerMichele Calgaro <michele.calgaro@yahoo.it>2024-11-22 20:55:03 +0900
commit5bed6e4a4c916a97f8fe4d1b07f7eecf4d733b90 (patch)
treef89cc49efc9ca1d0e1579ecb079ee7e7088ff8c8 /src/libs/widgets/iccprofiles
parent0bfbf616d9c1fd7abb1bd02732389ab35e5f8771 (diff)
downloaddigikam-5bed6e4a4c916a97f8fe4d1b07f7eecf4d733b90.tar.gz
digikam-5bed6e4a4c916a97f8fe4d1b07f7eecf4d733b90.zip
Rename 'digikam' folder to 'src'
Signed-off-by: Michele Calgaro <michele.calgaro@yahoo.it> (cherry picked from commit ee0d99607c14cb63d3ebdb3a970b508949fa8219)
Diffstat (limited to 'src/libs/widgets/iccprofiles')
-rw-r--r--src/libs/widgets/iccprofiles/Makefile.am23
-rw-r--r--src/libs/widgets/iccprofiles/cietonguewidget.cpp816
-rw-r--r--src/libs/widgets/iccprofiles/cietonguewidget.h115
-rw-r--r--src/libs/widgets/iccprofiles/iccpreviewwidget.cpp83
-rw-r--r--src/libs/widgets/iccprofiles/iccpreviewwidget.h71
-rw-r--r--src/libs/widgets/iccprofiles/iccprofilewidget.cpp448
-rw-r--r--src/libs/widgets/iccprofiles/iccprofilewidget.h79
7 files changed, 1635 insertions, 0 deletions
diff --git a/src/libs/widgets/iccprofiles/Makefile.am b/src/libs/widgets/iccprofiles/Makefile.am
new file mode 100644
index 00000000..8888d326
--- /dev/null
+++ b/src/libs/widgets/iccprofiles/Makefile.am
@@ -0,0 +1,23 @@
+METASOURCES = AUTO
+
+noinst_LTLIBRARIES = libiccprofileswidgets.la
+
+libiccprofileswidgets_la_SOURCES = iccprofilewidget.cpp cietonguewidget.cpp iccpreviewwidget.cpp
+
+libiccprofileswidgets_la_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LIB_TQT) -lDCOP $(LIB_TDECORE) $(LIB_TDEUI) -ltdefx $(LIB_TDEIO) -ltdetexteditor
+
+libiccprofileswidgets_la_LIBADD = $(top_builddir)/src/libs/lprof/liblprof.la
+
+INCLUDES = -I$(top_srcdir)/src/libs/widgets/metadata \
+ -I$(top_srcdir)/src/libs/widgets/common \
+ -I$(top_srcdir)/src/libs/lprof \
+ -I$(top_srcdir)/src/libs/dimg \
+ -I$(top_srcdir)/src/libs/dmetadata \
+ -I$(top_srcdir)/src/digikam \
+ $(LIBKDCRAW_CFLAGS) \
+ $(LIBKEXIV2_CFLAGS) \
+ $(all_includes)
+
+digikaminclude_HEADERS = cietonguewidget.h iccprofilewidget.h iccpreviewwidget.h
+
+digikamincludedir = $(includedir)/digikam
diff --git a/src/libs/widgets/iccprofiles/cietonguewidget.cpp b/src/libs/widgets/iccprofiles/cietonguewidget.cpp
new file mode 100644
index 00000000..2ec738b3
--- /dev/null
+++ b/src/libs/widgets/iccprofiles/cietonguewidget.cpp
@@ -0,0 +1,816 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-01-10
+ * Description : a widget to display CIE tongue from
+ * an ICC profile.
+ *
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * Any source code are inspired from lprof project and
+ * Copyright (C) 1998-2001 Marti Maria
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cmath>
+
+// TQt includes.
+
+#include <tqimage.h>
+#include <tqpainter.h>
+#include <tqpixmap.h>
+#include <tqfile.h>
+#include <tqtimer.h>
+
+// KDE includes.
+
+#include <tdelocale.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "lcmsprf.h"
+#include "cietonguewidget.h"
+#include "cietonguewidget.moc"
+
+namespace Digikam
+{
+
+ // The following table gives the CIE colour matching functions
+ // \bar{x}(\lambda), \bar{y}(\lambda), and \bar{z}(\lambda), for
+ // wavelengths \lambda at 5 nanometre increments from 380 nm through
+ // 780 nm. This table is used in conjunction with Planck's law for
+ // the energy spectrum of a black body at a given temperature to plot
+ // the black body curve on the CIE chart.
+
+ // The following table gives the spectral chromaticity co-ordinates
+ // x(\lambda) and y(\lambda) for wavelengths in 5 nanometre increments
+ // from 380 nm through 780 nm. These co-ordinates represent the
+ // position in the CIE x-y space of pure spectral colours of the given
+ // wavelength, and thus define the outline of the CIE "tongue"
+ // diagram.
+
+ static const double spectral_chromaticity[81][3] =
+ {
+ { 0.1741, 0.0050 }, // 380 nm
+ { 0.1740, 0.0050 },
+ { 0.1738, 0.0049 },
+ { 0.1736, 0.0049 },
+ { 0.1733, 0.0048 },
+ { 0.1730, 0.0048 },
+ { 0.1726, 0.0048 },
+ { 0.1721, 0.0048 },
+ { 0.1714, 0.0051 },
+ { 0.1703, 0.0058 },
+ { 0.1689, 0.0069 },
+ { 0.1669, 0.0086 },
+ { 0.1644, 0.0109 },
+ { 0.1611, 0.0138 },
+ { 0.1566, 0.0177 },
+ { 0.1510, 0.0227 },
+ { 0.1440, 0.0297 },
+ { 0.1355, 0.0399 },
+ { 0.1241, 0.0578 },
+ { 0.1096, 0.0868 },
+ { 0.0913, 0.1327 },
+ { 0.0687, 0.2007 },
+ { 0.0454, 0.2950 },
+ { 0.0235, 0.4127 },
+ { 0.0082, 0.5384 },
+ { 0.0039, 0.6548 },
+ { 0.0139, 0.7502 },
+ { 0.0389, 0.8120 },
+ { 0.0743, 0.8338 },
+ { 0.1142, 0.8262 },
+ { 0.1547, 0.8059 },
+ { 0.1929, 0.7816 },
+ { 0.2296, 0.7543 },
+ { 0.2658, 0.7243 },
+ { 0.3016, 0.6923 },
+ { 0.3373, 0.6589 },
+ { 0.3731, 0.6245 },
+ { 0.4087, 0.5896 },
+ { 0.4441, 0.5547 },
+ { 0.4788, 0.5202 },
+ { 0.5125, 0.4866 },
+ { 0.5448, 0.4544 },
+ { 0.5752, 0.4242 },
+ { 0.6029, 0.3965 },
+ { 0.6270, 0.3725 },
+ { 0.6482, 0.3514 },
+ { 0.6658, 0.3340 },
+ { 0.6801, 0.3197 },
+ { 0.6915, 0.3083 },
+ { 0.7006, 0.2993 },
+ { 0.7079, 0.2920 },
+ { 0.7140, 0.2859 },
+ { 0.7190, 0.2809 },
+ { 0.7230, 0.2770 },
+ { 0.7260, 0.2740 },
+ { 0.7283, 0.2717 },
+ { 0.7300, 0.2700 },
+ { 0.7311, 0.2689 },
+ { 0.7320, 0.2680 },
+ { 0.7327, 0.2673 },
+ { 0.7334, 0.2666 },
+ { 0.7340, 0.2660 },
+ { 0.7344, 0.2656 },
+ { 0.7346, 0.2654 },
+ { 0.7347, 0.2653 },
+ { 0.7347, 0.2653 },
+ { 0.7347, 0.2653 },
+ { 0.7347, 0.2653 },
+ { 0.7347, 0.2653 },
+ { 0.7347, 0.2653 },
+ { 0.7347, 0.2653 },
+ { 0.7347, 0.2653 },
+ { 0.7347, 0.2653 },
+ { 0.7347, 0.2653 },
+ { 0.7347, 0.2653 },
+ { 0.7347, 0.2653 },
+ { 0.7347, 0.2653 },
+ { 0.7347, 0.2653 },
+ { 0.7347, 0.2653 },
+ { 0.7347, 0.2653 },
+ { 0.7347, 0.2653 } // 780 nm
+ };
+
+class CIETongueWidgetPriv
+{
+public:
+
+ CIETongueWidgetPriv()
+ {
+ hMonitorProfile = 0;
+ hXYZProfile = 0;
+ hXFORM = 0;
+
+ Measurement.Patches = 0;
+ Measurement.Allowed = 0;
+ blinkTimer = 0;
+ pos = 0;
+
+ profileDataAvailable = true;
+ loadingImageMode = false;
+ loadingImageSucess = false;
+ }
+
+ bool profileDataAvailable;
+ bool loadingImageMode;
+ bool loadingImageSucess;
+
+ double gridside;
+
+ int xBias;
+ int yBias;
+ int pxcols;
+ int pxrows;
+ int pos; // Position of animation during loading/calculation.
+
+ TQPainter painter;
+ TQPixmap pixmap;
+ TQTimer *blinkTimer;
+
+ cmsHPROFILE hMonitorProfile;
+ cmsHPROFILE hXYZProfile;
+ cmsHTRANSFORM hXFORM;
+ cmsCIExyYTRIPLE Primaries;
+ cmsCIEXYZ MediaWhite;
+
+ MEASUREMENT Measurement;
+};
+
+CIETongueWidget::CIETongueWidget(int w, int h, TQWidget *parent, cmsHPROFILE hMonitor)
+ : TQWidget(parent, 0, TQt::WDestructiveClose)
+{
+ d = new CIETongueWidgetPriv;
+ d->blinkTimer = new TQTimer( this );
+ setMinimumSize(w, h);
+ cmsErrorAction(LCMS_ERROR_SHOW);
+
+ if (hMonitor)
+ d->hMonitorProfile = hMonitor;
+ else
+ d->hMonitorProfile = cmsCreate_sRGBProfile();
+
+ d->hXYZProfile = cmsCreateXYZProfile();
+ d->hXFORM = cmsCreateTransform(d->hXYZProfile, TYPE_XYZ_16,
+ d->hMonitorProfile, TYPE_RGB_8,
+ INTENT_PERCEPTUAL, 0);
+
+ connect(d->blinkTimer, TQ_SIGNAL(timeout()),
+ this, TQ_SLOT(slotBlinkTimerDone()));
+}
+
+CIETongueWidget::~CIETongueWidget()
+{
+ if (d->Measurement.Patches)
+ free(d->Measurement.Patches);
+
+ if (d->Measurement.Allowed)
+ free(d->Measurement.Allowed);
+
+ cmsDeleteTransform(d->hXFORM);
+ cmsCloseProfile(d->hXYZProfile);
+ cmsCloseProfile(d->hMonitorProfile);
+ delete d;
+}
+
+int CIETongueWidget::grids(double val) const
+{
+ return (int) floor(val * d->gridside + 0.5);
+}
+
+bool CIETongueWidget::setProfileData(const TQByteArray &profileData)
+{
+ if (!profileData.isEmpty())
+ {
+ cmsHPROFILE hProfile = cmsOpenProfileFromMem(const_cast<char*>(profileData.data()),
+ (DWORD)profileData.size());
+
+ if (!hProfile)
+ {
+ d->profileDataAvailable = false;
+ d->loadingImageSucess = false;
+ }
+ else
+ {
+ setProfile(hProfile);
+ cmsCloseProfile(hProfile);
+ d->profileDataAvailable = true;
+ d->loadingImageSucess = true;
+ }
+ }
+ else
+ {
+ d->profileDataAvailable = false;
+ d->loadingImageSucess = false;
+ }
+
+ d->loadingImageMode = false;
+
+ d->blinkTimer->stop();
+ repaint(false);
+ return (d->profileDataAvailable);
+}
+
+bool CIETongueWidget::setProfileFromFile(const KURL& file)
+{
+ if (!file.isEmpty() && file.isValid())
+ {
+ cmsHPROFILE hProfile = cmsOpenProfileFromFile(TQFile::encodeName(file.path()), "r");
+
+ if (!hProfile)
+ {
+ d->profileDataAvailable = false;
+ d->loadingImageSucess = false;
+ }
+ else
+ {
+ setProfile(hProfile);
+ cmsCloseProfile(hProfile);
+ d->profileDataAvailable = true;
+ d->loadingImageSucess = true;
+ }
+ }
+ else
+ {
+ d->profileDataAvailable = false;
+ d->loadingImageSucess = false;
+ }
+
+ d->blinkTimer->stop();
+ repaint(false);
+ return (d->profileDataAvailable);
+}
+
+void CIETongueWidget::setProfile(cmsHPROFILE hProfile)
+{
+ // Get the white point.
+
+ ZeroMemory(&(d->MediaWhite), sizeof(cmsCIEXYZ));
+ cmsTakeMediaWhitePoint(&(d->MediaWhite), hProfile);
+ cmsCIExyY White;
+ cmsXYZ2xyY(&White, &(d->MediaWhite));
+
+ // Get the colorant matrix.
+
+ ZeroMemory(&(d->Primaries), sizeof(cmsCIExyYTRIPLE));
+
+ if (cmsIsTag(hProfile, icSigRedColorantTag) &&
+ cmsIsTag(hProfile, icSigGreenColorantTag) &&
+ cmsIsTag(hProfile, icSigBlueColorantTag))
+ {
+ MAT3 Mat;
+
+ if (cmsReadICCMatrixRGB2XYZ(&Mat, hProfile))
+ {
+ // Undo chromatic adaptation
+ if (cmsAdaptMatrixFromD50(&Mat, &White))
+ {
+ cmsCIEXYZ tmp;
+
+ tmp.X = Mat.v[0].n[0];
+ tmp.Y = Mat.v[1].n[0];
+ tmp.Z = Mat.v[2].n[0];
+
+ // ScaleToWhite(&MediaWhite, &tmp);
+ cmsXYZ2xyY(&(d->Primaries.Red), &tmp);
+
+ tmp.X = Mat.v[0].n[1];
+ tmp.Y = Mat.v[1].n[1];
+ tmp.Z = Mat.v[2].n[1];
+ // ScaleToWhite(&MediaWhite, &tmp);
+ cmsXYZ2xyY(&(d->Primaries.Green), &tmp);
+
+ tmp.X = Mat.v[0].n[2];
+ tmp.Y = Mat.v[1].n[2];
+ tmp.Z = Mat.v[2].n[2];
+ // ScaleToWhite(&MediaWhite, &tmp);
+ cmsXYZ2xyY(&(d->Primaries.Blue), &tmp);
+ }
+ }
+ }
+
+ // Get target data stored in profile
+
+ ZeroMemory(&(d->Measurement), sizeof(MEASUREMENT));
+ char* CharTarget;
+ size_t CharTargetSize;
+
+ if (cmsTakeCharTargetData(hProfile, &CharTarget, &CharTargetSize))
+ {
+ LCMSHANDLE hSheet = cmsxIT8LoadFromMem(CharTarget, CharTargetSize);
+ if (hSheet != NULL)
+ {
+ cmsxPCollLoadFromSheet(&(d->Measurement), hSheet);
+ cmsxIT8Free(hSheet);
+ cmsxPCollValidatePatches(&(d->Measurement), PATCH_HAS_XYZ|PATCH_HAS_RGB);
+ }
+ }
+}
+
+void CIETongueWidget::mapPoint(int& icx, int& icy, LPcmsCIExyY xyY)
+{
+ icx = (int) floor((xyY->x * (d->pxcols - 1)) + .5);
+ icy = (int) floor(((d->pxrows - 1) - xyY->y * (d->pxrows - 1)) + .5);
+}
+
+void CIETongueWidget::biasedLine(int x1, int y1, int x2, int y2)
+{
+ d->painter.drawLine(x1 + d->xBias, y1, x2 + d->xBias, y2);
+}
+
+void CIETongueWidget::biasedText(int x, int y, TQString Txt)
+{
+ d->painter.drawText(TQPoint(d->xBias + x, y), Txt);
+}
+
+TQRgb CIETongueWidget::colorByCoord(double x, double y)
+{
+ // Get xyz components scaled from coordinates
+
+ double cx = ((double) x) / (d->pxcols - 1);
+ double cy = 1.0 - ((double) y) / (d->pxrows - 1);
+ double cz = 1.0 - cx - cy;
+
+ // Project xyz to XYZ space. Note that in this
+ // particular case we are substituting XYZ with xyz
+
+ cmsCIEXYZ XYZ = { cx , cy , cz };
+
+ WORD XYZW[3];
+ BYTE RGB[3];
+
+ cmsFloat2XYZEncoded(XYZW, &XYZ);
+ cmsDoTransform(d->hXFORM, XYZW, RGB, 1);
+
+ return tqRgb(RGB[0], RGB[1], RGB[2]);
+}
+
+void CIETongueWidget::outlineTongue()
+{
+ int lx = 0, ly = 0;
+ int fx=0, fy=0;
+
+ for (int x = 380; x <= 700; x += 5)
+ {
+ int ix = (x - 380) / 5;
+
+ cmsCIExyY p = {spectral_chromaticity[ix][0],
+ spectral_chromaticity[ix][1], 1};
+
+ int icx, icy;
+ mapPoint(icx, icy, &p);
+
+ if (x > 380)
+ {
+ biasedLine(lx, ly, icx, icy);
+ }
+ else
+ {
+ fx = icx;
+ fy = icy;
+ }
+
+ lx = icx;
+ ly = icy;
+ }
+
+ biasedLine(lx, ly, fx, fy);
+}
+
+void CIETongueWidget::fillTongue()
+{
+
+ TQImage Img = d->pixmap.convertToImage();
+
+ int x;
+
+ for (int y = 0; y < d->pxrows; y++)
+ {
+ int xe = 0;
+
+ // Find horizontal extents of tongue on this line.
+
+ for (x = 0; x < d->pxcols; x++)
+ {
+ if ((TQColor) Img.pixel(x + d->xBias, y) != TQt::black)
+ {
+ for (xe = d->pxcols - 1; xe >= x; xe--)
+ {
+ if ((TQColor) Img.pixel(xe + d->xBias, y) != TQt::black)
+ {
+ break;
+ }
+ }
+
+ break;
+ }
+ }
+
+ if (x < d->pxcols)
+ {
+ for ( ; x <= xe; x++)
+ {
+ TQRgb Color = colorByCoord(x, y);
+ Img.setPixel(x + d->xBias, y, Color);
+ }
+ }
+ }
+
+ d->pixmap.convertFromImage(Img, TQPixmap::AvoidDither );
+}
+
+void CIETongueWidget::drawTongueAxis()
+{
+ TQFont font;
+ font.setPointSize(6);
+ d->painter.setFont(font);
+
+ d->painter.setPen(tqRgb(255, 255, 255));
+
+ biasedLine(0, 0, 0, d->pxrows - 1);
+ biasedLine(0, d->pxrows-1, d->pxcols-1, d->pxrows - 1);
+
+ for (int y = 1; y <= 9; y += 1)
+ {
+ TQString s;
+ int xstart = (y * (d->pxcols - 1)) / 10;
+ int ystart = (y * (d->pxrows - 1)) / 10;
+
+ s.sprintf("0.%d", y);
+ biasedLine(xstart, d->pxrows - grids(1), xstart, d->pxrows - grids(4));
+ biasedText(xstart - grids(11), d->pxrows + grids(15), s);
+
+ s.sprintf("0.%d", 10 - y);
+ biasedLine(0, ystart, grids(3), ystart);
+ biasedText(grids(-25), ystart + grids(5), s);
+ }
+}
+
+void CIETongueWidget::drawTongueGrid()
+{
+ d->painter.setPen(tqRgb(80, 80, 80));
+
+ for (int y = 1; y <= 9; y += 1)
+ {
+ int xstart = (y * (d->pxcols - 1)) / 10;
+ int ystart = (y * (d->pxrows - 1)) / 10;
+
+ biasedLine(xstart, grids(4), xstart, d->pxrows - grids(4) - 1);
+ biasedLine(grids(7), ystart, d->pxcols-1-grids(7), ystart);
+ }
+}
+
+void CIETongueWidget::drawLabels()
+{
+ TQFont font;
+ font.setPointSize(5);
+ d->painter.setFont(font);
+
+ for (int x = 450; x <= 650; x += (x > 470 && x < 600) ? 5 : 10)
+ {
+ TQString wl;
+ int bx = 0, by = 0, tx, ty;
+
+ if (x < 520)
+ {
+ bx = grids(-22);
+ by = grids(2);
+ }
+ else if (x < 535)
+ {
+ bx = grids(-8);
+ by = grids(-6);
+ }
+ else
+ {
+ bx = grids(4);
+ }
+
+ int ix = (x - 380) / 5;
+
+ cmsCIExyY p = {spectral_chromaticity[ix][0],
+ spectral_chromaticity[ix][1], 1};
+
+ int icx, icy;
+ mapPoint(icx, icy, &p);
+
+ tx = icx + ((x < 520) ? grids(-2) : ((x >= 535) ? grids(2) : 0));
+ ty = icy + ((x < 520) ? 0 : ((x >= 535) ? grids(-1) : grids(-2)));
+
+ d->painter.setPen(tqRgb(255, 255, 255));
+ biasedLine(icx, icy, tx, ty);
+
+ TQRgb Color = colorByCoord(icx, icy);
+ d->painter.setPen(Color);
+
+ wl.sprintf("%d", x);
+ biasedText(icx+bx, icy+by, wl);
+ }
+}
+
+void CIETongueWidget::drawSmallElipse(LPcmsCIExyY xyY, BYTE r, BYTE g, BYTE b, int sz)
+{
+ int icx, icy;
+
+ mapPoint(icx, icy, xyY);
+ d->painter.setPen(tqRgb(r, g, b));
+ d->painter.drawEllipse(icx + d->xBias- sz/2, icy-sz/2, sz, sz);
+}
+
+void CIETongueWidget::drawPatches()
+{
+ for (int i=0; i < d->Measurement.nPatches; i++)
+ {
+ LPPATCH p = d->Measurement.Patches + i;
+
+ if (d->Measurement.Allowed[i])
+ {
+ LPcmsCIEXYZ XYZ = &p ->XYZ;
+ cmsCIExyY xyY;
+ cmsXYZ2xyY(&xyY, XYZ);
+
+ drawSmallElipse(&xyY, 0, 0, 0, 4);
+
+ if (p->dwFlags & PATCH_HAS_XYZ_PROOF)
+ {
+ if (p->XYZ.Y < 0.03)
+ continue;
+
+ if (p->XYZProof.Y < 0.03)
+ continue;
+
+ cmsCIExyY Pt;
+ cmsXYZ2xyY(&Pt, &p->XYZProof);
+ int icx1, icx2, icy1, icy2;
+
+ mapPoint(icx1, icy1, &xyY);
+ mapPoint(icx2, icy2, &Pt);
+
+ if (icx2 < 5 || icy2 < 5 || icx1 < 5 || icy1 < 5)
+ continue;
+
+ d->painter.setPen(tqRgb(255, 255, 0));
+ biasedLine(icx1, icy1, icx2, icy2);
+ }
+ }
+ }
+}
+
+void CIETongueWidget::drawColorantTriangle()
+{
+ drawSmallElipse(&(d->Primaries.Red), 255, 128, 128, 6);
+ drawSmallElipse(&(d->Primaries.Green), 128, 255, 128, 6);
+ drawSmallElipse(&(d->Primaries.Blue), 128, 128, 255, 6);
+
+ int x1, y1, x2, y2, x3, y3;
+
+ mapPoint(x1, y1, &(d->Primaries.Red));
+ mapPoint(x2, y2, &(d->Primaries.Green));
+ mapPoint(x3, y3, &(d->Primaries.Blue));
+
+ d->painter.setPen(tqRgb(255, 255, 255));
+
+ biasedLine(x1, y1, x2, y2);
+ biasedLine(x2, y2, x3, y3);
+ biasedLine(x3, y3, x1, y1);
+}
+
+void CIETongueWidget::sweep_sRGB()
+{
+ int r, g, b;
+ cmsHPROFILE hXYZ, hsRGB;
+
+ hXYZ = cmsCreateXYZProfile();
+ hsRGB = cmsCreate_sRGBProfile();
+
+ cmsHTRANSFORM xform = cmsCreateTransform(hsRGB, TYPE_RGB_16, hXYZ, TYPE_XYZ_16,
+ INTENT_ABSOLUTE_COLORIMETRIC, cmsFLAGS_NOTPRECALC);
+ WORD RGB[3], XYZ[3];
+ cmsCIEXYZ xyz, MediaWhite;
+ cmsCIExyY xyY, WhitePt;
+ int x1, y1;
+
+ cmsTakeMediaWhitePoint(&MediaWhite, hsRGB);
+ cmsXYZ2xyY(&WhitePt, &MediaWhite);
+
+ for (r=0; r < 65536; r += 1024)
+ {
+ for (g=0; g < 65536; g += 1024)
+ {
+ for (b=0; b < 65536; b += 1024)
+ {
+ RGB[0] = r; RGB[1] = g; RGB[2] = b;
+ cmsDoTransform(xform, RGB, XYZ, 1);
+ cmsXYZEncoded2Float(&xyz, XYZ);
+ cmsXYZ2xyY(&xyY, &xyz);
+ mapPoint(x1, y1, &xyY);
+ d->painter.drawPoint(x1 + d->xBias, y1);
+ }
+ }
+ }
+
+ cmsDeleteTransform(xform);
+ cmsCloseProfile(hXYZ);
+ cmsCloseProfile(hsRGB);
+}
+
+void CIETongueWidget::drawWhitePoint()
+{
+ cmsCIExyY Whitem_pntxyY;
+ cmsXYZ2xyY(&Whitem_pntxyY, &(d->MediaWhite));
+ drawSmallElipse(&Whitem_pntxyY, 255, 255, 255, 8);
+}
+
+void CIETongueWidget::loadingStarted()
+{
+ d->pos = 0;
+ d->loadingImageMode = true;
+ d->loadingImageSucess = false;
+ repaint(false);
+ d->blinkTimer->start(200);
+}
+
+void CIETongueWidget::loadingFailed()
+{
+ d->blinkTimer->stop();
+ d->pos = 0;
+ d->loadingImageMode = false;
+ d->loadingImageSucess = false;
+ repaint(false);
+}
+
+void CIETongueWidget::paintEvent(TQPaintEvent*)
+{
+ d->pixmap = TQPixmap(size());
+ d->pixmap.setOptimization(TQPixmap::BestOptim);
+
+ // Widget is disable : drawing grayed frame.
+
+ if ( !isEnabled() )
+ {
+ d->painter.begin(&d->pixmap);
+ d->painter.fillRect(0, 0, size().width(), size().height(), palette().disabled().background());
+ d->painter.setPen(TQPen(palette().disabled().foreground(), 1, TQt::SolidLine));
+ d->painter.drawRect(0, 0, width(), height());
+ d->painter.end();
+ bitBlt(this, 0, 0, &d->pixmap);
+ return;
+ }
+
+ // Loading image mode.
+
+ if (d->loadingImageMode && !d->loadingImageSucess)
+ {
+ // In first, we draw an animation.
+
+ int asize = 24;
+ TQPixmap anim(asize, asize);
+ TQPainter p2;
+ p2.begin(&anim, this);
+ p2.fillRect(0, 0, asize, asize, palette().active().background());
+ p2.translate(asize/2, asize/2);
+
+ d->pos = (d->pos + 10) % 360;
+ p2.setPen(TQPen(palette().active().text()));
+ p2.rotate(d->pos);
+ for ( int i=0 ; i<12 ; i++ )
+ {
+ p2.drawLine(asize/2-5, 0, asize/2-2, 0);
+ p2.rotate(30);
+ }
+ p2.end();
+
+ // ... and we render busy text.
+
+ d->painter.begin(&d->pixmap);
+ d->painter.fillRect(0, 0, size().width(), size().height(), palette().active().background());
+ d->painter.drawPixmap(width()/2 - asize /2, asize, anim);
+ d->painter.setPen(TQPen(palette().active().text(), 1, TQt::SolidLine));
+ d->painter.drawRect(0, 0, width(), height());
+ d->painter.drawText(0, 0, size().width(), size().height(), TQt::AlignCenter,
+ i18n("Loading image..."));
+
+ d->painter.end();
+ bitBlt(this, 0, 0, &d->pixmap);
+ return;
+ }
+
+ // No profile data to show.
+
+ if (!d->profileDataAvailable || (!d->loadingImageMode && !d->loadingImageSucess))
+ {
+ d->painter.begin(&d->pixmap);
+ d->painter.fillRect(0, 0, size().width(), size().height(), palette().active().background());
+ d->painter.setPen(TQPen(palette().active().text(), 1, TQt::SolidLine));
+ d->painter.drawRect(0, 0, width(), height());
+ d->painter.drawText(0, 0, size().width(), size().height(), TQt::AlignCenter,
+ i18n("No profile available..."));
+
+ d->painter.end();
+ bitBlt(this, 0, 0, &d->pixmap);
+ return;
+ }
+
+ // Draw the CIE tongue curve.
+
+ d->pixmap.fill(TQt::black);
+ d->painter.begin(&d->pixmap);
+
+ int pixcols = d->pixmap.width();
+ int pixrows = d->pixmap.height();
+
+ d->gridside = (TQMIN(pixcols, pixrows)) / 512.0;
+ d->xBias = grids(32);
+ d->yBias = grids(20);
+ d->pxcols = pixcols - d->xBias;
+ d->pxrows = pixrows - d->yBias;
+
+ d->painter.setBackgroundColor(tqRgb(0, 0, 0));
+ d->painter.setPen(tqRgb(255, 255, 255));
+
+ outlineTongue();
+ fillTongue();
+
+ drawTongueAxis();
+ drawLabels();
+ drawTongueGrid();
+
+ if (d->MediaWhite.Y > 0.0)
+ drawWhitePoint();
+
+ if (d->Primaries.Red.Y != 0.0)
+ drawColorantTriangle();
+
+ if (d->Measurement.Patches && d->Measurement.Allowed)
+ drawPatches();
+
+ d->painter.end();
+
+ bitBlt(this, 0, 0, &d->pixmap);
+}
+
+void CIETongueWidget::slotBlinkTimerDone()
+{
+ repaint(false);
+ d->blinkTimer->start( 200 );
+}
+
+} // namespace Digikam
diff --git a/src/libs/widgets/iccprofiles/cietonguewidget.h b/src/libs/widgets/iccprofiles/cietonguewidget.h
new file mode 100644
index 00000000..9fc8503d
--- /dev/null
+++ b/src/libs/widgets/iccprofiles/cietonguewidget.h
@@ -0,0 +1,115 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-01-10
+ * Description : a widget to display CIE tongue from
+ * an ICC profile.
+ *
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * Any source code are inspired from lprof project and
+ * Copyright (C) 1998-2001 Marti Maria
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef CIETONGUEWIDGET_H
+#define CIETONGUEWIDGET_H
+
+#include <config.h>
+
+// TQt includes.
+
+#include <tqwidget.h>
+#include <tqcolor.h>
+
+// KDE includes.
+
+#include <kurl.h>
+
+// lcms includes.
+
+#include LCMS_HEADER
+#if LCMS_VERSION < 114
+#define cmsTakeCopyright(profile) "Unknown"
+#endif // LCMS_VERSION < 114
+
+// Local includes.
+
+#include "digikam_export.h"
+
+namespace Digikam
+{
+
+class CIETongueWidgetPriv;
+
+class DIGIKAM_EXPORT CIETongueWidget : public TQWidget
+{
+TQ_OBJECT
+
+
+public:
+
+ CIETongueWidget(int w, int h, TQWidget *parent=0, cmsHPROFILE hMonitor=0);
+ ~CIETongueWidget();
+
+ bool setProfileData(const TQByteArray& profileData=TQByteArray());
+ bool setProfileFromFile(const KURL& file=KURL());
+
+ void loadingStarted();
+ void loadingFailed();
+
+protected:
+
+ int grids(double val) const;
+
+ void outlineTongue();
+ void fillTongue();
+ void drawTongueAxis();
+ void drawTongueGrid();
+ void drawLabels();
+
+ TQRgb colorByCoord(double x, double y);
+ void drawSmallElipse(LPcmsCIExyY xyY, BYTE r, BYTE g, BYTE b, int sz);
+
+ void paintEvent( TQPaintEvent * );
+
+private:
+
+ void drawColorantTriangle();
+ void drawWhitePoint();
+ void drawPatches();
+
+ void mapPoint(int& icx, int& icy, LPcmsCIExyY xyY);
+ void biasedLine(int x1, int y1, int x2, int y2);
+ void biasedText(int x, int y, TQString Txt);
+
+ void sweep_sRGB();
+
+ void setProfile(cmsHPROFILE hProfile);
+
+private slots:
+
+ void slotBlinkTimerDone();
+
+private :
+
+ CIETongueWidgetPriv* d;
+
+};
+
+} // namespace Digikam
+
+#endif /* CIETONGUEWIDGET_H */
diff --git a/src/libs/widgets/iccprofiles/iccpreviewwidget.cpp b/src/libs/widgets/iccprofiles/iccpreviewwidget.cpp
new file mode 100644
index 00000000..3398b37f
--- /dev/null
+++ b/src/libs/widgets/iccprofiles/iccpreviewwidget.cpp
@@ -0,0 +1,83 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-01-12
+ * Description : a widget to display ICC profiles descriptions
+ * in file dialog preview.
+ *
+ * Copyright (C) 2006-2007 by Francisco J. Cruz <fj.cruz@supercable.es>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqfileinfo.h>
+#include <tqlayout.h>
+#include <tqvgroupbox.h>
+
+// KDE includes.
+
+#include <kurl.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "iccprofilewidget.h"
+#include "iccpreviewwidget.h"
+#include "iccpreviewwidget.moc"
+
+namespace Digikam
+{
+
+ICCPreviewWidget::ICCPreviewWidget(TQWidget *parent)
+ : KPreviewWidgetBase( parent )
+{
+ TQVBoxLayout *layout = new TQVBoxLayout( this );
+ TQVGroupBox *box = new TQVGroupBox( this );
+ box->setInsideMargin(0);
+ box->setFrameStyle(TQFrame::NoFrame|TQFrame::Plain);
+ m_iccProfileWidget = new ICCProfileWidget(box);
+ layout->addWidget( box );
+}
+
+ICCPreviewWidget::~ICCPreviewWidget()
+{
+}
+
+void ICCPreviewWidget::showPreview( const KURL &url)
+{
+ clearPreview();
+ TQFileInfo fInfo(url.path());
+
+ if ( url.isLocalFile() && fInfo.isFile() && fInfo.isReadable() )
+ {
+ DDebug() << url << " is a readble local file" << endl;
+ m_iccProfileWidget->loadFromURL(url);
+ }
+ else
+ {
+ DDebug() << url << " is not a readable local file" << endl;
+ }
+}
+
+void ICCPreviewWidget::clearPreview()
+{
+ m_iccProfileWidget->loadFromURL(KURL());
+}
+
+} // namespace Digikam
+
+
diff --git a/src/libs/widgets/iccprofiles/iccpreviewwidget.h b/src/libs/widgets/iccprofiles/iccpreviewwidget.h
new file mode 100644
index 00000000..89b1f4b5
--- /dev/null
+++ b/src/libs/widgets/iccprofiles/iccpreviewwidget.h
@@ -0,0 +1,71 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-01-12
+ * Description : a widget to display ICC profiles descriptions
+ * in file dialog preview.
+ *
+ * Copyright (C) 2006-2007 by Francisco J. Cruz <fj.cruz@supercable.es>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef ICCPREVIEWWIDGET_H
+#define ICCPREVIEWWIDGET_H
+
+// KDE includes.
+
+#include <kpreviewwidgetbase.h>
+
+// Local includes.
+
+#include "digikam_export.h"
+
+class KURL;
+
+namespace Digikam
+{
+
+class ICCProfileWidget;
+
+class DIGIKAM_EXPORT ICCPreviewWidget : public KPreviewWidgetBase
+{
+
+TQ_OBJECT
+
+
+public:
+
+ ICCPreviewWidget(TQWidget *parent);
+ ~ICCPreviewWidget();
+
+public slots:
+
+ virtual void showPreview(const KURL &url);
+
+protected:
+
+ virtual void clearPreview();
+ virtual void virtual_hook(int, void*){};
+
+private :
+
+ ICCProfileWidget *m_iccProfileWidget;
+
+};
+
+} // namespace Digikam
+
+#endif /* ICCPREVIEWWIDGET_H */
diff --git a/src/libs/widgets/iccprofiles/iccprofilewidget.cpp b/src/libs/widgets/iccprofiles/iccprofilewidget.cpp
new file mode 100644
index 00000000..2e5152f7
--- /dev/null
+++ b/src/libs/widgets/iccprofiles/iccprofilewidget.cpp
@@ -0,0 +1,448 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-06-23
+ * Description : a tab widget to display ICC profile infos
+ *
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#include <config.h>
+
+// TQt includes.
+
+#include <tqlayout.h>
+#include <tqpushbutton.h>
+#include <tqwhatsthis.h>
+#include <tqlabel.h>
+#include <tqmap.h>
+#include <tqhbox.h>
+#include <tqfile.h>
+#include <tqcombobox.h>
+#include <tqgroupbox.h>
+#include <tqmap.h>
+
+// KDE includes.
+
+#include <kdialogbase.h>
+#include <tdelocale.h>
+#include <tdeapplication.h>
+
+// Lcms includes.
+
+#include LCMS_HEADER
+#if LCMS_VERSION < 114
+#define cmsTakeCopyright(profile) "Unknown"
+#endif // LCMS_VERSION < 114
+
+// Local includes.
+
+#include "ddebug.h"
+#include "metadatalistview.h"
+#include "cietonguewidget.h"
+#include "iccprofilewidget.h"
+#include "iccprofilewidget.moc"
+
+namespace Digikam
+{
+
+static const char* ICCHumanList[] =
+{
+ "ColorSpace",
+ "Copyright",
+ "DeviceClass",
+ "Name",
+ "Description",
+ "RenderingIntent",
+ "-1"
+};
+
+// This entry list is only require for compatibility with MetadataWidget implementation.
+static const char* ICCEntryList[] =
+{
+ "Header",
+ "-1"
+};
+
+class ICCTagInfo
+{
+
+public:
+
+ ICCTagInfo(){}
+
+ ICCTagInfo(const TQString& title, const TQString& description)
+ : m_title(title), m_description(description){}
+
+ TQString title() const { return m_title; }
+ TQString description() const { return m_description; }
+
+private:
+
+ TQString m_title;
+ TQString m_description;
+};
+
+typedef TQMap<TQString, ICCTagInfo> ICCTagInfoMap;
+
+class ICCProfileWidgetPriv
+{
+
+public:
+
+ ICCProfileWidgetPriv()
+ {
+ cieTongue = 0;
+ }
+
+ TQStringList tagsfilter;
+ TQStringList keysFilter;
+
+ CIETongueWidget *cieTongue;
+
+ ICCTagInfoMap iccTagsDescription;
+};
+
+
+ICCProfileWidget::ICCProfileWidget(TQWidget* parent, const char* name, int w, int h)
+ : MetadataWidget(parent, name)
+{
+ cmsErrorAction(LCMS_ERROR_SHOW);
+
+ d = new ICCProfileWidgetPriv;
+
+ // Set the translated ICC tags titles/descriptions list
+ d->iccTagsDescription["Icc.Header.Name"] = ICCTagInfo(i18n("Name"),
+ i18n("The ICC profile product name"));
+ d->iccTagsDescription["Icc.Header.Description"] = ICCTagInfo(i18n("Description"),
+ i18n("The ICC profile product description"));
+ d->iccTagsDescription["Icc.Header.Information"] = ICCTagInfo(i18n("Information"),
+ i18n("Additional ICC profile information"));
+ d->iccTagsDescription["Icc.Header.Manufacturer"] = ICCTagInfo(i18n("Manufacturer"),
+ i18n("Raw information about the ICC profile manufacturer"));
+ d->iccTagsDescription["Icc.Header.Model"] = ICCTagInfo(i18n("Model"),
+ i18n("Raw information about the ICC profile model"));
+ d->iccTagsDescription["Icc.Header.Copyright"] = ICCTagInfo(i18n("Copyright"),
+ i18n("Raw information about the ICC profile copyright"));
+ d->iccTagsDescription["Icc.Header.ProfileID"] = ICCTagInfo(i18n("Profile ID"),
+ i18n("The ICC profile ID number"));
+ d->iccTagsDescription["Icc.Header.ColorSpace"] = ICCTagInfo(i18n("Color Space"),
+ i18n("The color space used by the ICC profile"));
+ d->iccTagsDescription["Icc.Header.ConnectionSpace"] = ICCTagInfo(i18n("Connection Space"),
+ i18n("The connection space used by the ICC profile"));
+ d->iccTagsDescription["Icc.Header.DeviceClass"] = ICCTagInfo(i18n("Device Class"),
+ i18n("The ICC profile device class"));
+ d->iccTagsDescription["Icc.Header.RenderingIntent"] = ICCTagInfo(i18n("Rendering Intent"),
+ i18n("The ICC profile rendering intent"));
+ d->iccTagsDescription["Icc.Header.ProfileVersion"] = ICCTagInfo(i18n("Profile Version"),
+ i18n("The ICC version used to record the profile"));
+ d->iccTagsDescription["Icc.Header.CMMFlags"] = ICCTagInfo(i18n("CMM Flags"),
+ i18n("The ICC profile color management flags"));
+
+ // Set the list of keys and tags filters.
+ for (int i=0 ; TQString(ICCEntryList[i]) != TQString("-1") ; i++)
+ d->keysFilter << ICCEntryList[i];
+
+ for (int i=0 ; TQString(ICCHumanList[i]) != TQString("-1") ; i++)
+ d->tagsfilter << ICCHumanList[i];
+
+ // Add CIE tongue graph to the widget area
+
+ d->cieTongue = new CIETongueWidget(w, h, this);
+ TQWhatsThis::add( d->cieTongue, i18n("<p>This area contains a CIE or chromaticity diagram. "
+ "A CIE diagram is a representation of all the colors "
+ "that a person with normal vision can see. This is represented "
+ "by the colored sail-shaped area. In addition you will see a "
+ "triangle that is superimposed on the diagram outlined in white. "
+ "This triangle represents the outer boundaries of the color space "
+ "of the device that is characterized by the inspected profile. "
+ "This is called the device gamut.<p>"
+ "In addition there are black dots and yellow lines on the diagram. "
+ "Each black dot represents one of the measurement points that were "
+ "used to create this profile. The yellow line represents the "
+ "amount that each point is corrected by the profile, and the "
+ "direction of this correction."));
+
+ setUserAreaWidget(d->cieTongue);
+ decodeMetadata();
+}
+
+ICCProfileWidget::~ICCProfileWidget()
+{
+ delete d;
+}
+
+void ICCProfileWidget::setDataLoading()
+{
+ d->cieTongue->loadingStarted();
+}
+
+void ICCProfileWidget::setLoadingFailed()
+{
+ d->cieTongue->loadingFailed();
+}
+
+TQString ICCProfileWidget::getMetadataTitle()
+{
+ return i18n("ICC Color Profile Information");
+}
+
+bool ICCProfileWidget::loadFromURL(const KURL& url)
+{
+ setFileName(url.path());
+
+ if (url.isEmpty())
+ {
+ setMetadata();
+ d->cieTongue->setProfileData();
+ return false;
+ }
+ else
+ {
+ TQFile file(url.path());
+ if ( !file.open(IO_ReadOnly) )
+ {
+ setMetadata();
+ d->cieTongue->setProfileData();
+ return false;
+ }
+
+ TQByteArray iccData(file.size());
+ TQDataStream stream( &file );
+ stream.readRawBytes(iccData.data(), iccData.size());
+ file.close();
+
+ if (iccData.isEmpty())
+ {
+ setMetadata();
+ d->cieTongue->setProfileData();
+ return false;
+ }
+ else
+ {
+ setMetadata(iccData);
+ d->cieTongue->setProfileData(iccData);
+ }
+ }
+
+ return true;
+}
+
+bool ICCProfileWidget::decodeMetadata()
+{
+ TQByteArray iccData = getMetadata();
+ if (iccData.isNull())
+ return false;
+
+ d->cieTongue->setProfileData(iccData);
+
+ cmsHPROFILE hProfile = cmsOpenProfileFromMem(iccData.data(), (DWORD)iccData.size());
+
+ if (!hProfile)
+ {
+ DDebug() << "Cannot parse ICC profile tags using LCMS" << endl;
+ return false;
+ }
+
+ DMetadata::MetaDataMap metaDataMap;
+
+ if ( !TQString(cmsTakeProductName(hProfile)).isEmpty() )
+ metaDataMap.insert("Icc.Header.Name", TQString(cmsTakeProductName(hProfile)).replace("\n", " "));
+
+ if ( !TQString(cmsTakeProductDesc(hProfile)).isEmpty() )
+ metaDataMap.insert("Icc.Header.Description", TQString(cmsTakeProductDesc(hProfile)).replace("\n", " "));
+
+ if ( !TQString(cmsTakeProductInfo(hProfile)).isEmpty() )
+ metaDataMap.insert("Icc.Header.Information", TQString(cmsTakeProductInfo(hProfile)).replace("\n", " "));
+
+ if ( !TQString(cmsTakeManufacturer(hProfile)).isEmpty() )
+ metaDataMap.insert("Icc.Header.Manufacturer", TQString(cmsTakeManufacturer(hProfile)).replace("\n", " "));
+
+ if ( !TQString(cmsTakeModel(hProfile)).isEmpty() )
+ metaDataMap.insert("Icc.Header.Model", TQString(cmsTakeModel(hProfile)).replace("\n", " "));
+
+ if ( !TQString(cmsTakeCopyright(hProfile)).isEmpty() )
+ metaDataMap.insert("Icc.Header.Copyright", TQString(cmsTakeCopyright(hProfile)).replace("\n", " "));
+
+ metaDataMap.insert("Icc.Header.ProfileID", TQString::number((uint)*cmsTakeProfileID(hProfile)));
+ metaDataMap.insert("Icc.Header.ProfileVersion", TQString::number((uint)cmsGetProfileICCversion(hProfile)));
+ metaDataMap.insert("Icc.Header.CMMFlags", TQString::number((uint)cmsTakeHeaderFlags(hProfile)));
+
+ TQString colorSpace;
+ switch (cmsGetColorSpace(hProfile))
+ {
+ case icSigLabData:
+ colorSpace = i18n("Lab");
+ break;
+ case icSigLuvData:
+ colorSpace = i18n("Luv");
+ break;
+ case icSigRgbData:
+ colorSpace = i18n("RGB");
+ break;
+ case icSigGrayData:
+ colorSpace = i18n("GRAY");
+ break;
+ case icSigHsvData:
+ colorSpace = i18n("HSV");
+ break;
+ case icSigHlsData:
+ colorSpace = i18n("HLS");
+ break;
+ case icSigCmykData:
+ colorSpace = i18n("CMYK");
+ break;
+ case icSigCmyData:
+ colorSpace= i18n("CMY");
+ break;
+ default:
+ colorSpace = i18n("Unknown");
+ break;
+ }
+ metaDataMap.insert("Icc.Header.ColorSpace", colorSpace);
+
+ TQString connectionSpace;
+ switch (cmsGetPCS(hProfile))
+ {
+ case icSigLabData:
+ connectionSpace = i18n("Lab");
+ break;
+ case icSigLuvData:
+ connectionSpace = i18n("Luv");
+ break;
+ case icSigRgbData:
+ connectionSpace = i18n("RGB");
+ break;
+ case icSigGrayData:
+ connectionSpace = i18n("GRAY");
+ break;
+ case icSigHsvData:
+ connectionSpace = i18n("HSV");
+ break;
+ case icSigHlsData:
+ connectionSpace = i18n("HLS");
+ break;
+ case icSigCmykData:
+ connectionSpace = i18n("CMYK");
+ break;
+ case icSigCmyData:
+ connectionSpace= i18n("CMY");
+ break;
+ default:
+ connectionSpace = i18n("Unknown");
+ break;
+ }
+ metaDataMap.insert("Icc.Header.ConnectionSpace", connectionSpace);
+
+ TQString device;
+ switch ((int)cmsGetDeviceClass(hProfile))
+ {
+ case icSigInputClass:
+ device = i18n("Input device");
+ break;
+ case icSigDisplayClass:
+ device = i18n("Display device");
+ break;
+ case icSigOutputClass:
+ device = i18n("Output device");
+ break;
+ case icSigColorSpaceClass:
+ device = i18n("Color space");
+ break;
+ case icSigLinkClass:
+ device = i18n("Link device");
+ break;
+ case icSigAbstractClass:
+ device = i18n("Abstract");
+ break;
+ case icSigNamedColorClass:
+ device = i18n("Named color");
+ break;
+ default:
+ device = i18n("Unknown");
+ break;
+ }
+ metaDataMap.insert("Icc.Header.DeviceClass", device);
+
+ TQString intent;
+ switch (cmsTakeRenderingIntent(hProfile))
+ {
+ case 0:
+ intent = i18n("Perceptual");
+ break;
+ case 1:
+ intent = i18n("Relative Colorimetric");
+ break;
+ case 2:
+ intent = i18n("Saturation");
+ break;
+ case 3:
+ intent = i18n("Absolute Colorimetric");
+ break;
+ default:
+ intent = i18n("Unknown");
+ break;
+ }
+ metaDataMap.insert("Icc.Header.RenderingIntent", intent);
+
+ cmsCloseProfile(hProfile);
+
+ // Update all metadata contents.
+ setMetadataMap(metaDataMap);
+ return true;
+}
+
+void ICCProfileWidget::buildView()
+{
+ if (getMode() == SIMPLE)
+ {
+ setIfdList(getMetadataMap(), d->keysFilter, d->tagsfilter);
+ }
+ else
+ {
+ setIfdList(getMetadataMap(), d->keysFilter, TQStringList());
+ }
+
+ MetadataWidget::buildView();
+}
+
+TQString ICCProfileWidget::getTagTitle(const TQString& key)
+{
+ ICCTagInfoMap::Iterator it = d->iccTagsDescription.find(key);
+ if (it != d->iccTagsDescription.end())
+ return(it.data().title());
+
+ return key.section('.', 2, 2);
+}
+
+void ICCProfileWidget::slotSaveMetadataToFile()
+{
+ KURL url = saveMetadataToFile(i18n("ICC color profile File to Save"),
+ TQString("*.icc *.icm|"+i18n("ICC Files (*.icc; *.icm)")));
+ storeMetadataToFile(url);
+}
+
+TQString ICCProfileWidget::getTagDescription(const TQString& key)
+{
+ ICCTagInfoMap::Iterator it = d->iccTagsDescription.find(key);
+ if (it != d->iccTagsDescription.end())
+ return(it.data().description());
+
+ return key.section('.', 2, 2);
+}
+
+} // namespace Digikam
diff --git a/src/libs/widgets/iccprofiles/iccprofilewidget.h b/src/libs/widgets/iccprofiles/iccprofilewidget.h
new file mode 100644
index 00000000..d753f30e
--- /dev/null
+++ b/src/libs/widgets/iccprofiles/iccprofilewidget.h
@@ -0,0 +1,79 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-06-23
+ * Description : a tab widget to display ICC profile infos
+ *
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef ICCPROFILEWIDGET_H
+#define ICCPROFILEWIDGET_H
+
+// TQt includes.
+
+#include <tqwidget.h>
+#include <tqstring.h>
+
+// Local includes.
+
+#include "metadatawidget.h"
+#include "digikam_export.h"
+
+namespace Digikam
+{
+
+class ICCProfileWidgetPriv;
+
+class DIGIKAM_EXPORT ICCProfileWidget : public MetadataWidget
+{
+ TQ_OBJECT
+
+
+public:
+
+ ICCProfileWidget(TQWidget* parent, const char* name=0, int w=256, int h=256);
+ ~ICCProfileWidget();
+
+ bool loadFromURL(const KURL& url);
+
+ TQString getTagDescription(const TQString& key);
+ TQString getTagTitle(const TQString& key);
+
+ TQString getMetadataTitle();
+
+ void setLoadingFailed();
+ void setDataLoading();
+
+protected slots:
+
+ virtual void slotSaveMetadataToFile();
+
+private:
+
+ bool decodeMetadata();
+ void buildView();
+
+private:
+
+ ICCProfileWidgetPriv *d;
+
+};
+
+} // namespace Digikam
+
+#endif /* ICCPROFILEWIDGET_H */