You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
digikam/digikam/libs/widgets/iccprofiles/iccprofilewidget.cpp

449 lines
14 KiB

/* ============================================================
*
* 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 <klocale.h>
#include <kapplication.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* tqparent, const char* name, int w, int h)
: MetadataWidget(tqparent, 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-tqshaped 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