// -*- C++;indent-tabs-mode: t; tab-width: 4; c-basic-offset: 4; -*- /* This file is part of the KDE project * Copyright (C) 2003 * * 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 version 2. * * 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. * * You should have received a copy of the GNU General Public License * along with this program; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * $Id$ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kfile_exr.h" using namespace Imf; typedef KGenericFactory ExrFactory; K_EXPORT_COMPONENT_FACTORY(kfile_exr, ExrFactory("kfile_exr")) KExrPlugin::KExrPlugin(TQObject *parent, const char *name, const TQStringList &args) : KFilePlugin(parent, name, args) { // set up our mime type KFileMimeTypeInfo* info = addMimeTypeInfo( "image/x-exr" ); KFileMimeTypeInfo::GroupInfo* group = 0; KFileMimeTypeInfo::ItemInfo* item; // info group group = addGroupInfo( info, "Info", i18n("Information") ); addItemInfo( group, "Version", i18n("Format Version"), TQVariant::Int ); addItemInfo( group, "Tiled image", i18n("Tiled Image"), TQVariant::String ); item = addItemInfo( group, "Dimensions", i18n("Dimensions"), TQVariant::Size ); setHint( item, KFileMimeTypeInfo::Size ); setUnit( item, KFileMimeTypeInfo::Pixels ); item = addItemInfo( group, "ThumbnailDimensions", i18n("Thumbnail Dimensions"), TQVariant::Size ); setHint( item, KFileMimeTypeInfo::Size ); setUnit( item, KFileMimeTypeInfo::Pixels ); addItemInfo( group, "Comment", i18n("Comment"), TQVariant::String ); item = addItemInfo( group, "Thumbnail", i18n("Thumbnail"), TQVariant::Image ); setHint( item, KFileMimeTypeInfo::Thumbnail ); // standard attributes group group = addGroupInfo( info, "Standard", i18n("Standard Attributes") ); addItemInfo( group, "Owner", i18n("Owner"), TQVariant::String ); addItemInfo( group, "Comments", i18n("Comments"), TQVariant::String ); addItemInfo( group, "Capture Date", i18n("Capture Date"), TQVariant::String ); item = addItemInfo( group, "UTC Offset", i18n("UTC Offset"), TQVariant::String ); item = addItemInfo( group, "Exposure time", i18n("Exposure Time"), TQVariant::Double); setUnit( item, KFileMimeTypeInfo::Seconds ); item = addItemInfo( group, "Focus", i18n("Focus"), TQVariant::Double); setSuffix( item, i18n("Metres", "m") ); item = addItemInfo( group, "X Density", i18n("X Density"), TQVariant::Double); setSuffix( item, i18n("Pixels Per Inch", " ppi") ); item = addItemInfo( group, "White luminance", i18n("White Luminance"), TQVariant::Double); setSuffix( item, i18n("Candelas per square metre", " Nits") ); addItemInfo( group, "Longitude", i18n("Longitude"), TQVariant::String ); addItemInfo( group, "Latitude", i18n("Latitude"), TQVariant::String ); item = addItemInfo( group, "Altitude", i18n("Altitude"), TQVariant::String ); setSuffix( item, i18n("Metres", "m") ); addItemInfo( group, "ISO speed", i18n("ISO Speed"), TQVariant::Double ); addItemInfo( group, "Aperture", i18n("Aperture"), TQVariant::Double ); // channel group group = addGroupInfo( info, "Channel", i18n("Channels") ); addItemInfo( group, "A", i18n("A"), TQVariant::String ); addItemInfo( group, "R", i18n("R"), TQVariant::String ); addItemInfo( group, "G", i18n("G"), TQVariant::String ); addItemInfo( group, "B", i18n("B"), TQVariant::String ); addItemInfo( group, "Z", i18n("Z"), TQVariant::String ); addItemInfo( group, "NX", i18n("NX"), TQVariant::String ); addItemInfo( group, "NY", i18n("NY"), TQVariant::String ); addItemInfo( group, "NZ", i18n("NZ"), TQVariant::String ); addItemInfo( group, "R", i18n("R"), TQVariant::String ); addItemInfo( group, "U", i18n("U"), TQVariant::String ); addItemInfo( group, "V", i18n("V"), TQVariant::String ); addItemInfo( group, "materialID", i18n("materialID"), TQVariant::String ); addItemInfo( group, "objectID", i18n("objectID"), TQVariant::String ); addItemInfo( group, "renderID", i18n("renderID"), TQVariant::String ); addItemInfo( group, "pixelCover", i18n("pixelCover"), TQVariant::String ); addItemInfo( group, "velX", i18n("velX"), TQVariant::String ); addItemInfo( group, "velY", i18n("velY"), TQVariant::String ); addItemInfo( group, "packedRGBA", i18n("packedRGBA"), TQVariant::String ); // technical group group = addGroupInfo( info, "Technical", i18n("Technical Details") ); addItemInfo( group, "Compression", i18n("Compression"), TQVariant::String ); addItemInfo( group, "Line Order", i18n("Line Order"), TQVariant::String ); // 3dsMax group // This supports a special plugin for 3D Studio Max group = addGroupInfo( info, "3dsMax", i18n("3dsMax Details") ); addItemInfo( group, "Local time", i18n("Local Time"), TQVariant::String ); addItemInfo( group, "System time", i18n("System Time"), TQVariant::String ); addItemInfo( group, "Plugin version", i18n("Plugin Version"), TQVariant::String ); addItemInfo( group, "EXR version", i18n("EXR Version"), TQVariant::String ); addItemInfo( group, "Computer name", i18n("Computer Name"), TQVariant::String ); } TQCString doType( PixelType pt ) { switch (pt) { case UINT: return TQCString("32-bit unsigned integer"); break; case HALF: return TQCString("16-bit floating-point"); break; case FLOAT: return TQCString("32-bit floating-point"); break; default: return TQCString(); break; } } bool KExrPlugin::readInfo( KFileMetaInfo& info, uint what) { try { InputFile in ( info.path().ascii() ); const Header &h = in.header(); KFileMetaInfoGroup infogroup = appendGroup(info, "Info"); KFileMetaInfoGroup stdgroup = appendGroup(info, "Standard"); KFileMetaInfoGroup channelgroup = appendGroup(info, "Channel"); KFileMetaInfoGroup techgroup = appendGroup(info, "Technical"); KFileMetaInfoGroup threedsmaxgroup = appendGroup(info, "3dsMax"); appendItem( infogroup, "Version", getVersion(in.version()) ); if (isTiled(in.version())) { appendItem( infogroup, "Tiled image", "yes" ); } else { appendItem( infogroup, "Tiled image", "no" ); } Imath::Box2i dw = h.dataWindow(); appendItem( infogroup, "Dimensions", TQSize( (dw.max.x - dw.min.x + 1 ), (dw.max.y - dw.min.y + 1 ) ) ); if ( h.hasPreviewImage() ) { const PreviewImage &preview = in.header().previewImage(); appendItem( infogroup, "ThumbnailDimensions", TQSize(preview.width(), preview.height()) ); TQImage qpreview(preview.width(), preview.height(), 32, 0, TQImage::BigEndian); for ( unsigned int y=0; y < preview.height(); y++ ) { for ( unsigned int x=0; x < preview.width(); x++ ) { const PreviewRgba &q = preview.pixels()[x+(y*preview.width())]; qpreview.setPixel( x, y, tqRgba(q.r, q.g, q.b, q.a) ); } } appendItem( infogroup, "Thumbnail", qpreview); } const StringAttribute *commentSA = h.findTypedAttribute ("comment"); if (commentSA) { std::string commentString = commentSA->value(); TQString qcommentString(commentString.data()); qcommentString.setLength(commentString.size()); appendItem( infogroup, "Comment", qcommentString ); } // Standard Attributes we are interested in and can // meaningfully represent. if ( hasComments(h) ) { std::string commentsString = comments(h); TQString qcommentsString(commentsString.data()); qcommentsString.setLength(commentsString.size()); appendItem( stdgroup, "Comments", qcommentsString ); } if ( hasOwner(h) ) { std::string ownerString = owner(h); TQString qownerString(ownerString.data()); qownerString.setLength(ownerString.size()); appendItem( stdgroup, "Owner", qownerString ); } if ( hasCapDate(h) ) { std::string capDateString = capDate(h); TQString qcapDateString(capDateString.data()); qcapDateString.setLength(capDateString.size()); appendItem( stdgroup, "Capture Date", qcapDateString ); } // This define was introduced in EXR 1.6.0 #ifndef IMF_B44_COMPRESSION // This is the 1.4 and earlier version if ( hasutcOffset(h) ) { #else // This is the 1.6.0 and later version if ( hasUtcOffset(h) ) { #endif TQString UTCOffset; if (utcOffset(h)>0.0) { UTCOffset.append(TQString("%1").arg(utcOffset(h)/3600, 0, 'f', 1)); UTCOffset.append(" hours behind UTC"); } else { UTCOffset.append(TQString("%1").arg(-1.0*utcOffset(h)/3600, 0, 'f', 1)); UTCOffset.append(" hours ahead of UTC"); } appendItem( stdgroup, "UTC Offset", UTCOffset); } if ( hasExpTime(h) ) { double exposureTime = expTime(h); appendItem( stdgroup, "Exposure time", exposureTime ); } if ( hasFocus(h) ) { double focusDistance = focus(h); appendItem( stdgroup, "Focus", focusDistance ); } if ( hasXDensity(h) ) { double XDensity = xDensity(h); appendItem( stdgroup, "X Density", XDensity ); } if ( hasWhiteLuminance(h) ) { double WhiteLuminance = whiteLuminance(h); appendItem( stdgroup, "White luminance", WhiteLuminance ); } if ( hasLongitude(h) ) { TQString Longitude; if (longitude(h)<0.0) { Longitude.append(TQString("%1").arg(-1.0*longitude(h),0,'f',3)); Longitude.append(" deg West"); } else { Longitude.append(TQString("%1").arg(longitude(h),0,'f',3)); Longitude.append(" deg East"); } appendItem( stdgroup, "Longitude", Longitude); } if ( hasLatitude(h) ) { TQString Latitude; if (latitude(h)<0.0) { Latitude.append(TQString("%1").arg(-1.0*latitude(h),0,'f',3)); Latitude.append(" deg South"); } else { Latitude.append(TQString("%1").arg(latitude(h),0,'f',3)); Latitude.append(" deg North"); } appendItem( stdgroup, "Latitude", Latitude ); } if ( hasAltitude(h) ) { double Altitude = altitude(h); appendItem( stdgroup, "Altitude", TQString("%1").arg(Altitude,0,'f',1) ); } if ( hasIsoSpeed(h) ) { double IsoSpeed = isoSpeed(h); appendItem( stdgroup, "ISO speed", IsoSpeed ); } if ( hasAperture(h) ) { double Aperture = aperture(h); appendItem( stdgroup, "Aperture", Aperture ); } for (Header::ConstIterator i = h.begin(); i != h.end(); ++i) { const Attribute *a = &i.attribute(); if (const CompressionAttribute *ta = dynamic_cast (a)) { switch ( ta->value() ) { case NO_COMPRESSION: appendItem( techgroup, "Compression", i18n("No compression")); break; case RLE_COMPRESSION: appendItem( techgroup, "Compression", i18n("Run Length Encoding")); break; case ZIPS_COMPRESSION: appendItem( techgroup, "Compression", i18n("zip, individual scanlines")); break; case ZIP_COMPRESSION: appendItem( techgroup, "Compression", i18n("zip, multi-scanline blocks")); break; case PIZ_COMPRESSION: appendItem( techgroup, "Compression", i18n("piz compression")); break; default: break; } } else if (const LineOrderAttribute *ta = dynamic_cast (a)) { switch (ta->value()) { case INCREASING_Y: appendItem( techgroup, "Line Order", i18n("increasing Y")); break; case DECREASING_Y: appendItem( techgroup, "Line Order", i18n("decreasing Y")); break; default: break; }; } else if (const ChannelListAttribute *ta = dynamic_cast (a)) { for (ChannelList::ConstIterator i = ta->value().begin(); i != ta->value().end(); ++i) { appendItem( channelgroup, i.name(), doType(i.channel().type) ); } } } // This section deals with some special case stuff for a 3D Studio Max // plugin from Splutterfish. The weird construction is an // attempt to to deal with class conversion. C++ string handling // without TQt is a pain... const StringAttribute *ver3DSM = h.findTypedAttribute ("version3dsMax"); if (ver3DSM) { std::string ver3DSMstring = ver3DSM->value(); TQString qver3DSMstring(ver3DSMstring.data()); qver3DSMstring.setLength(ver3DSMstring.size()); appendItem( threedsmaxgroup, "Plugin version", qver3DSMstring ); } const StringAttribute *verEXR = h.findTypedAttribute ("versionEXR"); if (verEXR) { std::string verEXRstring = verEXR->value(); TQString qverEXRstring(verEXRstring.data()); qverEXRstring.setLength(verEXRstring.size()); appendItem( threedsmaxgroup, "EXR version", TQString( verEXRstring.data() ) ); } const StringAttribute *localTime = h.findTypedAttribute ("localTime"); if (localTime) { std::string localTimeString = localTime->value(); TQString qlocalTimeString(localTimeString.data()); qlocalTimeString.setLength(localTimeString.size()); appendItem( threedsmaxgroup, "Local time", qlocalTimeString ); } const StringAttribute *systemTime = h.findTypedAttribute ("systemTime"); if (systemTime) { std::string systemTimeString = systemTime->value(); TQString qsystemTimeString(systemTimeString.data()); qsystemTimeString.setLength(systemTimeString.size()); appendItem( threedsmaxgroup, "System time", qsystemTimeString ); } const StringAttribute *computerName = h.findTypedAttribute ("computerName"); if (computerName) { std::string computerNameString = computerName->value(); TQString qcomputerNameString(computerNameString.data()); qcomputerNameString.setLength(computerNameString.size()); appendItem( threedsmaxgroup, "Computer name", qcomputerNameString ); } return true; } catch (const std::exception &e) { kdDebug(0) << e.what() << endl; return false; } } #include "kfile_exr.moc"