1 /* Copyright (C) 2003-2006 Jesper K. Pedersen <blackie@kde.org>
3 This program is free software; you can redistribute it and/or
4 modify it under the terms of the GNU General Public
5 License as published by the Free Software Foundation; either
6 version 2 of the License, or (at your option) any later version.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program; see the file COPYING. If not, write to
15 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16 Boston, MA 02110-1301, USA.
18 #include "RawImageDecoder.h"
22 #include "Settings/SettingsData.h"
23 #include <config-kpa-kdcraw.h>
25 # include <libkdcraw/kdcraw.h>
26 # include <libkdcraw/rawfiles.h>
30 namespace ImageManager
33 bool RAWImageDecoder::_decode( QImage
*img
, const QString
& imageFile
, QSize
* fullSize
, int dim
)
35 /* width and height seem to be only hints, ignore */
39 if ( !KDcrawIface::KDcraw::loadDcrawPreview( *img
, imageFile
) )
42 if ( Settings::SettingsData::instance()->useRawThumbnail() &&
43 img
->width() >= Settings::SettingsData::instance()->useRawThumbnailSize().width() &&
44 img
->height() >= Settings::SettingsData::instance()->useRawThumbnailSize().height() )
47 KDcrawIface::DcrawInfoContainer metadata
;
49 if ( !KDcrawIface::KDcraw::rawFileIdentify( metadata
, imageFile
) ||
50 ( img
->width() < metadata
.imageSize
.width() * 0.8 ) ||
51 ( img
->height() < metadata
.imageSize
.height() * 0.8 ) ) {
53 // let's try to get a better resolution
54 KDcrawIface::KDcraw decoder
;
55 KDcrawIface::RawDecodingSettings rawDecodingSettings
;
57 if ( rawDecodingSettings
.sixteenBitsImage
) {
58 kDebug() << "16 bits per color channel is not supported yet";
61 QByteArray imageData
; /* 3 bytes for each pixel, */
62 int width
, height
, rgbmax
;
63 if ( !decoder
.decodeRAWImage( imageFile
, rawDecodingSettings
, imageData
, width
, height
, rgbmax
) )
66 // Now the funny part, how to turn this fugly QByteArray into an QImage. Yay!
67 *img
= QImage(width
, height
, QImage::Format_RGB32
);
71 uchar
* data
= img
->bits();
73 for ( int i
= 0; i
< imageData
.size(); i
+= 3, data
+= 4 ) {
74 data
[0] = imageData
[i
+ 2]; // blue
75 data
[1] = imageData
[i
+ 1]; // green
76 data
[2] = imageData
[i
]; // red
77 data
[3] = 0xff; // alpha
83 *fullSize
= img
->size();
86 #else /* HAVE_KDCRAW */
88 Q_UNUSED( imageFile
);
91 #endif /* HAVE_KDCRAW */
94 void RAWImageDecoder::_initializeExtensionLists( QStringList
& rawExtensions
, QStringList
& standardExtensions
, QStringList
& ignoredExtensions
) const
96 static QStringList _rawExtensions
, _standardExtensions
, _ignoredExtensions
;
97 static bool extensionListsInitialized
= false;
98 if ( ! extensionListsInitialized
) {
100 _rawExtensions
= QString::fromAscii( raw_file_extentions
).split( QChar::fromLatin1(' '), QString::SkipEmptyParts
);
101 #endif /* HAVE_KDCRAW */
102 for (QStringList::iterator it
= _rawExtensions
.begin(); it
!= _rawExtensions
.end(); ++it
)
103 (*it
).remove( QString::fromAscii("*.") );
105 _standardExtensions
<< QString::fromLatin1("jpg")
106 << QString::fromLatin1("JPG")
107 << QString::fromLatin1("jpeg")
108 << QString::fromLatin1("JPEG")
109 << QString::fromLatin1("tif")
110 << QString::fromLatin1("TIF")
111 << QString::fromLatin1("tiff")
112 << QString::fromLatin1("TIFF")
113 << QString::fromLatin1("png")
114 << QString::fromLatin1("PNG");
115 _ignoredExtensions
<< QString::fromLatin1("thm") // Thumbnails
116 << QString::fromLatin1("THM")
117 << QString::fromLatin1("thumb") // thumbnail files
119 << QString::fromLatin1("ctg") // Catalog files
120 << QString::fromLatin1("gz") // Compressed files
121 << QString::fromLatin1("Z")
122 << QString::fromLatin1("bz2")
123 << QString::fromLatin1("zip")
124 << QString::fromLatin1("xml")
125 << QString::fromLatin1("XML")
126 << QString::fromLatin1("html")
127 << QString::fromLatin1("HTML")
128 << QString::fromLatin1("htm")
129 << QString::fromLatin1("HTM");
131 QChar
dot( QChar::fromLatin1('.') );
132 for ( QStringList::iterator it
= _rawExtensions
.begin(); it
!= _rawExtensions
.end(); ++it
)
133 if ( !(*it
).startsWith( dot
) )
135 for ( QStringList::iterator it
= _standardExtensions
.begin(); it
!= _standardExtensions
.end(); ++it
)
136 if ( !(*it
).startsWith( dot
) )
138 for ( QStringList::iterator it
= _ignoredExtensions
.begin(); it
!= _ignoredExtensions
.end(); ++it
)
139 if ( !(*it
).startsWith( dot
) )
142 extensionListsInitialized
= true;
145 rawExtensions
= _rawExtensions
;
146 standardExtensions
= _standardExtensions
;
147 ignoredExtensions
= _ignoredExtensions
;
150 bool RAWImageDecoder::_fileExistsWithExtensions( const QString
& fileName
,
151 const QStringList
& extensionList
) const
153 QString baseFileName
= fileName
;
154 int extStart
= fileName
.lastIndexOf(QChar::fromLatin1('.'));
155 // We're interested in xxx.yyy, not .yyy
156 if (extStart
<= 1) return false;
157 baseFileName
.remove(extStart
, baseFileName
.length() - extStart
);
158 for ( QStringList::ConstIterator it
= extensionList
.begin();
159 it
!= extensionList
.end(); ++it
) {
160 if (QFile::exists(baseFileName
+ *it
)) return true;
165 bool RAWImageDecoder::_fileIsKnownWithExtensions( const QSet
<QString
>& files
,
166 const QString
& fileName
,
167 const QStringList
& extensionList
) const
169 QString baseFileName
= fileName
;
170 int extStart
= fileName
.lastIndexOf(QChar::fromLatin1('.'));
171 if (extStart
<= 1) return false;
172 baseFileName
.remove(extStart
, baseFileName
.length() - extStart
);
173 for ( QStringList::ConstIterator it
= extensionList
.begin();
174 it
!= extensionList
.end(); ++it
) {
175 if (files
.contains(baseFileName
+ *it
) ) return true;
180 bool RAWImageDecoder::_fileEndsWithExtensions( const QString
& fileName
,
181 const QStringList
& extensionList
) const
183 for ( QStringList::ConstIterator it
= extensionList
.begin();
184 it
!= extensionList
.end(); ++it
) {
185 if( fileName
.endsWith( *it
, Qt::CaseInsensitive
) ) return true;
190 bool RAWImageDecoder::_mightDecode( const QString
& imageFile
)
192 QStringList _rawExtensions
, _standardExtensions
, _ignoredExtensions
;
193 _initializeExtensionLists( _rawExtensions
, _standardExtensions
, _ignoredExtensions
);
195 if (Settings::SettingsData::instance()->skipRawIfOtherMatches() &&
196 _fileExistsWithExtensions(imageFile
, _standardExtensions
)) return false;
197 if (_fileEndsWithExtensions(imageFile
, _rawExtensions
)) return true;
201 bool RAWImageDecoder::_skipThisFile( const QSet
<QString
>& loadedFiles
, const QString
& imageFile
) const
203 QStringList _rawExtensions
, _standardExtensions
, _ignoredExtensions
;
204 _initializeExtensionLists( _rawExtensions
, _standardExtensions
, _ignoredExtensions
);
206 // We're not interested in thumbnail and other files.
207 if (_fileEndsWithExtensions(imageFile
, _ignoredExtensions
)) return true;
209 // If we *are* interested in raw files even when other equivalent
210 // non-raw files are available, then we're interested in this file.
211 if (! (Settings::SettingsData::instance()->skipRawIfOtherMatches())) return false;
213 // If the file ends with something other than a known raw extension,
214 // we're interested in it.
215 if (! _fileEndsWithExtensions(imageFile
, _rawExtensions
)) return false;
217 // At this point, the file ends with a known raw extension, and we're
218 // not interested in raw files when other non-raw files are available.
219 // So search for an existing file with one of the standard
222 // This may not be the best way to do this, but it's using the
223 // same algorithm as _mightDecode above.
224 // -- Robert Krawitz rlk@alum.mit.edu 2007-07-22
226 return _fileIsKnownWithExtensions(loadedFiles
, imageFile
, _standardExtensions
);