summaryrefslogtreecommitdiff
authorzecke <zecke>2004-04-02 19:28:09 (UTC)
committer zecke <zecke>2004-04-02 19:28:09 (UTC)
commit97bdc55663590ba430a4f322ad97aab9f4c02bf3 (patch) (unidiff)
tree8d340684ac97907b73d6b8abf995116f58680cdd
parent09d1ebb55ab44ebd129ff44b83b6b20054df77aa (diff)
downloadopie-97bdc55663590ba430a4f322ad97aab9f4c02bf3.zip
opie-97bdc55663590ba430a4f322ad97aab9f4c02bf3.tar.gz
opie-97bdc55663590ba430a4f322ad97aab9f4c02bf3.tar.bz2
-Fix realignment of the items but now it updates too often
-Fix slave not to include <qt></qt> for iconViewName
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/graphics/opie-eye/gui/iconview.cpp29
-rw-r--r--noncore/graphics/opie-eye/gui/mainwindow.cpp2
-rw-r--r--noncore/graphics/opie-eye/slave/gif_slave.cpp3
-rw-r--r--noncore/graphics/opie-eye/slave/jpeg_slave.cpp5
-rw-r--r--noncore/graphics/opie-eye/slave/png_slave.cpp3
5 files changed, 20 insertions, 22 deletions
diff --git a/noncore/graphics/opie-eye/gui/iconview.cpp b/noncore/graphics/opie-eye/gui/iconview.cpp
index b3f0006..ed9fc9c 100644
--- a/noncore/graphics/opie-eye/gui/iconview.cpp
+++ b/noncore/graphics/opie-eye/gui/iconview.cpp
@@ -1,378 +1,375 @@
1/* 1/*
2 * GPLv2 zecke@handhelds.org 2 * GPLv2 zecke@handhelds.org
3 * No WArranty... 3 * No WArranty...
4 */ 4 */
5 5
6#include "iconview.h" 6#include "iconview.h"
7 7
8#include <lib/imagecache.h> 8#include <lib/imagecache.h>
9 9
10#include <iface/dirview.h> 10#include <iface/dirview.h>
11#include <iface/dirlister.h> 11#include <iface/dirlister.h>
12 12
13#include <opie2/oconfig.h> 13#include <opie2/oconfig.h>
14#include <opie2/okeyconfigwidget.h> 14#include <opie2/okeyconfigwidget.h>
15#include <opie2/odebug.h>
15 16
16#include <qpe/resource.h> 17#include <qpe/resource.h>
17#include <qpe/qpemessagebox.h> 18#include <qpe/qpemessagebox.h>
18#include <qpe/ir.h> 19#include <qpe/ir.h>
19#include <qpe/qcopenvelope_qws.h> 20#include <qpe/qcopenvelope_qws.h>
20 21
21 22
22#include <qiconview.h> 23#include <qiconview.h>
23#include <qlabel.h> 24#include <qlabel.h>
24#include <qhbox.h> 25#include <qhbox.h>
25#include <qcombobox.h> 26#include <qcombobox.h>
26#include <qdir.h> 27#include <qdir.h>
27#include <qapplication.h> 28#include <qapplication.h>
28#include <qmainwindow.h> 29#include <qmainwindow.h>
29#include <qtimer.h> 30#include <qtimer.h>
30#include <qstyle.h> 31#include <qstyle.h>
31 32
32 33
33using Opie::Ui::OKeyConfigItem; 34using Opie::Ui::OKeyConfigItem;
34 35
35namespace { 36namespace {
36 QPixmap* _dirPix = 0; 37 QPixmap* _dirPix = 0;
37 QPixmap* _unkPix = 0; 38 QPixmap* _unkPix = 0;
38 class IconViewItem : public QIconViewItem { 39 class IconViewItem : public QIconViewItem {
39 public: 40 public:
40 IconViewItem( QIconView*, const QString& path, const QString& name, bool isDir = false); 41 IconViewItem( QIconView*, const QString& path, const QString& name, bool isDir = false);
41 QPixmap* pixmap()const; 42 QPixmap* pixmap()const;
42 QString path()const { return m_path; } 43 QString path()const { return m_path; }
43 bool isDir()const { return m_isDir; } 44 bool isDir()const { return m_isDir; }
44 void setText( const QString& ); 45 void setText( const QString& );
45 void reCalc(); 46
47
46 private: 48 private:
47 mutable QPixmap* m_pix; 49 mutable QPixmap* m_pix;
48 QString m_path; 50 QString m_path;
49 bool m_isDir : 1; 51 bool m_isDir : 1;
50 bool m_noInfo :1; 52 bool m_noInfo :1;
51 }; 53 };
52 54
53 55
54/* 56/*
55 * If we request an Image or String 57 * If we request an Image or String
56 * we add it to the map 58 * we add it to the map
57 */ 59 */
58 QMap<QString, IconViewItem*> g_stringInf; 60 QMap<QString, IconViewItem*> g_stringInf;
59 QMap<QString, IconViewItem*> g_stringPix; 61 QMap<QString, IconViewItem*> g_stringPix;
60 62
61 IconViewItem::IconViewItem( QIconView* view,const QString& path, 63 IconViewItem::IconViewItem( QIconView* view,const QString& path,
62 const QString& name, bool isDir ) 64 const QString& name, bool isDir )
63 : QIconViewItem( view ), m_path( path ), m_isDir( isDir ), 65 : QIconViewItem( view ), m_path( path ), m_isDir( isDir ),
64 m_noInfo( false ) 66 m_noInfo( false )
65 { 67 {
66 QIconViewItem::setText( name ); 68 QIconViewItem::setText( name );
67 if ( isDir && !_dirPix ) 69 if ( isDir && !_dirPix )
68 _dirPix = new QPixmap( Resource::loadPixmap("advancedfm/FileBrowser")); 70 _dirPix = new QPixmap( Resource::loadPixmap("advancedfm/FileBrowser"));
69 else if ( !isDir && !_unkPix ) 71 else if ( !isDir && !_unkPix )
70 _unkPix = new QPixmap( Resource::loadPixmap( "UnknownDocument" ) ); 72 _unkPix = new QPixmap( Resource::loadPixmap( "UnknownDocument" ) );
71 } 73 }
72 inline QPixmap* IconViewItem::pixmap()const { 74 inline QPixmap* IconViewItem::pixmap()const {
75 qWarning( "Name is " + m_path.right( 15 ) + " rect is %d %d %d %d | %d %d",
76 rect().x(),rect().y(),rect().width(),rect().height(),
77 iconView()->contentsX(), iconView()->contentsY());
78
73 if ( m_isDir ) 79 if ( m_isDir )
74 return _dirPix; 80 return _dirPix;
75 else{ 81 else{
76 if (!m_noInfo && !g_stringInf.contains( m_path ) ) { 82 if (!m_noInfo && !g_stringInf.contains( m_path ) ) {
77 currentView()->dirLister()->imageInfo( m_path ); 83 currentView()->dirLister()->imageInfo( m_path );
78 g_stringInf.insert( m_path, const_cast<IconViewItem*>(this)); 84 g_stringInf.insert( m_path, const_cast<IconViewItem*>(this));
79 } 85 }
80 86
81 m_pix = PPixmapCache::self()->cachedImage( m_path, 64, 64 ); 87 m_pix = PPixmapCache::self()->cachedImage( m_path, 64, 64 );
82 if ( !m_pix && !g_stringPix.contains( m_path )) { 88 if ( !m_pix && !g_stringPix.contains( m_path )) {
83 currentView()->dirLister()->thumbNail( m_path, 64, 64 ); 89 currentView()->dirLister()->thumbNail( m_path, 64, 64 );
84 g_stringPix.insert( m_path, const_cast<IconViewItem*>(this)); 90 g_stringPix.insert( m_path, const_cast<IconViewItem*>(this));
85 } 91 }
86 return m_pix ? m_pix : _unkPix; 92 return m_pix ? m_pix : _unkPix;
87 } 93 }
88 } 94 }
89 inline void IconViewItem::setText( const QString& str ) { 95 inline void IconViewItem::setText( const QString& str ) {
90 QString text = QIconViewItem::text()+"\n"+str; 96 QString text = QIconViewItem::text()+"\n"+str;
91 m_noInfo = true; 97 m_noInfo = true;
92 QIconViewItem::setText( text ); 98 QIconViewItem::setText( text );
93 reCalc();
94 }
95
96 inline void IconViewItem::reCalc()
97 {
98 calcRect();
99 } 99 }
100} 100}
101 101
102 102
103PIconView::PIconView( QWidget* wid, Opie::Core::OConfig* cfg ) 103PIconView::PIconView( QWidget* wid, Opie::Core::OConfig* cfg )
104 : QVBox( wid ), m_cfg( cfg ) 104 : QVBox( wid ), m_cfg( cfg )
105{ 105{
106 { 106 {
107 QCopEnvelope( "QPE/Application/opie-eye_slave", "refUp()" ); 107 QCopEnvelope( "QPE/Application/opie-eye_slave", "refUp()" );
108 } 108 }
109 m_path = QDir::homeDirPath(); 109 m_path = QDir::homeDirPath();
110 110
111 QHBox *hbox = new QHBox( this ); 111 QHBox *hbox = new QHBox( this );
112 QLabel* lbl = new QLabel( hbox ); 112 QLabel* lbl = new QLabel( hbox );
113 lbl->setText( tr("View as" ) ); 113 lbl->setText( tr("View as" ) );
114 114
115 m_views = new QComboBox( hbox, "View As" ); 115 m_views = new QComboBox( hbox, "View As" );
116 connect( m_views, SIGNAL(activated(int)), 116 connect( m_views, SIGNAL(activated(int)),
117 this, SLOT(slotViewChanged(int)) ); 117 this, SLOT(slotViewChanged(int)) );
118 118
119 m_view= new QIconView( this ); 119 m_view= new QIconView( this );
120 connect(m_view, SIGNAL(clicked(QIconViewItem*) ), 120 connect(m_view, SIGNAL(clicked(QIconViewItem*) ),
121 this, SLOT(slotClicked(QIconViewItem*)) ); 121 this, SLOT(slotClicked(QIconViewItem*)) );
122 122
123 m_view->setArrangement( QIconView::LeftToRight ); 123 m_view->setArrangement( QIconView::LeftToRight );
124 m_view->setItemTextPos( QIconView::Right ); 124 m_view->setItemTextPos( QIconView::Right );
125 m_view->setResizeMode(QIconView::Adjust);
126 125
127 int dw = QApplication::desktop()->width(); 126 int dw = QApplication::desktop()->width();
128 int viewerWidth = dw-style().scrollBarExtent().width(); 127 int viewerWidth = dw-style().scrollBarExtent().width();
129 m_view->setGridX( viewerWidth-2*m_view->spacing() ); 128 m_view->setGridX( viewerWidth-3*m_view->spacing());
130 m_view->setGridY( fontMetrics().height()*2+40 ); 129 m_view->setGridY( fontMetrics().height()*2+40 );
131 130
132 131
133 initKeys(); 132 initKeys();
134 133
135 loadViews(); 134 loadViews();
136 slotViewChanged( m_views->currentItem() ); 135 slotViewChanged( m_views->currentItem() );
137} 136}
138 137
139PIconView::~PIconView() { 138PIconView::~PIconView() {
140 { 139 {
141 QCopEnvelope( "QPE/Application/opie-eye_slave", "refDown()" ); 140 QCopEnvelope( "QPE/Application/opie-eye_slave", "refDown()" );
142 } 141 }
143 m_viewManager->save(); 142 m_viewManager->save();
144 delete m_viewManager; 143 delete m_viewManager;
145} 144}
146 145
147Opie::Ui::OKeyConfigManager* PIconView::manager() { 146Opie::Ui::OKeyConfigManager* PIconView::manager() {
148 return m_viewManager; 147 return m_viewManager;
149} 148}
150 149
151void PIconView::initKeys() { 150void PIconView::initKeys() {
152 Opie::Ui::OKeyPair::List lst; 151 Opie::Ui::OKeyPair::List lst;
153 lst.append( Opie::Ui::OKeyPair::upArrowKey() ); 152 lst.append( Opie::Ui::OKeyPair::upArrowKey() );
154 lst.append( Opie::Ui::OKeyPair::downArrowKey() ); 153 lst.append( Opie::Ui::OKeyPair::downArrowKey() );
155 lst.append( Opie::Ui::OKeyPair::leftArrowKey() ); 154 lst.append( Opie::Ui::OKeyPair::leftArrowKey() );
156 lst.append( Opie::Ui::OKeyPair::rightArrowKey() ); 155 lst.append( Opie::Ui::OKeyPair::rightArrowKey() );
157 lst.append( Opie::Ui::OKeyPair::returnKey() ); 156 lst.append( Opie::Ui::OKeyPair::returnKey() );
158 157
159 m_viewManager = new Opie::Ui::OKeyConfigManager(m_cfg, "View-KeyBoard-Config", 158 m_viewManager = new Opie::Ui::OKeyConfigManager(m_cfg, "View-KeyBoard-Config",
160 lst, false,this, "keyconfig name" ); 159 lst, false,this, "keyconfig name" );
161 m_viewManager->addKeyConfig( OKeyConfigItem(tr("Beam Current Item") , "beam", 160 m_viewManager->addKeyConfig( OKeyConfigItem(tr("Beam Current Item") , "beam",
162 QString::fromLatin1("beam"), BeamItem, 161 QString::fromLatin1("beam"), BeamItem,
163 Opie::Ui::OKeyPair(Qt::Key_B, Qt::ShiftButton), 162 Opie::Ui::OKeyPair(Qt::Key_B, Qt::ShiftButton),
164 this, SLOT(slotBeam())) ); 163 this, SLOT(slotBeam())) );
165 m_viewManager->addKeyConfig( OKeyConfigItem(tr("Delete Current Item"), "delete", 164 m_viewManager->addKeyConfig( OKeyConfigItem(tr("Delete Current Item"), "delete",
166 QString::fromLatin1("trash"), DeleteItem, 165 QString::fromLatin1("trash"), DeleteItem,
167 Opie::Ui::OKeyPair(Qt::Key_D, Qt::ShiftButton), 166 Opie::Ui::OKeyPair(Qt::Key_D, Qt::ShiftButton),
168 this, SLOT(slotTrash())) ); 167 this, SLOT(slotTrash())) );
169 m_viewManager->addKeyConfig( OKeyConfigItem(tr("View Current Item"), "view", 168 m_viewManager->addKeyConfig( OKeyConfigItem(tr("View Current Item"), "view",
170 QString::fromLatin1("1to1"), ViewItem, 169 QString::fromLatin1("1to1"), ViewItem,
171 Opie::Ui::OKeyPair(Qt::Key_V, Qt::ShiftButton), 170 Opie::Ui::OKeyPair(Qt::Key_V, Qt::ShiftButton),
172 this, SLOT(slotShowImage()))); 171 this, SLOT(slotShowImage())));
173 m_viewManager->addKeyConfig( OKeyConfigItem(tr("Show Image Info") , "info", 172 m_viewManager->addKeyConfig( OKeyConfigItem(tr("Show Image Info") , "info",
174 QString::fromLatin1("DocumentTypeWord"), InfoItem, 173 QString::fromLatin1("DocumentTypeWord"), InfoItem,
175 Opie::Ui::OKeyPair(Qt::Key_I, Qt::ShiftButton ), 174 Opie::Ui::OKeyPair(Qt::Key_I, Qt::ShiftButton ),
176 this, SLOT(slotImageInfo()) ) ); 175 this, SLOT(slotImageInfo()) ) );
177 m_viewManager->load(); 176 m_viewManager->load();
178 m_viewManager->handleWidget( m_view ); 177 m_viewManager->handleWidget( m_view );
179} 178}
180 179
181void PIconView::slotDirUp() { 180void PIconView::slotDirUp() {
182 QDir dir( m_path ); 181 QDir dir( m_path );
183 dir.cdUp(); 182 dir.cdUp();
184 slotChangeDir( dir.absPath() ); 183 slotChangeDir( dir.absPath() );
185 184
186} 185}
187 186
188void PIconView::slotChangeDir(const QString& path) { 187void PIconView::slotChangeDir(const QString& path) {
189 if ( !currentView() ) 188 if ( !currentView() )
190 return; 189 return;
191 190
192 PDirLister *lister = currentView()->dirLister(); 191 PDirLister *lister = currentView()->dirLister();
193 if (!lister ) 192 if (!lister )
194 return; 193 return;
195 194
196 lister->setStartPath( path ); 195 lister->setStartPath( path );
197 m_path = lister->currentPath(); 196 m_path = lister->currentPath();
198 197
199 m_view->setUpdatesEnabled( false ); 198 m_view->viewport()->setUpdatesEnabled( false );
200 m_view->clear(); 199 m_view->clear();
201 addFolders( lister->folders() ); 200 addFolders( lister->folders() );
202 addFiles( lister->files() ); 201 addFiles( lister->files() );
203 m_view->setUpdatesEnabled( true ); 202 m_view->viewport()->setUpdatesEnabled( true );
204 203
205 // Also invalidate the cache. We can't cancel the operations anyway 204 // Also invalidate the cache. We can't cancel the operations anyway
206 g_stringPix.clear(); 205 g_stringPix.clear();
207 g_stringInf.clear(); 206 g_stringInf.clear();
208 207
209 // looks ugly 208 // looks ugly
210 static_cast<QMainWindow*>(parent())->setCaption( QObject::tr("%1 - O View", "Name of the dir").arg( m_path ) ); 209 static_cast<QMainWindow*>(parent())->setCaption( QObject::tr("%1 - O View", "Name of the dir").arg( m_path ) );
211} 210}
212 211
213QString PIconView::currentFileName(bool &isDir)const { 212QString PIconView::currentFileName(bool &isDir)const {
214 isDir = false; 213 isDir = false;
215 QIconViewItem* _it = m_view->currentItem(); 214 QIconViewItem* _it = m_view->currentItem();
216 if ( !_it ) 215 if ( !_it )
217 return QString::null; 216 return QString::null;
218 217
219 IconViewItem* it = static_cast<IconViewItem*>( _it ); 218 IconViewItem* it = static_cast<IconViewItem*>( _it );
220 isDir = it->isDir(); 219 isDir = it->isDir();
221 return it->path(); 220 return it->path();
222} 221}
223 222
224void PIconView::slotTrash() { 223void PIconView::slotTrash() {
225 bool isDir; 224 bool isDir;
226 QString pa = currentFileName( isDir ); 225 QString pa = currentFileName( isDir );
227 if ( isDir && pa.isEmpty() ) 226 if ( isDir && pa.isEmpty() )
228 return; 227 return;
229 228
230 if (!QPEMessageBox::confirmDelete( this, 229 if (!QPEMessageBox::confirmDelete( this,
231 tr("Delete Image" ), 230 tr("Delete Image" ),
232 tr("the Image %1" ).arg(pa))) 231 tr("the Image %1" ).arg(pa)))
233 return 232 return
234 233
235 234
236 currentView()->dirLister()->deleteImage( pa ); 235 currentView()->dirLister()->deleteImage( pa );
237 delete m_view->currentItem(); 236 delete m_view->currentItem();
238} 237}
239void PIconView::loadViews() { 238void PIconView::loadViews() {
240 ViewMap::Iterator it; 239 ViewMap::Iterator it;
241 ViewMap* map = viewMap(); 240 ViewMap* map = viewMap();
242 for ( it = map->begin(); it != map->end(); ++it ) 241 for ( it = map->begin(); it != map->end(); ++it )
243 m_views->insertItem( QObject::tr(it.key() ) ); 242 m_views->insertItem( QObject::tr(it.key() ) );
244} 243}
245 244
246void PIconView::resetView() { 245void PIconView::resetView() {
247 slotViewChanged(m_views->currentItem()); 246 slotViewChanged(m_views->currentItem());
248} 247}
249 248
250void PIconView::slotViewChanged( int i) { 249void PIconView::slotViewChanged( int i) {
251 if (!m_views->count() ) { 250 if (!m_views->count() ) {
252 setCurrentView( 0l); 251 setCurrentView( 0l);
253 return; 252 return;
254 } 253 }
255 254
256 PDirView* cur = currentView(); 255 PDirView* cur = currentView();
257 delete cur; 256 delete cur;
258 QString str = m_views->text(i); 257 QString str = m_views->text(i);
259 cur = (*(*viewMap())[str])(*m_cfg); 258 cur = (*(*viewMap())[str])(*m_cfg);
260 setCurrentView( cur ); 259 setCurrentView( cur );
261 260
262 /* connect to the signals of the lister */ 261 /* connect to the signals of the lister */
263 PDirLister* lis = cur->dirLister(); 262 PDirLister* lis = cur->dirLister();
264 connect(lis, SIGNAL(sig_thumbInfo(const QString&, const QString& )), 263 connect(lis, SIGNAL(sig_thumbInfo(const QString&, const QString& )),
265 this, SLOT( slotThumbInfo(const QString&, const QString&))); 264 this, SLOT( slotThumbInfo(const QString&, const QString&)));
266 connect(lis, SIGNAL( sig_thumbNail(const QString&, const QPixmap&)), 265 connect(lis, SIGNAL( sig_thumbNail(const QString&, const QPixmap&)),
267 this, SLOT(slotThumbNail(const QString&, const QPixmap&))); 266 this, SLOT(slotThumbNail(const QString&, const QPixmap&)));
268 connect(lis, SIGNAL(sig_start()), 267 connect(lis, SIGNAL(sig_start()),
269 this, SLOT(slotStart())); 268 this, SLOT(slotStart()));
270 connect(lis, SIGNAL(sig_end()) , 269 connect(lis, SIGNAL(sig_end()) ,
271 this, SLOT(slotEnd()) ); 270 this, SLOT(slotEnd()) );
272 271
273 272
274 /* reload now */ 273 /* reload now */
275 QTimer::singleShot( 0, this, SLOT(slotReloadDir())); 274 QTimer::singleShot( 0, this, SLOT(slotReloadDir()));
276} 275}
277 276
278 277
279void PIconView::slotReloadDir() { 278void PIconView::slotReloadDir() {
280 slotChangeDir( m_path ); 279 slotChangeDir( m_path );
281} 280}
282 281
283 282
284void PIconView::addFolders( const QStringList& lst) { 283void PIconView::addFolders( const QStringList& lst) {
285 QStringList::ConstIterator it; 284 QStringList::ConstIterator it;
286 285
287 for(it=lst.begin(); it != lst.end(); ++it ) { 286 for(it=lst.begin(); it != lst.end(); ++it ) {
288 (void)new IconViewItem( m_view, m_path+"/"+(*it), (*it), true ); 287 (void)new IconViewItem( m_view, m_path+"/"+(*it), (*it), true );
289 } 288 }
290 289
291} 290}
292 291
293void PIconView::addFiles( const QStringList& lst) { 292void PIconView::addFiles( const QStringList& lst) {
294 QStringList::ConstIterator it; 293 QStringList::ConstIterator it;
295 for (it=lst.begin(); it!= lst.end(); ++it ) 294 for (it=lst.begin(); it!= lst.end(); ++it )
296 (void)new IconViewItem( m_view, m_path+"/"+(*it), (*it) ); 295 (void)new IconViewItem( m_view, m_path+"/"+(*it), (*it) );
297 296
298} 297}
299 298
300void PIconView::slotClicked(QIconViewItem* _it) { 299void PIconView::slotClicked(QIconViewItem* _it) {
301 if(!_it ) 300 if(!_it )
302 return; 301 return;
303 302
304 IconViewItem* it = static_cast<IconViewItem*>(_it); 303 IconViewItem* it = static_cast<IconViewItem*>(_it);
305 if( it->isDir() ) 304 if( it->isDir() )
306 slotChangeDir( it->path() ); 305 slotChangeDir( it->path() );
307 else // view image 306 else // view image
308 ; 307 ;
309} 308}
310 309
311void PIconView::slotThumbInfo( const QString& _path, const QString& str ) { 310void PIconView::slotThumbInfo( const QString& _path, const QString& str ) {
312 if ( g_stringInf.contains( _path ) ) { 311 if ( g_stringInf.contains( _path ) ) {
313 IconViewItem* item = g_stringInf[_path]; 312 IconViewItem* item = g_stringInf[_path];
314 /* if set the view shows nonsens! 313 /* if set the view shows nonsens!
315 I dont know how to fix the format of displayed text :(*/ 314 I dont know how to fix the format of displayed text :(*/
316 item->setText( str ); 315 item->setText( str );
317 item->repaint();
318 g_stringInf.remove( _path ); 316 g_stringInf.remove( _path );
319 } 317 }
320} 318}
321void PIconView::slotThumbNail(const QString& _path, const QPixmap &pix) { 319void PIconView::slotThumbNail(const QString& _path, const QPixmap &pix) {
322 if ( g_stringPix.contains( _path ) ) { 320 if ( g_stringPix.contains( _path ) ) {
323 IconViewItem* item = g_stringPix[_path]; 321 IconViewItem* item = g_stringPix[_path];
324 322
325 if (pix.width()>0) { 323 if (pix.width()>0) {
326 PPixmapCache::self()->insertImage( _path, pix, 64, 64 ); 324 PPixmapCache::self()->insertImage( _path, pix, 64, 64 );
327 /* required for a recalculated rectangle. otherwise the view show nonsense! */ 325 /* required for a recalculated rectangle. otherwise the view show nonsense! */
328 item->reCalc();
329 } else { 326 } else {
330 PPixmapCache::self()->insertImage(_path,Resource::loadPixmap( "UnknownDocument" ),64,64 ); 327 PPixmapCache::self()->insertImage(_path,Resource::loadPixmap( "UnknownDocument" ),64,64 );
331 } 328 }
332 item->repaint();
333 g_stringPix.remove( _path ); 329 g_stringPix.remove( _path );
334 } 330 }
335} 331}
336 332
337 333
338void PIconView::slotRename() { 334void PIconView::slotRename() {
339 335
340} 336}
341 337
342void PIconView::slotBeam() { 338void PIconView::slotBeam() {
343 bool isDir; 339 bool isDir;
344 QString pa = currentFileName( isDir ); 340 QString pa = currentFileName( isDir );
345 if ( isDir && pa.isEmpty() ) 341 if ( isDir && pa.isEmpty() )
346 return; 342 return;
347 343
348 Ir* ir = new Ir( this ); 344 Ir* ir = new Ir( this );
349 connect( ir, SIGNAL(done(Ir*)), 345 connect( ir, SIGNAL(done(Ir*)),
350 this, SLOT(slotBeamDone(Ir*))); 346 this, SLOT(slotBeamDone(Ir*)));
351 ir->send(pa, tr( "Image" ) ); 347 ir->send(pa, tr( "Image" ) );
352 348
353} 349}
354 350
355void PIconView::slotBeamDone( Ir* ir) { 351void PIconView::slotBeamDone( Ir* ir) {
356 delete ir; 352 delete ir;
357} 353}
358 354
359void PIconView::slotStart() { 355void PIconView::slotStart() {
360 m_view->setUpdatesEnabled( false ); 356 m_view->viewport()->setUpdatesEnabled( false );
361} 357}
362 358
363void PIconView::slotEnd() { 359void PIconView::slotEnd() {
364 m_view->setUpdatesEnabled( true ); 360 m_view->arrangeItemsInGrid( );
361 m_view->viewport()->setUpdatesEnabled( true );
365} 362}
366 363
367void PIconView::slotShowImage() { 364void PIconView::slotShowImage() {
368 365
369} 366}
370void PIconView::slotShowImage( const QString& ) { 367void PIconView::slotShowImage( const QString& ) {
371 368
372} 369}
373void PIconView::slotImageInfo() { 370void PIconView::slotImageInfo() {
374 371
375} 372}
376void PIconView::slotImageInfo( const QString& ) { 373void PIconView::slotImageInfo( const QString& ) {
377 374
378} 375}
diff --git a/noncore/graphics/opie-eye/gui/mainwindow.cpp b/noncore/graphics/opie-eye/gui/mainwindow.cpp
index 0314659..83ff4f1 100644
--- a/noncore/graphics/opie-eye/gui/mainwindow.cpp
+++ b/noncore/graphics/opie-eye/gui/mainwindow.cpp
@@ -1,138 +1,138 @@
1/* 1/*
2 * GPLv2 zecke@handhelds.org 2 * GPLv2 zecke@handhelds.org
3 * No WArranty... 3 * No WArranty...
4 */ 4 */
5#include "mainwindow.h" 5#include "mainwindow.h"
6 6
7#include "iconview.h" 7#include "iconview.h"
8#include "filesystem.h" 8#include "filesystem.h"
9 9
10#include <iface/ifaceinfo.h> 10#include <iface/ifaceinfo.h>
11#include <iface/dirview.h> 11#include <iface/dirview.h>
12 12
13#include <opie2/oapplicationfactory.h> 13#include <opie2/oapplicationfactory.h>
14#include <opie2/otabwidget.h> 14#include <opie2/otabwidget.h>
15#include <opie2/okeyconfigwidget.h> 15#include <opie2/okeyconfigwidget.h>
16 16
17 17
18#include <qpe/resource.h> 18#include <qpe/resource.h>
19#include <qpe/config.h> 19#include <qpe/config.h>
20#include <qpe/ir.h> 20#include <qpe/ir.h>
21 21
22#include <qtoolbar.h> 22#include <qtoolbar.h>
23#include <qtoolbutton.h> 23#include <qtoolbutton.h>
24#include <qlayout.h> 24#include <qlayout.h>
25#include <qdialog.h> 25#include <qdialog.h>
26#include <qmap.h> 26#include <qmap.h>
27 27
28 28
29 29
30 30
31 31
32OPIE_EXPORT_APP( Opie::Core::OApplicationFactory<PMainWindow> ) 32OPIE_EXPORT_APP( Opie::Core::OApplicationFactory<PMainWindow> )
33 33
34PMainWindow::PMainWindow(QWidget* wid, const char* name, WFlags style) 34PMainWindow::PMainWindow(QWidget* wid, const char* name, WFlags style)
35 : QMainWindow( wid, name, style ) 35 : QMainWindow( wid, name, style )
36{ 36{
37 setCaption( QObject::tr("Opie Eye Caramba" ) ); 37 setCaption( QObject::tr("Opie Eye Caramba" ) );
38 m_cfg = new Opie::Core::OConfig("phunkview"); 38 m_cfg = new Opie::Core::OConfig("phunkview");
39 m_cfg->setGroup("Zecke_view" ); 39 m_cfg->setGroup("Zecke_view" );
40 40
41 41
42 /* 42 /*
43 * Initialize ToolBar and IconView 43 * Initialize ToolBar and IconView
44 * And Connect Them 44 * And Connect Them
45 */ 45 */
46 QToolBar *bar = new QToolBar( this ); 46 QToolBar *bar = new QToolBar( this );
47 bar->setHorizontalStretchable( true ); 47 bar->setHorizontalStretchable( true );
48 setToolBarsMovable( false ); 48 setToolBarsMovable( false );
49 49
50 m_view = new PIconView( this, m_cfg ); 50 m_view = new PIconView( this, m_cfg );
51 setCentralWidget( m_view ); 51 setCentralWidget( m_view );
52 52
53 QToolButton *btn = new QToolButton( bar ); 53 QToolButton *btn = new QToolButton( bar );
54 btn->setIconSet( Resource::loadIconSet( "up" ) ); 54 btn->setIconSet( Resource::loadIconSet( "up" ) );
55 connect( btn, SIGNAL(clicked()), 55 connect( btn, SIGNAL(clicked()),
56 m_view, SLOT(slotDirUp()) ); 56 m_view, SLOT(slotDirUp()) );
57 57
58 btn = new PFileSystem( bar ); 58 btn = new PFileSystem( bar );
59 connect( btn, SIGNAL( changeDir( const QString& ) ), 59 connect( btn, SIGNAL( changeDir( const QString& ) ),
60 m_view, SLOT(slotChangeDir( const QString& ) ) ); 60 m_view, SLOT(slotChangeDir( const QString& ) ) );
61 61
62 btn = new QToolButton( bar ); 62 btn = new QToolButton( bar );
63 btn->setIconSet( Resource::loadIconSet( "edit" ) ); 63 btn->setIconSet( Resource::loadIconSet( "edit" ) );
64 connect( btn, SIGNAL(clicked()), 64 connect( btn, SIGNAL(clicked()),
65 m_view, SLOT(slotRename()) ); 65 m_view, SLOT(slotRename()) );
66 66
67 if ( Ir::supported() ) { 67 if ( Ir::supported() ) {
68 btn = new QToolButton( bar ); 68 btn = new QToolButton( bar );
69 btn->setIconSet( Resource::loadIconSet( "beam" ) ); 69 btn->setIconSet( Resource::loadIconSet( "beam" ) );
70 connect( btn, SIGNAL(clicked()), 70 connect( btn, SIGNAL(clicked()),
71 m_view, SLOT(slotBeam()) ); 71 m_view, SLOT(slotBeam()) );
72 } 72 }
73 73
74 btn = new QToolButton( bar ); 74 btn = new QToolButton( bar );
75 btn->setIconSet( Resource::loadIconSet( "trash" ) ); 75 btn->setIconSet( Resource::loadIconSet( "trash" ) );
76 connect( btn, SIGNAL(clicked() ), 76 connect( btn, SIGNAL(clicked() ),
77 m_view, SLOT(slotTrash() ) ); 77 m_view, SLOT(slotTrash() ) );
78 78
79 btn = new QToolButton( bar ); 79 btn = new QToolButton( bar );
80 btn->setIconSet( Resource::loadIconSet( "SettingsIcon" ) ); 80 btn->setIconSet( Resource::loadIconSet( "SettingsIcon" ) );
81 connect( btn, SIGNAL(clicked() ), 81 connect( btn, SIGNAL(clicked() ),
82 this, SLOT(slotConfig() ) ); 82 this, SLOT(slotConfig() ) );
83 83
84} 84}
85 85
86PMainWindow::~PMainWindow() { 86PMainWindow::~PMainWindow() {
87} 87}
88 88
89 89
90void PMainWindow::slotConfig() { 90void PMainWindow::slotConfig() {
91/* 91/*
92 * have a tab with the possible views 92 * have a tab with the possible views
93 * a tab for globals image cache size.. scaled loading 93 * a tab for globals image cache size.. scaled loading
94 * and one tab for the KeyConfigs 94 * and one tab for the KeyConfigs
95 */ 95 */
96 QDialog dlg(this, 0, true); 96 QDialog dlg(this, 0, true);
97 dlg.setCaption( tr("Phunk View - Config" ) ); 97 dlg.setCaption( tr("Phunk View - Config" ) );
98 98
99 QHBoxLayout *lay = new QHBoxLayout(&dlg); 99 QHBoxLayout *lay = new QHBoxLayout(&dlg);
100 Opie::Ui::OTabWidget *wid = new Opie::Ui::OTabWidget(&dlg ); 100 Opie::Ui::OTabWidget *wid = new Opie::Ui::OTabWidget(&dlg );
101 lay->addWidget( wid ); 101 lay->addWidget( wid );
102 ViewMap *vM = viewMap(); 102 ViewMap *vM = viewMap();
103 ViewMap::Iterator _it = vM->begin(); 103 ViewMap::Iterator _it = vM->begin();
104 QMap<PDirView*, QWidget*> lst; 104 QMap<PDirView*, QWidget*> lst;
105 105
106 for( ; _it != vM->end(); ++_it ) { 106 for( ; _it != vM->end(); ++_it ) {
107 PDirView *view = (_it.data())(*m_cfg); 107 PDirView *view = (_it.data())(*m_cfg);
108 PInterfaceInfo *inf = view->interfaceInfo(); 108 PInterfaceInfo *inf = view->interfaceInfo();
109 QWidget *_wid = inf->configWidget( *m_cfg ); 109 QWidget *_wid = inf->configWidget( *m_cfg );
110 _wid->reparent(wid, QPoint() ); 110 _wid->reparent(wid, QPoint() );
111 lst.insert( view, _wid ); 111 lst.insert( view, _wid );
112 wid->addTab( _wid, QString::null, inf->name() ); 112 wid->addTab( _wid, "fileopen", inf->name() );
113 } 113 }
114 114
115/* 115/*
116 * Add the KeyConfigWidget 116 * Add the KeyConfigWidget
117 */ 117 */
118 Opie::Ui::OKeyConfigWidget* keyWid = new Opie::Ui::OKeyConfigWidget( wid, "key config" ); 118 Opie::Ui::OKeyConfigWidget* keyWid = new Opie::Ui::OKeyConfigWidget( wid, "key config" );
119 keyWid->setChangeMode( Opie::Ui::OKeyConfigWidget::Queue ); 119 keyWid->setChangeMode( Opie::Ui::OKeyConfigWidget::Queue );
120 keyWid->insert( tr("Browser Keyboard Actions"), m_view->manager() ); 120 keyWid->insert( tr("Browser Keyboard Actions"), m_view->manager() );
121 keyWid->load(); 121 keyWid->load();
122 wid->addTab( keyWid, QString::fromLatin1("AppsIcon" ), tr("Keyboard Configuration") ); 122 wid->addTab( keyWid, QString::fromLatin1("AppsIcon" ), tr("Keyboard Configuration") );
123 123
124 124
125 bool act = ( QPEApplication::execDialog( &dlg ) == QDialog::Accepted ); 125 bool act = ( QPEApplication::execDialog( &dlg ) == QDialog::Accepted );
126 126
127 QMap<PDirView*, QWidget*>::Iterator it; 127 QMap<PDirView*, QWidget*>::Iterator it;
128 for ( it = lst.begin(); it != lst.end(); ++it ) { 128 for ( it = lst.begin(); it != lst.end(); ++it ) {
129 if ( act ) 129 if ( act )
130 it.key()->interfaceInfo()->writeConfig(it.data(), *m_cfg); 130 it.key()->interfaceInfo()->writeConfig(it.data(), *m_cfg);
131 delete it.key(); 131 delete it.key();
132 } 132 }
133 133
134 if ( act ) { 134 if ( act ) {
135 m_view->resetView(); 135 m_view->resetView();
136 keyWid->save(); 136 keyWid->save();
137 } 137 }
138} 138}
diff --git a/noncore/graphics/opie-eye/slave/gif_slave.cpp b/noncore/graphics/opie-eye/slave/gif_slave.cpp
index feb69b6..f0dc86e 100644
--- a/noncore/graphics/opie-eye/slave/gif_slave.cpp
+++ b/noncore/graphics/opie-eye/slave/gif_slave.cpp
@@ -1,305 +1,306 @@
1#include "gif_slave.h" 1#include "gif_slave.h"
2 2
3#include "thumbnailtool.h" 3#include "thumbnailtool.h"
4 4
5#include <qimage.h> 5#include <qimage.h>
6#include <qobject.h> 6#include <qobject.h>
7#include <qfile.h> 7#include <qfile.h>
8#include <qpixmap.h> 8#include <qpixmap.h>
9 9
10 10
11PHUNK_VIEW_INTERFACE( "Gif", GifSlave ); 11PHUNK_VIEW_INTERFACE( "Gif", GifSlave );
12 12
13 13
14namespace { 14namespace {
15/* 15/*
16** $Id$ 16** $Id$
17** 17**
18** Minimal GIF parser, for use in extracting and setting metadata. 18** Minimal GIF parser, for use in extracting and setting metadata.
19** Modified for standalone & KDE calling by Bryce Nesbitt 19** Modified for standalone & KDE calling by Bryce Nesbitt
20** 20**
21** TODO: 21** TODO:
22** Support gif comments that span more than one comment block. 22** Support gif comments that span more than one comment block.
23** Verify that Unicode utf-8 is fully unmolested by this code. 23** Verify that Unicode utf-8 is fully unmolested by this code.
24** Implement gif structure verifier. 24** Implement gif structure verifier.
25** 25**
26** Based on: GIFtrans v1.12.2 26** Based on: GIFtrans v1.12.2
27** Copyright (C) 24.2.94 by Andreas Ley <ley@rz.uni-karlsruhe.de> 27** Copyright (C) 24.2.94 by Andreas Ley <ley@rz.uni-karlsruhe.de>
28** 28**
29******************************************************************************* 29*******************************************************************************
30** 30**
31** Original distribution site is 31** Original distribution site is
32** ftp://ftp.rz.uni-karlsruhe.de/pub/net/www/tools/giftrans/giftrans.c 32** ftp://ftp.rz.uni-karlsruhe.de/pub/net/www/tools/giftrans/giftrans.c
33** A man-page by knordlun@fltxa.helsinki.fi (Kai Nordlund) is at 33** A man-page by knordlun@fltxa.helsinki.fi (Kai Nordlund) is at
34** ftp://ftp.rz.uni-karlsruhe.de/pub/net/www/tools/giftrans/giftrans.1 34** ftp://ftp.rz.uni-karlsruhe.de/pub/net/www/tools/giftrans/giftrans.1
35** An online version by taylor@intuitive.com (Dave Taylor) is at 35** An online version by taylor@intuitive.com (Dave Taylor) is at
36** http://www.intuitive.com/coolweb/Addons/giftrans-doc.html 36** http://www.intuitive.com/coolweb/Addons/giftrans-doc.html
37** To compile for MS-DOS or OS/2, you need getopt: 37** To compile for MS-DOS or OS/2, you need getopt:
38** ftp://ftp.rz.uni-karlsruhe.de/pub/net/www/tools/giftrans/getopt.c 38** ftp://ftp.rz.uni-karlsruhe.de/pub/net/www/tools/giftrans/getopt.c
39** MS-DOS executable can be found at 39** MS-DOS executable can be found at
40** ftp://ftp.rz.uni-karlsruhe.de/pub/net/www/tools/giftrans/giftrans.exe 40** ftp://ftp.rz.uni-karlsruhe.de/pub/net/www/tools/giftrans/giftrans.exe
41** OS/2 executable can be found at 41** OS/2 executable can be found at
42** ftp://ftp.rz.uni-karlsruhe.de/pub/net/www/tools/giftrans/giftrans.os2.exe 42** ftp://ftp.rz.uni-karlsruhe.de/pub/net/www/tools/giftrans/giftrans.os2.exe
43** A template rgb.txt for use with the MS-DOS version can be found at 43** A template rgb.txt for use with the MS-DOS version can be found at
44** ftp://ftp.rz.uni-karlsruhe.de/pub/net/www/tools/giftrans/rgb.txt 44** ftp://ftp.rz.uni-karlsruhe.de/pub/net/www/tools/giftrans/rgb.txt
45** Additional info can be found on 45** Additional info can be found on
46** http://melmac.corp.harris.com/transparent_images.html 46** http://melmac.corp.harris.com/transparent_images.html
47** 47**
48** The GIF file format is documented in 48** The GIF file format is documented in
49** ftp://ftp.uu.net/doc/literary/obi/Standards/Graphics/Formats/gif89a.doc.Z 49** ftp://ftp.uu.net/doc/literary/obi/Standards/Graphics/Formats/gif89a.doc.Z
50** A good quick reference is at: 50** A good quick reference is at:
51** http://www.goice.co.jp/member/mo/formats/gif.html 51** http://www.goice.co.jp/member/mo/formats/gif.html
52** 52**
53******************************************************************************* 53*******************************************************************************
54** 54**
55** This program is free software; you can redistribute it and/or modify 55** This program is free software; you can redistribute it and/or modify
56** it under the terms of the GNU General Public License as published by 56** it under the terms of the GNU General Public License as published by
57** the Free Software Foundation; either version 2 of the License, or 57** the Free Software Foundation; either version 2 of the License, or
58** (at your option) any later version. 58** (at your option) any later version.
59** 59**
60** This program is distributed in the hope that it will be useful, 60** This program is distributed in the hope that it will be useful,
61** but WITHOUT ANY WARRANTY; without even the implied warranty of 61** but WITHOUT ANY WARRANTY; without even the implied warranty of
62** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 62** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
63** GNU General Public License for more details. 63** GNU General Public License for more details.
64** 64**
65** You should have received a copy of the GNU General Public License 65** You should have received a copy of the GNU General Public License
66** along with this program; if not, write to the Free Software 66** along with this program; if not, write to the Free Software
67** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 67** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
68** 68**
69*/ 69*/
70#define SUCCESS (0) 70#define SUCCESS (0)
71#define FAILURE (1) 71#define FAILURE (1)
72 72
73#define READ_BINARY "r" 73#define READ_BINARY "r"
74#define WRITE_BINARY "w" 74#define WRITE_BINARY "w"
75 75
76 76
77static long int pos; 77static long int pos;
78static char skipcomment,verbose; 78static char skipcomment,verbose;
79char *global_comment; 79char *global_comment;
80 80
81#define readword(buffer) ((buffer)[0]+256*(buffer)[1]) 81#define readword(buffer) ((buffer)[0]+256*(buffer)[1])
82#define readflag(buffer) ((buffer)?true:false) 82#define readflag(buffer) ((buffer)?true:false)
83#define hex(c) ('a'<=(c)&&(c)<='z'?(c)-'a'+10:'A'<=(c)&&(c)<='Z'?(c)-'A'+10:(c)-'0') 83#define hex(c) ('a'<=(c)&&(c)<='z'?(c)-'a'+10:'A'<=(c)&&(c)<='Z'?(c)-'A'+10:(c)-'0')
84 84
85static bool debug = false; 85static bool debug = false;
86static bool output= false; 86static bool output= false;
87 87
88void dump(long int, unsigned char *, size_t) { 88void dump(long int, unsigned char *, size_t) {
89} 89}
90 90
91void skipdata(FILE *src) 91void skipdata(FILE *src)
92{ 92{
93 unsigned char size,buffer[256]; 93 unsigned char size,buffer[256];
94 94
95 do { 95 do {
96 pos=ftell(src); 96 pos=ftell(src);
97 (void)fread((void *)&size,1,1,src); 97 (void)fread((void *)&size,1,1,src);
98 if (debug) 98 if (debug)
99 dump(pos,&size,1); 99 dump(pos,&size,1);
100 if (debug) { 100 if (debug) {
101 pos=ftell(src); 101 pos=ftell(src);
102 (void)fread((void *)buffer,(size_t)size,1,src); 102 (void)fread((void *)buffer,(size_t)size,1,src);
103 dump(pos,buffer,(size_t)size); 103 dump(pos,buffer,(size_t)size);
104 } 104 }
105 else 105 else
106 (void)fseek(src,(long int)size,SEEK_CUR); 106 (void)fseek(src,(long int)size,SEEK_CUR);
107 } while (!feof(src)&&size>0); 107 } while (!feof(src)&&size>0);
108} 108}
109 109
110 110
111void transdata(FILE *src, FILE *dest) 111void transdata(FILE *src, FILE *dest)
112{ 112{
113 unsigned char size,buffer[256]; 113 unsigned char size,buffer[256];
114 114
115 do { 115 do {
116 pos=ftell(src); 116 pos=ftell(src);
117 (void)fread((void *)&size,1,1,src); 117 (void)fread((void *)&size,1,1,src);
118 pos=ftell(src); 118 pos=ftell(src);
119 (void)fread((void *)buffer,(size_t)size,1,src); 119 (void)fread((void *)buffer,(size_t)size,1,src);
120 if (debug) 120 if (debug)
121 dump(pos,buffer,(size_t)size); 121 dump(pos,buffer,(size_t)size);
122 if (output) 122 if (output)
123 (void)fwrite((void *)buffer,(size_t)size,1,dest); 123 (void)fwrite((void *)buffer,(size_t)size,1,dest);
124 } while (!feof(src)&&size>0); 124 } while (!feof(src)&&size>0);
125} 125}
126 126
127void transblock(FILE *src, FILE* dest) 127void transblock(FILE *src, FILE* dest)
128{ 128{
129 unsigned char size,buffer[256]; 129 unsigned char size,buffer[256];
130 130
131 pos=ftell(src); 131 pos=ftell(src);
132 (void)fread((void *)&size,1,1,src); 132 (void)fread((void *)&size,1,1,src);
133 if (debug) 133 if (debug)
134 dump(pos,&size,1); 134 dump(pos,&size,1);
135 if (output) 135 if (output)
136 (void)fwrite((void *)&size,1,1,dest); 136 (void)fwrite((void *)&size,1,1,dest);
137 pos=ftell(src); 137 pos=ftell(src);
138 (void)fread((void *)buffer,(size_t)size,1,src); 138 (void)fread((void *)buffer,(size_t)size,1,src);
139 if (debug) 139 if (debug)
140 dump(pos,buffer,(size_t)size); 140 dump(pos,buffer,(size_t)size);
141 if (output) 141 if (output)
142 (void)fwrite((void *)buffer,(size_t)size,1,dest); 142 (void)fwrite((void *)buffer,(size_t)size,1,dest);
143} 143}
144 144
145void dumpcomment(FILE *src, QCString& str) 145void dumpcomment(FILE *src, QCString& str)
146{ 146{
147 unsigned char size; 147 unsigned char size;
148 148
149 pos=ftell(src); 149 pos=ftell(src);
150 (void)fread((void *)&size,1,1,src); 150 (void)fread((void *)&size,1,1,src);
151 if (debug) 151 if (debug)
152 dump(pos,&size,1); 152 dump(pos,&size,1);
153 str.resize( size+1 ); 153 str.resize( size+1 );
154 (void)fread((void *)str.data(),size,1,src); 154 (void)fread((void *)str.data(),size,1,src);
155 (void)fseek(src,(long int)pos,SEEK_SET); 155 (void)fseek(src,(long int)pos,SEEK_SET);
156} 156}
157 157
158 158
159 159
160 160
161int giftrans(FILE *src, FILE* dest, QString& str, bool full) 161int giftrans(FILE *src, FILE* dest, QString& str, bool full)
162{ 162{
163 unsigned char buffer[3*256],lsd[7],gct[3*256]; 163 unsigned char buffer[3*256],lsd[7],gct[3*256];
164 unsigned int size,gct_size; 164 unsigned int size,gct_size;
165 165
166 /* Header */ 166 /* Header */
167 pos=ftell(src); 167 pos=ftell(src);
168 (void)fread((void *)buffer,6,1,src); 168 (void)fread((void *)buffer,6,1,src);
169 if (strncmp((char *)buffer,"GIF",3)) { 169 if (strncmp((char *)buffer,"GIF",3)) {
170 str = QObject::tr("Not a GIF file"); 170 str = QObject::tr("Not a GIF file");
171 (void)fprintf(stderr,"Not GIF file!\n"); 171 (void)fprintf(stderr,"Not GIF file!\n");
172 return(1); 172 return(1);
173 } 173 }
174 174
175 /* Logical Screen Descriptor */ 175 /* Logical Screen Descriptor */
176 pos=ftell(src); 176 pos=ftell(src);
177 (void)fread((void *)lsd,7,1,src); 177 (void)fread((void *)lsd,7,1,src);
178 //(void)fprintf(stderr,"Logical Screen Descriptor:\n"); 178 //(void)fprintf(stderr,"Logical Screen Descriptor:\n");
179 str += QObject::tr("Dimensions: %1x%2\n").arg( readword(lsd) ).arg( readword(lsd+2 ) ); 179 str += QObject::tr("Dimensions: %1x%2\n").arg( readword(lsd) ).arg( readword(lsd+2 ) );
180 //(void)fprintf(stderr,"Global Color Table Flag: %s\n",readflag(lsd[4]&0x80)); 180 //(void)fprintf(stderr,"Global Color Table Flag: %s\n",readflag(lsd[4]&0x80));
181 str += QObject::tr("Depth: %1 bits\n").arg( (lsd[4]&0x70>>4 )+1); 181 str += QObject::tr("Depth: %1 bits\n").arg( (lsd[4]&0x70>>4 )+1);
182 //(void)fprintf(stderr,"Depth : %d bits\n",(lsd[4]&0x70>>4)+1); 182 //(void)fprintf(stderr,"Depth : %d bits\n",(lsd[4]&0x70>>4)+1);
183 if (lsd[4]&0x80 && full) { 183 if (lsd[4]&0x80 && full) {
184 str += QObject::tr("Sort Flag: %1\n" ).arg(readflag(lsd[4]&0x8) ); 184 str += QObject::tr("Sort Flag: %1\n" ).arg(readflag(lsd[4]&0x8) );
185 str += QObject::tr("Size of Global Color Table: %1 colors\n" ).arg( 2<<(lsd[4]&0x7)); 185 str += QObject::tr("Size of Global Color Table: %1 colors\n" ).arg( 2<<(lsd[4]&0x7));
186 str += QObject::tr("Background Color Index: %1\n" ).arg(lsd[5]); 186 str += QObject::tr("Background Color Index: %1\n" ).arg(lsd[5]);
187 } 187 }
188 if (lsd[6] && full) 188 if (lsd[6] && full)
189 str += QObject::tr("Pixel Aspect Ratio: %1 (Aspect Ratio %2)\n" ).arg( lsd[6] ). 189 str += QObject::tr("Pixel Aspect Ratio: %1 (Aspect Ratio %2)\n" ).arg( lsd[6] ).
190 arg( ((double)lsd[6]+15)/64 ); 190 arg( ((double)lsd[6]+15)/64 );
191 191
192 /* Global Color Table */ 192 /* Global Color Table */
193 if (lsd[4]&0x80) { 193 if (lsd[4]&0x80) {
194 gct_size=2<<(lsd[4]&0x7); 194 gct_size=2<<(lsd[4]&0x7);
195 pos=ftell(src); 195 pos=ftell(src);
196 (void)fread((void *)gct,gct_size,3,src); 196 (void)fread((void *)gct,gct_size,3,src);
197 } 197 }
198 198
199 do { 199 do {
200 pos=ftell(src); 200 pos=ftell(src);
201 (void)fread((void *)buffer,1,1,src); 201 (void)fread((void *)buffer,1,1,src);
202 switch (buffer[0]) { 202 switch (buffer[0]) {
203 case 0x2c: /* Image Descriptor */ 203 case 0x2c: /* Image Descriptor */
204 (void)fread((void *)(buffer+1),9,1,src); 204 (void)fread((void *)(buffer+1),9,1,src);
205 /* Local Color Table */ 205 /* Local Color Table */
206 if (buffer[8]&0x80) { 206 if (buffer[8]&0x80) {
207 size=2<<(buffer[8]&0x7); 207 size=2<<(buffer[8]&0x7);
208 pos=ftell(src); 208 pos=ftell(src);
209 (void)fread((void *)buffer,size,3,src); 209 (void)fread((void *)buffer,size,3,src);
210 } 210 }
211 /* Table Based Image Data */ 211 /* Table Based Image Data */
212 pos=ftell(src); 212 pos=ftell(src);
213 (void)fread((void *)buffer,1,1,src); 213 (void)fread((void *)buffer,1,1,src);
214 transdata(src,dest); 214 transdata(src,dest);
215 break; 215 break;
216 case 0x21: /* Extension */ 216 case 0x21: /* Extension */
217 (void)fread((void *)(buffer+1),1,1,src); 217 (void)fread((void *)(buffer+1),1,1,src);
218 switch (buffer[1]) { 218 switch (buffer[1]) {
219 case 0xfe: /* Comment Extension */ 219 case 0xfe: /* Comment Extension */
220 if (true) 220 if (true)
221 { 221 {
222 QCString st; 222 QCString st;
223 dumpcomment(src, st); 223 dumpcomment(src, st);
224 str += QObject::tr("Comment: %1\n" ).arg( st ); 224 str += QObject::tr("Comment: %1\n" ).arg( st );
225 } 225 }
226 if (skipcomment) 226 if (skipcomment)
227 skipdata(src); 227 skipdata(src);
228 else { 228 else {
229 transdata(src,dest); 229 transdata(src,dest);
230 } 230 }
231 break; 231 break;
232 case 0x01: /* Plain Text Extension */ 232 case 0x01: /* Plain Text Extension */
233 case 0xf9: /* Graphic Control Extension */ 233 case 0xf9: /* Graphic Control Extension */
234 case 0xff: /* Application Extension */ 234 case 0xff: /* Application Extension */
235 default: 235 default:
236 transblock(src,dest); 236 transblock(src,dest);
237 transdata(src,dest); 237 transdata(src,dest);
238 break; 238 break;
239 } 239 }
240 break; 240 break;
241 case 0x3b: /* Trailer (write comment just before here) */ 241 case 0x3b: /* Trailer (write comment just before here) */
242 break; 242 break;
243 default: 243 default:
244 (void)fprintf(stderr,"0x%08lx: Error, unknown block 0x%02x!\n",ftell(src)-1,buffer[0]); 244 (void)fprintf(stderr,"0x%08lx: Error, unknown block 0x%02x!\n",ftell(src)-1,buffer[0]);
245 return(1); 245 return(1);
246 } 246 }
247 } while (buffer[0]!=0x3b&&!feof(src)); 247 } while (buffer[0]!=0x3b&&!feof(src));
248 return(buffer[0]==0x3b?SUCCESS:FAILURE); 248 return(buffer[0]==0x3b?SUCCESS:FAILURE);
249} 249}
250 250
251 251
252/****************************************************************************/ 252/****************************************************************************/
253extern void get_gif_info( const char * original_filename, QString& str, 253extern void get_gif_info( const char * original_filename, QString& str,
254 bool full =false) 254 bool full =false)
255{ 255{
256FILE * infile; 256FILE * infile;
257 257
258 if ((infile = fopen(original_filename, READ_BINARY)) == NULL) { 258 if ((infile = fopen(original_filename, READ_BINARY)) == NULL) {
259 fprintf(stderr, "can't open gif image '%s'\n", original_filename); 259 fprintf(stderr, "can't open gif image '%s'\n", original_filename);
260 return ; 260 return ;
261 } 261 }
262 262
263 output = FALSE; 263 output = FALSE;
264 verbose = TRUE; 264 verbose = TRUE;
265 debug = FALSE; 265 debug = FALSE;
266 skipcomment = FALSE; 266 skipcomment = FALSE;
267 giftrans( infile, NULL, str, full ); 267 giftrans( infile, NULL, str, full );
268 fclose( infile ); 268 fclose( infile );
269} 269}
270 270
271} 271}
272 272
273 273
274GifSlave::GifSlave() 274GifSlave::GifSlave()
275 : SlaveInterface(QStringList("gif")) 275 : SlaveInterface(QStringList("gif"))
276{} 276{}
277 277
278GifSlave::~GifSlave() { 278GifSlave::~GifSlave() {
279 279
280} 280}
281 281
282QString GifSlave::iconViewName(const QString& str) { 282QString GifSlave::iconViewName(const QString& str) {
283 QString st; 283 QString st;
284 get_gif_info(QFile::encodeName( str ).data(), st ); 284 get_gif_info(QFile::encodeName( str ).data(), st );
285 return st; 285 return st;
286} 286}
287 287
288QString GifSlave::fullImageInfo( const QString& str) { 288QString GifSlave::fullImageInfo( const QString& str) {
289 QString st; 289 QString st = "<qt>";
290 get_gif_info(QFile::encodeName( str ).data(), st, true ); 290 get_gif_info(QFile::encodeName( str ).data(), st, true );
291 st.append( "</qt>" );
291 return st; 292 return st;
292} 293}
293 294
294QPixmap GifSlave::pixmap(const QString& path, int width, int height ) { 295QPixmap GifSlave::pixmap(const QString& path, int width, int height ) {
295 static QImage img; 296 static QImage img;
296 img.load( path ); 297 img.load( path );
297 if ( img.isNull() ) { 298 if ( img.isNull() ) {
298 QPixmap pix; 299 QPixmap pix;
299 return pix; 300 return pix;
300 } 301 }
301 302
302 return ThumbNailTool::scaleImage( img, width,height ); 303 return ThumbNailTool::scaleImage( img, width,height );
303} 304}
304 305
305 306
diff --git a/noncore/graphics/opie-eye/slave/jpeg_slave.cpp b/noncore/graphics/opie-eye/slave/jpeg_slave.cpp
index 95055fd..086b47f 100644
--- a/noncore/graphics/opie-eye/slave/jpeg_slave.cpp
+++ b/noncore/graphics/opie-eye/slave/jpeg_slave.cpp
@@ -1,1426 +1,1425 @@
1#include "jpeg_slave.h" 1#include "jpeg_slave.h"
2 2
3#include "thumbnailtool.h" 3#include "thumbnailtool.h"
4 4
5PHUNK_VIEW_INTERFACE( "JPEG", JpegSlave ) 5PHUNK_VIEW_INTERFACE( "JPEG", JpegSlave )
6 6
7#include <qtopia/timestring.h> 7#include <qtopia/timestring.h>
8#include <qobject.h> 8#include <qobject.h>
9#include <qimage.h> 9#include <qimage.h>
10 10
11/** 11/**
12 exif.h 12 exif.h
13*/ 13*/
14 14
15#include <stdio.h> 15#include <stdio.h>
16#include <stdlib.h> 16#include <stdlib.h>
17#include <math.h> 17#include <math.h>
18#include <time.h> 18#include <time.h>
19 19
20#include <qstring.h> 20#include <qstring.h>
21#include <qfile.h> 21#include <qfile.h>
22#include <qimage.h> 22#include <qimage.h>
23 23
24typedef enum { 24typedef enum {
25 READ_EXIF = 1, 25 READ_EXIF = 1,
26 READ_IMAGE = 2, 26 READ_IMAGE = 2,
27 READ_ALL = 3 27 READ_ALL = 3
28}ReadMode_t; 28}ReadMode_t;
29 29
30//-------------------------------------------------------------------------- 30//--------------------------------------------------------------------------
31// This structure is used to store jpeg file sections in memory. 31// This structure is used to store jpeg file sections in memory.
32typedef struct { 32typedef struct {
33 uchar * Data; 33 uchar * Data;
34 int Type; 34 int Type;
35 unsigned Size; 35 unsigned Size;
36}Section_t; 36}Section_t;
37 37
38typedef unsigned char uchar; 38typedef unsigned char uchar;
39 39
40typedef struct { 40typedef struct {
41 unsigned short Tag; 41 unsigned short Tag;
42 const char*const Desc; 42 const char*const Desc;
43}TagTable_t; 43}TagTable_t;
44 44
45#define MAX_SECTIONS 20 45#define MAX_SECTIONS 20
46#define PSEUDO_IMAGE_MARKER 0x123; // Extra value. 46#define PSEUDO_IMAGE_MARKER 0x123; // Extra value.
47 47
48class ExifData { 48class ExifData {
49 Section_t Sections[MAX_SECTIONS]; 49 Section_t Sections[MAX_SECTIONS];
50 50
51 QString CameraMake; 51 QString CameraMake;
52 QString CameraModel; 52 QString CameraModel;
53 QString DateTime; 53 QString DateTime;
54 int Orientation; 54 int Orientation;
55 int Height, Width; 55 int Height, Width;
56 int ExifImageLength, ExifImageWidth; 56 int ExifImageLength, ExifImageWidth;
57 int IsColor; 57 int IsColor;
58 int Process; 58 int Process;
59 int FlashUsed; 59 int FlashUsed;
60 float FocalLength; 60 float FocalLength;
61 float ExposureTime; 61 float ExposureTime;
62 float ApertureFNumber; 62 float ApertureFNumber;
63 float Distance; 63 float Distance;
64 int Whitebalance; 64 int Whitebalance;
65 int MeteringMode; 65 int MeteringMode;
66 float CCDWidth; 66 float CCDWidth;
67 float ExposureBias; 67 float ExposureBias;
68 int ExposureProgram; 68 int ExposureProgram;
69 int ISOequivalent; 69 int ISOequivalent;
70 int CompressionLevel; 70 int CompressionLevel;
71 QString UserComment; 71 QString UserComment;
72 QString Comment; 72 QString Comment;
73 QImage Thumbnail; 73 QImage Thumbnail;
74 74
75 int ReadJpegSections (QFile & infile, ReadMode_t ReadMode); 75 int ReadJpegSections (QFile & infile, ReadMode_t ReadMode);
76 void DiscardData(void); 76 void DiscardData(void);
77 int Get16u(void * Short); 77 int Get16u(void * Short);
78 int Get32s(void * Long); 78 int Get32s(void * Long);
79 unsigned Get32u(void * Long); 79 unsigned Get32u(void * Long);
80 double ConvertAnyFormat(void * ValuePtr, int Format); 80 double ConvertAnyFormat(void * ValuePtr, int Format);
81 void ProcessExifDir(unsigned char * DirStart, unsigned char * OffsetBase, unsigned ExifLength); 81 void ProcessExifDir(unsigned char * DirStart, unsigned char * OffsetBase, unsigned ExifLength);
82 void process_COM (const uchar * Data, int length); 82 void process_COM (const uchar * Data, int length);
83 void process_SOFn (const uchar * Data, int marker); 83 void process_SOFn (const uchar * Data, int marker);
84 int Get16m(const void * Short); 84 int Get16m(const void * Short);
85 void process_EXIF(unsigned char * CharBuf, unsigned int length); 85 void process_EXIF(unsigned char * CharBuf, unsigned int length);
86 int Exif2tm(struct tm * timeptr, char * ExifTime); 86 int Exif2tm(struct tm * timeptr, char * ExifTime);
87 87
88public: 88public:
89 ExifData(); 89 ExifData();
90 bool scan(const QString &); 90 bool scan(const QString &);
91 QString getCameraMake() { return CameraMake; } 91 QString getCameraMake() { return CameraMake; }
92 QString getCameraModel() { return CameraModel; } 92 QString getCameraModel() { return CameraModel; }
93 QString getDateTime() { return DateTime; } 93 QString getDateTime() { return DateTime; }
94 int getOrientation() { return Orientation; } 94 int getOrientation() { return Orientation; }
95 int getHeight() { return Height; } 95 int getHeight() { return Height; }
96 int getWidth() { return Width; } 96 int getWidth() { return Width; }
97 int getIsColor() { return IsColor; } 97 int getIsColor() { return IsColor; }
98 int getProcess() { return Process; } 98 int getProcess() { return Process; }
99 int getFlashUsed() { return FlashUsed; } 99 int getFlashUsed() { return FlashUsed; }
100 float getFocalLength() { return FocalLength; } 100 float getFocalLength() { return FocalLength; }
101 float getExposureTime() { return ExposureTime; } 101 float getExposureTime() { return ExposureTime; }
102 float getApertureFNumber() { return ApertureFNumber; } 102 float getApertureFNumber() { return ApertureFNumber; }
103 float getDistance() { return Distance; } 103 float getDistance() { return Distance; }
104 int getWhitebalance() { return Whitebalance; } 104 int getWhitebalance() { return Whitebalance; }
105 int getMeteringMode() { return MeteringMode; } 105 int getMeteringMode() { return MeteringMode; }
106 float getCCDWidth() { return CCDWidth; } 106 float getCCDWidth() { return CCDWidth; }
107 float getExposureBias() { return ExposureBias; } 107 float getExposureBias() { return ExposureBias; }
108 int getExposureProgram() { return ExposureProgram; } 108 int getExposureProgram() { return ExposureProgram; }
109 int getISOequivalent() { return ISOequivalent; } 109 int getISOequivalent() { return ISOequivalent; }
110 int getCompressionLevel() { return CompressionLevel; } 110 int getCompressionLevel() { return CompressionLevel; }
111 QString getUserComment() { return UserComment; } 111 QString getUserComment() { return UserComment; }
112 QString getComment() { return Comment; } 112 QString getComment() { return Comment; }
113 QImage getThumbnail(); 113 QImage getThumbnail();
114 bool isThumbnailSane(); 114 bool isThumbnailSane();
115 bool isNullThumbnail() { return !isThumbnailSane(); } 115 bool isNullThumbnail() { return !isThumbnailSane(); }
116}; 116};
117 117
118class FatalError { 118class FatalError {
119 const char* ex; 119 const char* ex;
120public: 120public:
121 FatalError(const char* s) { ex = s; } 121 FatalError(const char* s) { ex = s; }
122 void debug_print() const { qWarning("exception: %s", ex ); } 122 void debug_print() const { qWarning("exception: %s", ex ); }
123}; 123};
124 124
125 125
126 126
127static unsigned char * LastExifRefd; 127static unsigned char * LastExifRefd;
128static int ExifSettingsLength; 128static int ExifSettingsLength;
129static double FocalplaneXRes; 129static double FocalplaneXRes;
130static double FocalplaneUnits; 130static double FocalplaneUnits;
131static int MotorolaOrder = 0; 131static int MotorolaOrder = 0;
132static int SectionsRead; 132static int SectionsRead;
133//static int HaveAll; 133//static int HaveAll;
134 134
135//-------------------------------------------------------------------------- 135//--------------------------------------------------------------------------
136// Table of Jpeg encoding process names 136// Table of Jpeg encoding process names
137 137
138#define M_SOF0 0xC0 // Start Of Frame N 138#define M_SOF0 0xC0 // Start Of Frame N
139#define M_SOF1 0xC1 // N indicates which compression process 139#define M_SOF1 0xC1 // N indicates which compression process
140#define M_SOF2 0xC2 // Only SOF0-SOF2 are now in common use 140#define M_SOF2 0xC2 // Only SOF0-SOF2 are now in common use
141#define M_SOF3 0xC3 141#define M_SOF3 0xC3
142#define M_SOF5 0xC5 // NB: codes C4 and CC are NOT SOF markers 142#define M_SOF5 0xC5 // NB: codes C4 and CC are NOT SOF markers
143#define M_SOF6 0xC6 143#define M_SOF6 0xC6
144#define M_SOF7 0xC7 144#define M_SOF7 0xC7
145#define M_SOF9 0xC9 145#define M_SOF9 0xC9
146#define M_SOF10 0xCA 146#define M_SOF10 0xCA
147#define M_SOF11 0xCB 147#define M_SOF11 0xCB
148#define M_SOF13 0xCD 148#define M_SOF13 0xCD
149#define M_SOF14 0xCE 149#define M_SOF14 0xCE
150#define M_SOF15 0xCF 150#define M_SOF15 0xCF
151#define M_SOI 0xD8 // Start Of Image (beginning of datastream) 151#define M_SOI 0xD8 // Start Of Image (beginning of datastream)
152#define M_EOI 0xD9 // End Of Image (end of datastream) 152#define M_EOI 0xD9 // End Of Image (end of datastream)
153#define M_SOS 0xDA // Start Of Scan (begins compressed data) 153#define M_SOS 0xDA // Start Of Scan (begins compressed data)
154#define M_JFIF 0xE0 // Jfif marker 154#define M_JFIF 0xE0 // Jfif marker
155#define M_EXIF 0xE1 // Exif marker 155#define M_EXIF 0xE1 // Exif marker
156#define M_COM 0xFE // COMment 156#define M_COM 0xFE // COMment
157 157
158 158
159TagTable_t ProcessTable[] = { 159TagTable_t ProcessTable[] = {
160 { M_SOF0, "Baseline"}, 160 { M_SOF0, "Baseline"},
161 { M_SOF1, "Extended sequential"}, 161 { M_SOF1, "Extended sequential"},
162 { M_SOF2, "Progressive"}, 162 { M_SOF2, "Progressive"},
163 { M_SOF3, "Lossless"}, 163 { M_SOF3, "Lossless"},
164 { M_SOF5, "Differential sequential"}, 164 { M_SOF5, "Differential sequential"},
165 { M_SOF6, "Differential progressive"}, 165 { M_SOF6, "Differential progressive"},
166 { M_SOF7, "Differential lossless"}, 166 { M_SOF7, "Differential lossless"},
167 { M_SOF9, "Extended sequential, arithmetic coding"}, 167 { M_SOF9, "Extended sequential, arithmetic coding"},
168 { M_SOF10, "Progressive, arithmetic coding"}, 168 { M_SOF10, "Progressive, arithmetic coding"},
169 { M_SOF11, "Lossless, arithmetic coding"}, 169 { M_SOF11, "Lossless, arithmetic coding"},
170 { M_SOF13, "Differential sequential, arithmetic coding"}, 170 { M_SOF13, "Differential sequential, arithmetic coding"},
171 { M_SOF14, "Differential progressive, arithmetic coding"}, 171 { M_SOF14, "Differential progressive, arithmetic coding"},
172 { M_SOF15, "Differential lossless, arithmetic coding"}, 172 { M_SOF15, "Differential lossless, arithmetic coding"},
173 { 0, "Unknown"} 173 { 0, "Unknown"}
174}; 174};
175 175
176 176
177 177
178//-------------------------------------------------------------------------- 178//--------------------------------------------------------------------------
179// Describes format descriptor 179// Describes format descriptor
180static int BytesPerFormat[] = {0,1,1,2,4,8,1,1,2,4,8,4,8}; 180static int BytesPerFormat[] = {0,1,1,2,4,8,1,1,2,4,8,4,8};
181#define NUM_FORMATS 12 181#define NUM_FORMATS 12
182 182
183#define FMT_BYTE 1 183#define FMT_BYTE 1
184#define FMT_STRING 2 184#define FMT_STRING 2
185#define FMT_USHORT 3 185#define FMT_USHORT 3
186#define FMT_ULONG 4 186#define FMT_ULONG 4
187#define FMT_URATIONAL 5 187#define FMT_URATIONAL 5
188#define FMT_SBYTE 6 188#define FMT_SBYTE 6
189#define FMT_UNDEFINED 7 189#define FMT_UNDEFINED 7
190#define FMT_SSHORT 8 190#define FMT_SSHORT 8
191#define FMT_SLONG 9 191#define FMT_SLONG 9
192#define FMT_SRATIONAL 10 192#define FMT_SRATIONAL 10
193#define FMT_SINGLE 11 193#define FMT_SINGLE 11
194#define FMT_DOUBLE 12 194#define FMT_DOUBLE 12
195 195
196//-------------------------------------------------------------------------- 196//--------------------------------------------------------------------------
197// Describes tag values 197// Describes tag values
198 198
199#define TAG_EXIF_OFFSET 0x8769 199#define TAG_EXIF_OFFSET 0x8769
200#define TAG_INTEROP_OFFSET 0xa005 200#define TAG_INTEROP_OFFSET 0xa005
201 201
202#define TAG_MAKE 0x010F 202#define TAG_MAKE 0x010F
203#define TAG_MODEL 0x0110 203#define TAG_MODEL 0x0110
204#define TAG_ORIENTATION 0x0112 204#define TAG_ORIENTATION 0x0112
205 205
206#define TAG_EXPOSURETIME 0x829A 206#define TAG_EXPOSURETIME 0x829A
207#define TAG_FNUMBER 0x829D 207#define TAG_FNUMBER 0x829D
208 208
209#define TAG_SHUTTERSPEED 0x9201 209#define TAG_SHUTTERSPEED 0x9201
210#define TAG_APERTURE 0x9202 210#define TAG_APERTURE 0x9202
211#define TAG_MAXAPERTURE 0x9205 211#define TAG_MAXAPERTURE 0x9205
212#define TAG_FOCALLENGTH 0x920A 212#define TAG_FOCALLENGTH 0x920A
213 213
214#define TAG_DATETIME_ORIGINAL 0x9003 214#define TAG_DATETIME_ORIGINAL 0x9003
215#define TAG_USERCOMMENT 0x9286 215#define TAG_USERCOMMENT 0x9286
216 216
217#define TAG_SUBJECT_DISTANCE 0x9206 217#define TAG_SUBJECT_DISTANCE 0x9206
218#define TAG_FLASH 0x9209 218#define TAG_FLASH 0x9209
219 219
220#define TAG_FOCALPLANEXRES 0xa20E 220#define TAG_FOCALPLANEXRES 0xa20E
221#define TAG_FOCALPLANEUNITS 0xa210 221#define TAG_FOCALPLANEUNITS 0xa210
222#define TAG_EXIF_IMAGEWIDTH 0xA002 222#define TAG_EXIF_IMAGEWIDTH 0xA002
223#define TAG_EXIF_IMAGELENGTH 0xA003 223#define TAG_EXIF_IMAGELENGTH 0xA003
224 224
225// the following is added 05-jan-2001 vcs 225// the following is added 05-jan-2001 vcs
226#define TAG_EXPOSURE_BIAS 0x9204 226#define TAG_EXPOSURE_BIAS 0x9204
227#define TAG_WHITEBALANCE 0x9208 227#define TAG_WHITEBALANCE 0x9208
228#define TAG_METERING_MODE 0x9207 228#define TAG_METERING_MODE 0x9207
229#define TAG_EXPOSURE_PROGRAM 0x8822 229#define TAG_EXPOSURE_PROGRAM 0x8822
230#define TAG_ISO_EQUIVALENT 0x8827 230#define TAG_ISO_EQUIVALENT 0x8827
231#define TAG_COMPRESSION_LEVEL 0x9102 231#define TAG_COMPRESSION_LEVEL 0x9102
232 232
233#define TAG_THUMBNAIL_OFFSET 0x0201 233#define TAG_THUMBNAIL_OFFSET 0x0201
234#define TAG_THUMBNAIL_LENGTH 0x0202 234#define TAG_THUMBNAIL_LENGTH 0x0202
235 235
236 236
237 237
238 238
239//-------------------------------------------------------------------------- 239//--------------------------------------------------------------------------
240// Parse the marker stream until SOS or EOI is seen; 240// Parse the marker stream until SOS or EOI is seen;
241//-------------------------------------------------------------------------- 241//--------------------------------------------------------------------------
242int ExifData::ReadJpegSections (QFile & infile, ReadMode_t ReadMode) 242int ExifData::ReadJpegSections (QFile & infile, ReadMode_t ReadMode)
243{ 243{
244 int a; 244 int a;
245 245
246 a = infile.getch(); 246 a = infile.getch();
247 247
248 if (a != 0xff || infile.getch() != M_SOI) { 248 if (a != 0xff || infile.getch() != M_SOI) {
249 SectionsRead = 0; 249 SectionsRead = 0;
250 return false; 250 return false;
251 } 251 }
252 for(SectionsRead = 0; SectionsRead < MAX_SECTIONS-1; ){ 252 for(SectionsRead = 0; SectionsRead < MAX_SECTIONS-1; ){
253 int marker = 0; 253 int marker = 0;
254 int got; 254 int got;
255 unsigned int ll,lh; 255 unsigned int ll,lh;
256 unsigned int itemlen; 256 unsigned int itemlen;
257 uchar * Data; 257 uchar * Data;
258 258
259 for (a=0;a<7;a++){ 259 for (a=0;a<7;a++){
260 marker = infile.getch(); 260 marker = infile.getch();
261 if (marker != 0xff) break; 261 if (marker != 0xff) break;
262 262
263 if (a >= 6){ 263 if (a >= 6){
264 264
265 qWarning( "too many padding bytes" ); 265 qWarning( "too many padding bytes" );
266 return false; 266 return false;
267 267
268 } 268 }
269 } 269 }
270 270
271 if (marker == 0xff){ 271 if (marker == 0xff){
272 // 0xff is legal padding, but if we get that many, something's wrong. 272 // 0xff is legal padding, but if we get that many, something's wrong.
273 return false; 273 return false;
274 } 274 }
275 275
276 Sections[SectionsRead].Type = marker; 276 Sections[SectionsRead].Type = marker;
277 277
278 // Read the length of the section. 278 // Read the length of the section.
279 lh = (uchar) infile.getch(); 279 lh = (uchar) infile.getch();
280 ll = (uchar) infile.getch(); 280 ll = (uchar) infile.getch();
281 281
282 itemlen = (lh << 8) | ll; 282 itemlen = (lh << 8) | ll;
283 283
284 if (itemlen < 2) { 284 if (itemlen < 2) {
285 return false;; 285 return false;;
286 } 286 }
287 287
288 Sections[SectionsRead].Size = itemlen; 288 Sections[SectionsRead].Size = itemlen;
289 289
290 Data = (uchar *)malloc(itemlen+1); // Add 1 to allow sticking a 0 at the end. 290 Data = (uchar *)malloc(itemlen+1); // Add 1 to allow sticking a 0 at the end.
291 Sections[SectionsRead].Data = Data; 291 Sections[SectionsRead].Data = Data;
292 292
293 // Store first two pre-read bytes. 293 // Store first two pre-read bytes.
294 Data[0] = (uchar)lh; 294 Data[0] = (uchar)lh;
295 Data[1] = (uchar)ll; 295 Data[1] = (uchar)ll;
296 296
297 got = infile.readBlock((char*)Data+2, itemlen-2); // Read the whole section. 297 got = infile.readBlock((char*)Data+2, itemlen-2); // Read the whole section.
298 if (( unsigned ) got != itemlen-2){ 298 if (( unsigned ) got != itemlen-2){
299 return false; 299 return false;
300 } 300 }
301 SectionsRead++; 301 SectionsRead++;
302 302
303 switch(marker){ 303 switch(marker){
304 304
305 case M_SOS: // stop before hitting compressed data 305 case M_SOS: // stop before hitting compressed data
306 // If reading entire image is requested, read the rest of the data. 306 // If reading entire image is requested, read the rest of the data.
307 if (ReadMode & READ_IMAGE){ 307 if (ReadMode & READ_IMAGE){
308 unsigned long size; 308 unsigned long size;
309 309
310 size = QMAX( 0ul, infile.size()-infile.at() ); 310 size = QMAX( 0ul, infile.size()-infile.at() );
311 Data = (uchar *)malloc(size); 311 Data = (uchar *)malloc(size);
312 if (Data == NULL){ 312 if (Data == NULL){
313 return false; 313 return false;
314 } 314 }
315 315
316 got = infile.readBlock((char*)Data, size); 316 got = infile.readBlock((char*)Data, size);
317 if (( unsigned ) got != size){ 317 if (( unsigned ) got != size){
318 return false; 318 return false;
319 } 319 }
320 320
321 Sections[SectionsRead].Data = Data; 321 Sections[SectionsRead].Data = Data;
322 Sections[SectionsRead].Size = size; 322 Sections[SectionsRead].Size = size;
323 Sections[SectionsRead].Type = PSEUDO_IMAGE_MARKER; 323 Sections[SectionsRead].Type = PSEUDO_IMAGE_MARKER;
324 SectionsRead ++; 324 SectionsRead ++;
325 //HaveAll = 1; 325 //HaveAll = 1;
326 } 326 }
327 return true; 327 return true;
328 328
329 case M_EOI: // in case it's a tables-only JPEG stream 329 case M_EOI: // in case it's a tables-only JPEG stream
330 qWarning( "No image in jpeg!" ); 330 qWarning( "No image in jpeg!" );
331 return false; 331 return false;
332 332
333 case M_COM: // Comment section 333 case M_COM: // Comment section
334 // pieczy 2002-02-12 334 // pieczy 2002-02-12
335 // now the User comment goes to UserComment 335 // now the User comment goes to UserComment
336 // so we can store a Comment section also in READ_EXIF mode 336 // so we can store a Comment section also in READ_EXIF mode
337 process_COM(Data, itemlen); 337 process_COM(Data, itemlen);
338 break; 338 break;
339 339
340 case M_JFIF: 340 case M_JFIF:
341 // Regular jpegs always have this tag, exif images have the exif 341 // Regular jpegs always have this tag, exif images have the exif
342 // marker instead, althogh ACDsee will write images with both markers. 342 // marker instead, althogh ACDsee will write images with both markers.
343 // this program will re-create this marker on absence of exif marker. 343 // this program will re-create this marker on absence of exif marker.
344 // hence no need to keep the copy from the file. 344 // hence no need to keep the copy from the file.
345 free(Sections[--SectionsRead].Data); 345 free(Sections[--SectionsRead].Data);
346 break; 346 break;
347 347
348 case M_EXIF: 348 case M_EXIF:
349 // Seen files from some 'U-lead' software with Vivitar scanner 349 // Seen files from some 'U-lead' software with Vivitar scanner
350 // that uses marker 31 for non exif stuff. Thus make sure 350 // that uses marker 31 for non exif stuff. Thus make sure
351 // it says 'Exif' in the section before treating it as exif. 351 // it says 'Exif' in the section before treating it as exif.
352 if ((ReadMode & READ_EXIF) && memcmp(Data+2, "Exif", 4) == 0){ 352 if ((ReadMode & READ_EXIF) && memcmp(Data+2, "Exif", 4) == 0){
353 process_EXIF((uchar *)Data, itemlen); 353 process_EXIF((uchar *)Data, itemlen);
354 }else{ 354 }else{
355 // Discard this section. 355 // Discard this section.
356 free(Sections[--SectionsRead].Data); 356 free(Sections[--SectionsRead].Data);
357 } 357 }
358 break; 358 break;
359 359
360 case M_SOF0: 360 case M_SOF0:
361 case M_SOF1: 361 case M_SOF1:
362 case M_SOF2: 362 case M_SOF2:
363 case M_SOF3: 363 case M_SOF3:
364 case M_SOF5: 364 case M_SOF5:
365 case M_SOF6: 365 case M_SOF6:
366 case M_SOF7: 366 case M_SOF7:
367 case M_SOF9: 367 case M_SOF9:
368 case M_SOF10: 368 case M_SOF10:
369 case M_SOF11: 369 case M_SOF11:
370 case M_SOF13: 370 case M_SOF13:
371 case M_SOF14: 371 case M_SOF14:
372 case M_SOF15: 372 case M_SOF15:
373 process_SOFn(Data, marker); 373 process_SOFn(Data, marker);
374 default: 374 default:
375 break; 375 break;
376 break; 376 break;
377 } 377 }
378 } 378 }
379 return true; 379 return true;
380} 380}
381 381
382 382
383//-------------------------------------------------------------------------- 383//--------------------------------------------------------------------------
384// Discard read data. 384// Discard read data.
385//-------------------------------------------------------------------------- 385//--------------------------------------------------------------------------
386void ExifData::DiscardData(void) 386void ExifData::DiscardData(void)
387{ 387{
388 for (int a=0; a < SectionsRead; a++) 388 for (int a=0; a < SectionsRead; a++)
389 free(Sections[a].Data); 389 free(Sections[a].Data);
390 SectionsRead = 0; 390 SectionsRead = 0;
391} 391}
392 392
393//-------------------------------------------------------------------------- 393//--------------------------------------------------------------------------
394// Convert a 16 bit unsigned value from file's native byte order 394// Convert a 16 bit unsigned value from file's native byte order
395//-------------------------------------------------------------------------- 395//--------------------------------------------------------------------------
396int ExifData::Get16u(void * Short) 396int ExifData::Get16u(void * Short)
397{ 397{
398 if (MotorolaOrder){ 398 if (MotorolaOrder){
399 return (((uchar *)Short)[0] << 8) | ((uchar *)Short)[1]; 399 return (((uchar *)Short)[0] << 8) | ((uchar *)Short)[1];
400 }else{ 400 }else{
401 return (((uchar *)Short)[1] << 8) | ((uchar *)Short)[0]; 401 return (((uchar *)Short)[1] << 8) | ((uchar *)Short)[0];
402 } 402 }
403} 403}
404 404
405//-------------------------------------------------------------------------- 405//--------------------------------------------------------------------------
406// Convert a 32 bit signed value from file's native byte order 406// Convert a 32 bit signed value from file's native byte order
407//-------------------------------------------------------------------------- 407//--------------------------------------------------------------------------
408int ExifData::Get32s(void * Long) 408int ExifData::Get32s(void * Long)
409{ 409{
410 if (MotorolaOrder){ 410 if (MotorolaOrder){
411 return ((( char *)Long)[0] << 24) | (((uchar *)Long)[1] << 16) 411 return ((( char *)Long)[0] << 24) | (((uchar *)Long)[1] << 16)
412 | (((uchar *)Long)[2] << 8 ) | (((uchar *)Long)[3] << 0 ); 412 | (((uchar *)Long)[2] << 8 ) | (((uchar *)Long)[3] << 0 );
413 }else{ 413 }else{
414 return ((( char *)Long)[3] << 24) | (((uchar *)Long)[2] << 16) 414 return ((( char *)Long)[3] << 24) | (((uchar *)Long)[2] << 16)
415 | (((uchar *)Long)[1] << 8 ) | (((uchar *)Long)[0] << 0 ); 415 | (((uchar *)Long)[1] << 8 ) | (((uchar *)Long)[0] << 0 );
416 } 416 }
417} 417}
418 418
419//-------------------------------------------------------------------------- 419//--------------------------------------------------------------------------
420// Convert a 32 bit unsigned value from file's native byte order 420// Convert a 32 bit unsigned value from file's native byte order
421//-------------------------------------------------------------------------- 421//--------------------------------------------------------------------------
422unsigned ExifData::Get32u(void * Long) 422unsigned ExifData::Get32u(void * Long)
423{ 423{
424 return (unsigned)Get32s(Long) & 0xffffffff; 424 return (unsigned)Get32s(Long) & 0xffffffff;
425} 425}
426 426
427//-------------------------------------------------------------------------- 427//--------------------------------------------------------------------------
428// Evaluate number, be it int, rational, or float from directory. 428// Evaluate number, be it int, rational, or float from directory.
429//-------------------------------------------------------------------------- 429//--------------------------------------------------------------------------
430double ExifData::ConvertAnyFormat(void * ValuePtr, int Format) 430double ExifData::ConvertAnyFormat(void * ValuePtr, int Format)
431{ 431{
432 double Value; 432 double Value;
433 Value = 0; 433 Value = 0;
434 434
435 switch(Format){ 435 switch(Format){
436 case FMT_SBYTE: Value = *(signed char *)ValuePtr; break; 436 case FMT_SBYTE: Value = *(signed char *)ValuePtr; break;
437 case FMT_BYTE: Value = *(uchar *)ValuePtr; break; 437 case FMT_BYTE: Value = *(uchar *)ValuePtr; break;
438 438
439 case FMT_USHORT: Value = Get16u(ValuePtr); break; 439 case FMT_USHORT: Value = Get16u(ValuePtr); break;
440 440
441 case FMT_ULONG: Value = Get32u(ValuePtr); break; 441 case FMT_ULONG: Value = Get32u(ValuePtr); break;
442 442
443 case FMT_URATIONAL: 443 case FMT_URATIONAL:
444 case FMT_SRATIONAL: 444 case FMT_SRATIONAL:
445 { 445 {
446 int Num,Den; 446 int Num,Den;
447 Num = Get32s(ValuePtr); 447 Num = Get32s(ValuePtr);
448 Den = Get32s(4+(char *)ValuePtr); 448 Den = Get32s(4+(char *)ValuePtr);
449 if (Den == 0){ 449 if (Den == 0){
450 Value = 0; 450 Value = 0;
451 }else{ 451 }else{
452 Value = (double)Num/Den; 452 Value = (double)Num/Den;
453 } 453 }
454 break; 454 break;
455 } 455 }
456 456
457 case FMT_SSHORT: Value = (signed short)Get16u(ValuePtr); break; 457 case FMT_SSHORT: Value = (signed short)Get16u(ValuePtr); break;
458 case FMT_SLONG: Value = Get32s(ValuePtr); break; 458 case FMT_SLONG: Value = Get32s(ValuePtr); break;
459 459
460 // Not sure if this is correct (never seen float used in Exif format) 460 // Not sure if this is correct (never seen float used in Exif format)
461 case FMT_SINGLE: Value = (double)*(float *)ValuePtr; break; 461 case FMT_SINGLE: Value = (double)*(float *)ValuePtr; break;
462 case FMT_DOUBLE: Value = *(double *)ValuePtr; break; 462 case FMT_DOUBLE: Value = *(double *)ValuePtr; break;
463 } 463 }
464 return Value; 464 return Value;
465} 465}
466 466
467//-------------------------------------------------------------------------- 467//--------------------------------------------------------------------------
468// Process one of the nested EXIF directories. 468// Process one of the nested EXIF directories.
469//-------------------------------------------------------------------------- 469//--------------------------------------------------------------------------
470void ExifData::ProcessExifDir(unsigned char * DirStart, unsigned char * OffsetBase, unsigned ExifLength) 470void ExifData::ProcessExifDir(unsigned char * DirStart, unsigned char * OffsetBase, unsigned ExifLength)
471{ 471{
472 int de; 472 int de;
473 int a; 473 int a;
474 int NumDirEntries; 474 int NumDirEntries;
475 unsigned ThumbnailOffset = 0; 475 unsigned ThumbnailOffset = 0;
476 unsigned ThumbnailSize = 0; 476 unsigned ThumbnailSize = 0;
477 477
478 NumDirEntries = Get16u(DirStart); 478 NumDirEntries = Get16u(DirStart);
479 #define DIR_ENTRY_ADDR(Start, Entry) (Start+2+12*(Entry)) 479 #define DIR_ENTRY_ADDR(Start, Entry) (Start+2+12*(Entry))
480 480
481 { 481 {
482 unsigned char * DirEnd; 482 unsigned char * DirEnd;
483 DirEnd = DIR_ENTRY_ADDR(DirStart, NumDirEntries); 483 DirEnd = DIR_ENTRY_ADDR(DirStart, NumDirEntries);
484 if (DirEnd+4 > (OffsetBase+ExifLength)){ 484 if (DirEnd+4 > (OffsetBase+ExifLength)){
485 if (DirEnd+2 == OffsetBase+ExifLength || DirEnd == OffsetBase+ExifLength){ 485 if (DirEnd+2 == OffsetBase+ExifLength || DirEnd == OffsetBase+ExifLength){
486 // Version 1.3 of jhead would truncate a bit too much. 486 // Version 1.3 of jhead would truncate a bit too much.
487 // This also caught later on as well. 487 // This also caught later on as well.
488 }else{ 488 }else{
489 // Note: Files that had thumbnails trimmed with jhead 1.3 or earlier 489 // Note: Files that had thumbnails trimmed with jhead 1.3 or earlier
490 // might trigger this. 490 // might trigger this.
491 return; 491 return;
492 } 492 }
493 } 493 }
494 if (DirEnd < LastExifRefd) LastExifRefd = DirEnd; 494 if (DirEnd < LastExifRefd) LastExifRefd = DirEnd;
495 } 495 }
496 496
497 for (de=0;de<NumDirEntries;de++){ 497 for (de=0;de<NumDirEntries;de++){
498 int Tag, Format, Components; 498 int Tag, Format, Components;
499 unsigned char * ValuePtr; 499 unsigned char * ValuePtr;
500 int ByteCount; 500 int ByteCount;
501 char * DirEntry; 501 char * DirEntry;
502 DirEntry = (char *)DIR_ENTRY_ADDR(DirStart, de); 502 DirEntry = (char *)DIR_ENTRY_ADDR(DirStart, de);
503 503
504 Tag = Get16u(DirEntry); 504 Tag = Get16u(DirEntry);
505 Format = Get16u(DirEntry+2); 505 Format = Get16u(DirEntry+2);
506 Components = Get32u(DirEntry+4); 506 Components = Get32u(DirEntry+4);
507 507
508 if ((Format-1) >= NUM_FORMATS) { 508 if ((Format-1) >= NUM_FORMATS) {
509 // (-1) catches illegal zero case as unsigned underflows to positive large. 509 // (-1) catches illegal zero case as unsigned underflows to positive large.
510 return; 510 return;
511 } 511 }
512 512
513 ByteCount = Components * BytesPerFormat[Format]; 513 ByteCount = Components * BytesPerFormat[Format];
514 514
515 if (ByteCount > 4){ 515 if (ByteCount > 4){
516 unsigned OffsetVal; 516 unsigned OffsetVal;
517 OffsetVal = Get32u(DirEntry+8); 517 OffsetVal = Get32u(DirEntry+8);
518 // If its bigger than 4 bytes, the dir entry contains an offset. 518 // If its bigger than 4 bytes, the dir entry contains an offset.
519 if (OffsetVal+ByteCount > ExifLength){ 519 if (OffsetVal+ByteCount > ExifLength){
520 // Bogus pointer offset and / or bytecount value 520 // Bogus pointer offset and / or bytecount value
521 //printf("Offset %d bytes %d ExifLen %d\n",OffsetVal, ByteCount, ExifLength); 521 //printf("Offset %d bytes %d ExifLen %d\n",OffsetVal, ByteCount, ExifLength);
522 522
523 return; 523 return;
524 } 524 }
525 ValuePtr = OffsetBase+OffsetVal; 525 ValuePtr = OffsetBase+OffsetVal;
526 }else{ 526 }else{
527 // 4 bytes or less and value is in the dir entry itself 527 // 4 bytes or less and value is in the dir entry itself
528 ValuePtr = (unsigned char *)DirEntry+8; 528 ValuePtr = (unsigned char *)DirEntry+8;
529 } 529 }
530 530
531 if (LastExifRefd < ValuePtr+ByteCount){ 531 if (LastExifRefd < ValuePtr+ByteCount){
532 // Keep track of last byte in the exif header that was actually referenced. 532 // Keep track of last byte in the exif header that was actually referenced.
533 // That way, we know where the discardable thumbnail data begins. 533 // That way, we know where the discardable thumbnail data begins.
534 LastExifRefd = ValuePtr+ByteCount; 534 LastExifRefd = ValuePtr+ByteCount;
535 } 535 }
536 536
537 // Extract useful components of tag 537 // Extract useful components of tag
538 switch(Tag){ 538 switch(Tag){
539 539
540 case TAG_MAKE: 540 case TAG_MAKE:
541 ExifData::CameraMake = QString((char*)ValuePtr); 541 ExifData::CameraMake = QString((char*)ValuePtr);
542 break; 542 break;
543 543
544 case TAG_MODEL: 544 case TAG_MODEL:
545 ExifData::CameraModel = QString((char*)ValuePtr); 545 ExifData::CameraModel = QString((char*)ValuePtr);
546 break; 546 break;
547 547
548 case TAG_ORIENTATION: 548 case TAG_ORIENTATION:
549 Orientation = (int)ConvertAnyFormat(ValuePtr, Format); 549 Orientation = (int)ConvertAnyFormat(ValuePtr, Format);
550 break; 550 break;
551 551
552 case TAG_DATETIME_ORIGINAL: 552 case TAG_DATETIME_ORIGINAL:
553 DateTime = QString((char*)ValuePtr); 553 DateTime = QString((char*)ValuePtr);
554 break; 554 break;
555 555
556 case TAG_USERCOMMENT: 556 case TAG_USERCOMMENT:
557 // Olympus has this padded with trailing spaces. Remove these first. 557 // Olympus has this padded with trailing spaces. Remove these first.
558 for (a=ByteCount;;){ 558 for (a=ByteCount;;){
559 a--; 559 a--;
560 if ((ValuePtr)[a] == ' '){ 560 if ((ValuePtr)[a] == ' '){
561 (ValuePtr)[a] = '\0'; 561 (ValuePtr)[a] = '\0';
562 }else{ 562 }else{
563 break; 563 break;
564 } 564 }
565 if (a == 0) break; 565 if (a == 0) break;
566 } 566 }
567 567
568 // Copy the comment 568 // Copy the comment
569 if (memcmp(ValuePtr, "ASCII",5) == 0){ 569 if (memcmp(ValuePtr, "ASCII",5) == 0){
570 for (a=5;a<10;a++){ 570 for (a=5;a<10;a++){
571 int c; 571 int c;
572 c = (ValuePtr)[a]; 572 c = (ValuePtr)[a];
573 if (c != '\0' && c != ' '){ 573 if (c != '\0' && c != ' '){
574 //strncpy(ImageInfo.Comments, (const char*)(a+ValuePtr), 199); 574 //strncpy(ImageInfo.Comments, (const char*)(a+ValuePtr), 199);
575 UserComment.sprintf("%s", (const char*)(a+ValuePtr)); 575 UserComment.sprintf("%s", (const char*)(a+ValuePtr));
576 break; 576 break;
577 } 577 }
578 } 578 }
579 }else{ 579 }else{
580 //strncpy(ImageInfo.Comments, (const char*)ValuePtr, 199); 580 //strncpy(ImageInfo.Comments, (const char*)ValuePtr, 199);
581 UserComment.sprintf("%s", (const char*)ValuePtr); 581 UserComment.sprintf("%s", (const char*)ValuePtr);
582 } 582 }
583 break; 583 break;
584 584
585 case TAG_FNUMBER: 585 case TAG_FNUMBER:
586 // Simplest way of expressing aperture, so I trust it the most. 586 // Simplest way of expressing aperture, so I trust it the most.
587 // (overwrite previously computd value if there is one) 587 // (overwrite previously computd value if there is one)
588 ExifData::ApertureFNumber = (float)ConvertAnyFormat(ValuePtr, Format); 588 ExifData::ApertureFNumber = (float)ConvertAnyFormat(ValuePtr, Format);
589 break; 589 break;
590 590
591 case TAG_APERTURE: 591 case TAG_APERTURE:
592 case TAG_MAXAPERTURE: 592 case TAG_MAXAPERTURE:
593 // More relevant info always comes earlier, so only use this field if we don't 593 // More relevant info always comes earlier, so only use this field if we don't
594 // have appropriate aperture information yet. 594 // have appropriate aperture information yet.
595 if (ExifData::ApertureFNumber == 0){ 595 if (ExifData::ApertureFNumber == 0){
596 ExifData::ApertureFNumber 596 ExifData::ApertureFNumber
597 = (float)exp(ConvertAnyFormat(ValuePtr, Format)*log(2)*0.5); 597 = (float)exp(ConvertAnyFormat(ValuePtr, Format)*log(2)*0.5);
598 } 598 }
599 break; 599 break;
600 600
601 case TAG_FOCALLENGTH: 601 case TAG_FOCALLENGTH:
602 // Nice digital cameras actually save the focal length as a function 602 // Nice digital cameras actually save the focal length as a function
603 // of how farthey are zoomed in. 603 // of how farthey are zoomed in.
604 ExifData::FocalLength = (float)ConvertAnyFormat(ValuePtr, Format); 604 ExifData::FocalLength = (float)ConvertAnyFormat(ValuePtr, Format);
605 break; 605 break;
606 606
607 case TAG_SUBJECT_DISTANCE: 607 case TAG_SUBJECT_DISTANCE:
608 // Inidcates the distacne the autofocus camera is focused to. 608 // Inidcates the distacne the autofocus camera is focused to.
609 // Tends to be less accurate as distance increases. 609 // Tends to be less accurate as distance increases.
610 ExifData::Distance = (float)ConvertAnyFormat(ValuePtr, Format); 610 ExifData::Distance = (float)ConvertAnyFormat(ValuePtr, Format);
611 break; 611 break;
612 612
613 case TAG_EXPOSURETIME: 613 case TAG_EXPOSURETIME:
614 // Simplest way of expressing exposure time, so I trust it most. 614 // Simplest way of expressing exposure time, so I trust it most.
615 // (overwrite previously computd value if there is one) 615 // (overwrite previously computd value if there is one)
616 ExifData::ExposureTime = (float)ConvertAnyFormat(ValuePtr, Format); 616 ExifData::ExposureTime = (float)ConvertAnyFormat(ValuePtr, Format);
617 break; 617 break;
618 618
619 case TAG_SHUTTERSPEED: 619 case TAG_SHUTTERSPEED:
620 // More complicated way of expressing exposure time, so only use 620 // More complicated way of expressing exposure time, so only use
621 // this value if we don't already have it from somewhere else. 621 // this value if we don't already have it from somewhere else.
622 if (ExifData::ExposureTime == 0){ 622 if (ExifData::ExposureTime == 0){
623 ExifData::ExposureTime 623 ExifData::ExposureTime
624 = (float)(1/exp(ConvertAnyFormat(ValuePtr, Format)*log(2))); 624 = (float)(1/exp(ConvertAnyFormat(ValuePtr, Format)*log(2)));
625 } 625 }
626 break; 626 break;
627 627
628 case TAG_FLASH: 628 case TAG_FLASH:
629 if (ConvertAnyFormat(ValuePtr, Format)){ 629 if (ConvertAnyFormat(ValuePtr, Format)){
630 ExifData::FlashUsed = 1; 630 ExifData::FlashUsed = 1;
631 } 631 }
632 break; 632 break;
633 633
634 case TAG_EXIF_IMAGELENGTH: 634 case TAG_EXIF_IMAGELENGTH:
635 ExifImageLength = (int)ConvertAnyFormat(ValuePtr, Format); 635 ExifImageLength = (int)ConvertAnyFormat(ValuePtr, Format);
636 break; 636 break;
637 637
638 case TAG_EXIF_IMAGEWIDTH: 638 case TAG_EXIF_IMAGEWIDTH:
639 ExifImageWidth = (int)ConvertAnyFormat(ValuePtr, Format); 639 ExifImageWidth = (int)ConvertAnyFormat(ValuePtr, Format);
640 break; 640 break;
641 641
642 case TAG_FOCALPLANEXRES: 642 case TAG_FOCALPLANEXRES:
643 FocalplaneXRes = ConvertAnyFormat(ValuePtr, Format); 643 FocalplaneXRes = ConvertAnyFormat(ValuePtr, Format);
644 break; 644 break;
645 645
646 case TAG_FOCALPLANEUNITS: 646 case TAG_FOCALPLANEUNITS:
647 switch((int)ConvertAnyFormat(ValuePtr, Format)){ 647 switch((int)ConvertAnyFormat(ValuePtr, Format)){
648 case 1: FocalplaneUnits = 25.4; break; // inch 648 case 1: FocalplaneUnits = 25.4; break; // inch
649 case 2: 649 case 2:
650 // According to the information I was using, 2 means meters. 650 // According to the information I was using, 2 means meters.
651 // But looking at the Cannon powershot's files, inches is the only 651 // But looking at the Cannon powershot's files, inches is the only
652 // sensible value. 652 // sensible value.
653 FocalplaneUnits = 25.4; 653 FocalplaneUnits = 25.4;
654 break; 654 break;
655 655
656 case 3: FocalplaneUnits = 10; break; // centimeter 656 case 3: FocalplaneUnits = 10; break; // centimeter
657 case 4: FocalplaneUnits = 1; break; // milimeter 657 case 4: FocalplaneUnits = 1; break; // milimeter
658 case 5: FocalplaneUnits = .001; break; // micrometer 658 case 5: FocalplaneUnits = .001; break; // micrometer
659 } 659 }
660 break; 660 break;
661 661
662 // Remaining cases contributed by: Volker C. Schoech (schoech@gmx.de) 662 // Remaining cases contributed by: Volker C. Schoech (schoech@gmx.de)
663 663
664 case TAG_EXPOSURE_BIAS: 664 case TAG_EXPOSURE_BIAS:
665 ExifData::ExposureBias = (float)ConvertAnyFormat(ValuePtr, Format); 665 ExifData::ExposureBias = (float)ConvertAnyFormat(ValuePtr, Format);
666 break; 666 break;
667 667
668 case TAG_WHITEBALANCE: 668 case TAG_WHITEBALANCE:
669 ExifData::Whitebalance = (int)ConvertAnyFormat(ValuePtr, Format); 669 ExifData::Whitebalance = (int)ConvertAnyFormat(ValuePtr, Format);
670 break; 670 break;
671 671
672 case TAG_METERING_MODE: 672 case TAG_METERING_MODE:
673 ExifData::MeteringMode = (int)ConvertAnyFormat(ValuePtr, Format); 673 ExifData::MeteringMode = (int)ConvertAnyFormat(ValuePtr, Format);
674 break; 674 break;
675 675
676 case TAG_EXPOSURE_PROGRAM: 676 case TAG_EXPOSURE_PROGRAM:
677 ExifData::ExposureProgram = (int)ConvertAnyFormat(ValuePtr, Format); 677 ExifData::ExposureProgram = (int)ConvertAnyFormat(ValuePtr, Format);
678 break; 678 break;
679 679
680 case TAG_ISO_EQUIVALENT: 680 case TAG_ISO_EQUIVALENT:
681 ExifData::ISOequivalent = (int)ConvertAnyFormat(ValuePtr, Format); 681 ExifData::ISOequivalent = (int)ConvertAnyFormat(ValuePtr, Format);
682 if ( ExifData::ISOequivalent < 50 ) ExifData::ISOequivalent *= 200; 682 if ( ExifData::ISOequivalent < 50 ) ExifData::ISOequivalent *= 200;
683 break; 683 break;
684 684
685 case TAG_COMPRESSION_LEVEL: 685 case TAG_COMPRESSION_LEVEL:
686 ExifData::CompressionLevel = (int)ConvertAnyFormat(ValuePtr, Format); 686 ExifData::CompressionLevel = (int)ConvertAnyFormat(ValuePtr, Format);
687 break; 687 break;
688 688
689 case TAG_THUMBNAIL_OFFSET: 689 case TAG_THUMBNAIL_OFFSET:
690 ThumbnailOffset = (unsigned)ConvertAnyFormat(ValuePtr, Format); 690 ThumbnailOffset = (unsigned)ConvertAnyFormat(ValuePtr, Format);
691 break; 691 break;
692 692
693 case TAG_THUMBNAIL_LENGTH: 693 case TAG_THUMBNAIL_LENGTH:
694 ThumbnailSize = (unsigned)ConvertAnyFormat(ValuePtr, Format); 694 ThumbnailSize = (unsigned)ConvertAnyFormat(ValuePtr, Format);
695 break; 695 break;
696 696
697 } 697 }
698 698
699 if (Tag == TAG_EXIF_OFFSET || Tag == TAG_INTEROP_OFFSET){ 699 if (Tag == TAG_EXIF_OFFSET || Tag == TAG_INTEROP_OFFSET){
700 unsigned char * SubdirStart; 700 unsigned char * SubdirStart;
701 SubdirStart = OffsetBase + Get32u(ValuePtr); 701 SubdirStart = OffsetBase + Get32u(ValuePtr);
702 if (SubdirStart < OffsetBase || SubdirStart > OffsetBase+ExifLength){ 702 if (SubdirStart < OffsetBase || SubdirStart > OffsetBase+ExifLength){
703 return; 703 return;
704 } 704 }
705 ProcessExifDir(SubdirStart, OffsetBase, ExifLength); 705 ProcessExifDir(SubdirStart, OffsetBase, ExifLength);
706 continue; 706 continue;
707 } 707 }
708 } 708 }
709 709
710 { 710 {
711 // In addition to linking to subdirectories via exif tags, 711 // In addition to linking to subdirectories via exif tags,
712 // there's also a potential link to another directory at the end of each 712 // there's also a potential link to another directory at the end of each
713 // directory. this has got to be the result of a comitee! 713 // directory. this has got to be the result of a comitee!
714 unsigned char * SubdirStart; 714 unsigned char * SubdirStart;
715 unsigned Offset; 715 unsigned Offset;
716 716
717 if (DIR_ENTRY_ADDR(DirStart, NumDirEntries) + 4 <= OffsetBase+ExifLength){ 717 if (DIR_ENTRY_ADDR(DirStart, NumDirEntries) + 4 <= OffsetBase+ExifLength){
718 Offset = Get32u(DIR_ENTRY_ADDR(DirStart, NumDirEntries)); 718 Offset = Get32u(DIR_ENTRY_ADDR(DirStart, NumDirEntries));
719 // There is at least one jpeg from an HP camera having an Offset of almost MAXUINT. 719 // There is at least one jpeg from an HP camera having an Offset of almost MAXUINT.
720 // Adding OffsetBase to it produces an overflow, so compare with ExifLength here. 720 // Adding OffsetBase to it produces an overflow, so compare with ExifLength here.
721 // See http://bugs.kde.org/show_bug.cgi?id=54542 721 // See http://bugs.kde.org/show_bug.cgi?id=54542
722 if (Offset && Offset < ExifLength){ 722 if (Offset && Offset < ExifLength){
723 SubdirStart = OffsetBase + Offset; 723 SubdirStart = OffsetBase + Offset;
724 if (SubdirStart > OffsetBase+ExifLength){ 724 if (SubdirStart > OffsetBase+ExifLength){
725 if (SubdirStart < OffsetBase+ExifLength+20){ 725 if (SubdirStart < OffsetBase+ExifLength+20){
726 // Jhead 1.3 or earlier would crop the whole directory! 726 // Jhead 1.3 or earlier would crop the whole directory!
727 // As Jhead produces this form of format incorrectness, 727 // As Jhead produces this form of format incorrectness,
728 // I'll just let it pass silently 728 // I'll just let it pass silently
729 qWarning( "Thumbnail removed with Jhead 1.3 or earlier" ); 729 qWarning( "Thumbnail removed with Jhead 1.3 or earlier" );
730 }else{ 730 }else{
731 return; 731 return;
732 } 732 }
733 }else{ 733 }else{
734 if (SubdirStart <= OffsetBase+ExifLength){ 734 if (SubdirStart <= OffsetBase+ExifLength){
735 ProcessExifDir(SubdirStart, OffsetBase, ExifLength); 735 ProcessExifDir(SubdirStart, OffsetBase, ExifLength);
736 } 736 }
737 } 737 }
738 } 738 }
739 }else{ 739 }else{
740 // The exif header ends before the last next directory pointer. 740 // The exif header ends before the last next directory pointer.
741 } 741 }
742 } 742 }
743 743
744 if (ThumbnailSize && ThumbnailOffset){ 744 if (ThumbnailSize && ThumbnailOffset){
745 if (ThumbnailSize + ThumbnailOffset <= ExifLength){ 745 if (ThumbnailSize + ThumbnailOffset <= ExifLength){
746 // The thumbnail pointer appears to be valid. Store it. 746 // The thumbnail pointer appears to be valid. Store it.
747 Thumbnail.loadFromData(OffsetBase + ThumbnailOffset, ThumbnailSize, "JPEG"); 747 Thumbnail.loadFromData(OffsetBase + ThumbnailOffset, ThumbnailSize, "JPEG");
748 } 748 }
749 } 749 }
750} 750}
751 751
752//-------------------------------------------------------------------------- 752//--------------------------------------------------------------------------
753// Process a COM marker. We want to leave the bytes unchanged. The 753// Process a COM marker. We want to leave the bytes unchanged. The
754// progam that displays this text may decide to remove blanks, convert 754// progam that displays this text may decide to remove blanks, convert
755// newlines, or otherwise modify the text. In particular we want to be 755// newlines, or otherwise modify the text. In particular we want to be
756// safe for passing utf-8 text. 756// safe for passing utf-8 text.
757//-------------------------------------------------------------------------- 757//--------------------------------------------------------------------------
758void ExifData::process_COM (const uchar * Data, int length) 758void ExifData::process_COM (const uchar * Data, int length)
759{ 759{
760 QChar ch; 760 QChar ch;
761 int a; 761 int a;
762 762
763 for (a=2;a<length;a++){ 763 for (a=2;a<length;a++){
764 ch = Data[a]; 764 ch = Data[a];
765 if (ch == '\000') continue; // Remove nulls 765 if (ch == '\000') continue; // Remove nulls
766 Comment.append(ch); 766 Comment.append(ch);
767 } 767 }
768} 768}
769 769
770 770
771//-------------------------------------------------------------------------- 771//--------------------------------------------------------------------------
772// Process a SOFn marker. This is useful for the image dimensions 772// Process a SOFn marker. This is useful for the image dimensions
773//-------------------------------------------------------------------------- 773//--------------------------------------------------------------------------
774void ExifData::process_SOFn (const uchar * Data, int marker) 774void ExifData::process_SOFn (const uchar * Data, int marker)
775{ 775{
776 int data_precision, num_components; 776 int data_precision, num_components;
777 777
778 data_precision = Data[2]; 778 data_precision = Data[2];
779 ExifData::Height = Get16m(Data+3); 779 ExifData::Height = Get16m(Data+3);
780 ExifData::Width = Get16m(Data+5); 780 ExifData::Width = Get16m(Data+5);
781 num_components = Data[7]; 781 num_components = Data[7];
782 782
783 if (num_components == 3){ 783 if (num_components == 3){
784 ExifData::IsColor = 1; 784 ExifData::IsColor = 1;
785 }else{ 785 }else{
786 ExifData::IsColor = 0; 786 ExifData::IsColor = 0;
787 } 787 }
788 788
789 ExifData::Process = marker; 789 ExifData::Process = marker;
790 790
791} 791}
792 792
793//-------------------------------------------------------------------------- 793//--------------------------------------------------------------------------
794// Get 16 bits motorola order (always) for jpeg header stuff. 794// Get 16 bits motorola order (always) for jpeg header stuff.
795//-------------------------------------------------------------------------- 795//--------------------------------------------------------------------------
796int ExifData::Get16m(const void * Short) 796int ExifData::Get16m(const void * Short)
797{ 797{
798 return (((uchar *)Short)[0] << 8) | ((uchar *)Short)[1]; 798 return (((uchar *)Short)[0] << 8) | ((uchar *)Short)[1];
799} 799}
800 800
801 801
802//-------------------------------------------------------------------------- 802//--------------------------------------------------------------------------
803// Process a EXIF marker 803// Process a EXIF marker
804// Describes all the drivel that most digital cameras include... 804// Describes all the drivel that most digital cameras include...
805//-------------------------------------------------------------------------- 805//--------------------------------------------------------------------------
806void ExifData::process_EXIF(unsigned char * CharBuf, unsigned int length) 806void ExifData::process_EXIF(unsigned char * CharBuf, unsigned int length)
807{ 807{
808 ExifData::FlashUsed = 0; // If it s from a digicam, and it used flash, it says so. 808 ExifData::FlashUsed = 0; // If it s from a digicam, and it used flash, it says so.
809 809
810 FocalplaneXRes = 0; 810 FocalplaneXRes = 0;
811 FocalplaneUnits = 0; 811 FocalplaneUnits = 0;
812 ExifImageWidth = 0; 812 ExifImageWidth = 0;
813 ExifImageLength = 0; 813 ExifImageLength = 0;
814 814
815 { // Check the EXIF header component 815 { // Check the EXIF header component
816 static const uchar ExifHeader[] = "Exif\0\0"; 816 static const uchar ExifHeader[] = "Exif\0\0";
817 if (memcmp(CharBuf+2, ExifHeader,6)){ 817 if (memcmp(CharBuf+2, ExifHeader,6)){
818 return; 818 return;
819 } 819 }
820 } 820 }
821 821
822 if (memcmp(CharBuf+8,"II",2) == 0){ 822 if (memcmp(CharBuf+8,"II",2) == 0){
823 // printf("Exif section in Intel order\n"); 823 // printf("Exif section in Intel order\n");
824 MotorolaOrder = 0; 824 MotorolaOrder = 0;
825 }else{ 825 }else{
826 if (memcmp(CharBuf+8,"MM",2) == 0){ 826 if (memcmp(CharBuf+8,"MM",2) == 0){
827 // printf("Exif section in Motorola order\n"); 827 // printf("Exif section in Motorola order\n");
828 MotorolaOrder = 1; 828 MotorolaOrder = 1;
829 }else{ 829 }else{
830 return; 830 return;
831 } 831 }
832 } 832 }
833 833
834 // Check the next two values for correctness. 834 // Check the next two values for correctness.
835 if (Get16u(CharBuf+10) != 0x2a 835 if (Get16u(CharBuf+10) != 0x2a
836 || Get32u(CharBuf+12) != 0x08){ 836 || Get32u(CharBuf+12) != 0x08){
837 return; 837 return;
838 } 838 }
839 839
840 LastExifRefd = CharBuf; 840 LastExifRefd = CharBuf;
841 841
842 // First directory starts 16 bytes in. Offsets start at 8 bytes in. 842 // First directory starts 16 bytes in. Offsets start at 8 bytes in.
843 ProcessExifDir(CharBuf+16, CharBuf+8, length-6); 843 ProcessExifDir(CharBuf+16, CharBuf+8, length-6);
844 844
845 // This is how far the interesting (non thumbnail) part of the exif went. 845 // This is how far the interesting (non thumbnail) part of the exif went.
846 ExifSettingsLength = LastExifRefd - CharBuf; 846 ExifSettingsLength = LastExifRefd - CharBuf;
847 847
848 // Compute the CCD width, in milimeters. 848 // Compute the CCD width, in milimeters.
849 if (FocalplaneXRes != 0){ 849 if (FocalplaneXRes != 0){
850 ExifData::CCDWidth = (float)(ExifImageWidth * FocalplaneUnits / FocalplaneXRes); 850 ExifData::CCDWidth = (float)(ExifImageWidth * FocalplaneUnits / FocalplaneXRes);
851 } 851 }
852} 852}
853 853
854//-------------------------------------------------------------------------- 854//--------------------------------------------------------------------------
855// Convert exif time to Unix time structure 855// Convert exif time to Unix time structure
856//-------------------------------------------------------------------------- 856//--------------------------------------------------------------------------
857int ExifData::Exif2tm(struct tm * timeptr, char * ExifTime) 857int ExifData::Exif2tm(struct tm * timeptr, char * ExifTime)
858{ 858{
859 int a; 859 int a;
860 860
861 timeptr->tm_wday = -1; 861 timeptr->tm_wday = -1;
862 862
863 // Check for format: YYYY:MM:DD HH:MM:SS format. 863 // Check for format: YYYY:MM:DD HH:MM:SS format.
864 a = sscanf(ExifTime, "%d:%d:%d %d:%d:%d", 864 a = sscanf(ExifTime, "%d:%d:%d %d:%d:%d",
865 &timeptr->tm_year, &timeptr->tm_mon, &timeptr->tm_mday, 865 &timeptr->tm_year, &timeptr->tm_mon, &timeptr->tm_mday,
866 &timeptr->tm_hour, &timeptr->tm_min, &timeptr->tm_sec); 866 &timeptr->tm_hour, &timeptr->tm_min, &timeptr->tm_sec);
867 867
868 if (a == 6){ 868 if (a == 6){
869 timeptr->tm_isdst = -1; 869 timeptr->tm_isdst = -1;
870 timeptr->tm_mon -= 1; // Adjust for unix zero-based months 870 timeptr->tm_mon -= 1; // Adjust for unix zero-based months
871 timeptr->tm_year -= 1900; // Adjust for year starting at 1900 871 timeptr->tm_year -= 1900; // Adjust for year starting at 1900
872 return true; // worked. 872 return true; // worked.
873 } 873 }
874 874
875 return false; // Wasn't in Exif date format. 875 return false; // Wasn't in Exif date format.
876} 876}
877 877
878//-------------------------------------------------------------------------- 878//--------------------------------------------------------------------------
879// Contructor for initialising 879// Contructor for initialising
880//-------------------------------------------------------------------------- 880//--------------------------------------------------------------------------
881ExifData::ExifData() 881ExifData::ExifData()
882{ 882{
883 ExifData::Whitebalance = -1; 883 ExifData::Whitebalance = -1;
884 ExifData::MeteringMode = -1; 884 ExifData::MeteringMode = -1;
885 ExifData::FlashUsed = -1; 885 ExifData::FlashUsed = -1;
886 Orientation = 0; 886 Orientation = 0;
887 Height = 0; 887 Height = 0;
888 Width = 0; 888 Width = 0;
889 IsColor = 0; 889 IsColor = 0;
890 Process = 0; 890 Process = 0;
891 FocalLength = 0; 891 FocalLength = 0;
892 ExposureTime = 0; 892 ExposureTime = 0;
893 ApertureFNumber = 0; 893 ApertureFNumber = 0;
894 Distance = 0; 894 Distance = 0;
895 CCDWidth = 0; 895 CCDWidth = 0;
896 ExposureBias = 0; 896 ExposureBias = 0;
897 ExposureProgram = 0; 897 ExposureProgram = 0;
898 ISOequivalent = 0; 898 ISOequivalent = 0;
899 CompressionLevel = 0; 899 CompressionLevel = 0;
900} 900}
901 901
902//-------------------------------------------------------------------------- 902//--------------------------------------------------------------------------
903// process a EXIF jpeg file 903// process a EXIF jpeg file
904//-------------------------------------------------------------------------- 904//--------------------------------------------------------------------------
905bool ExifData::scan(const QString & path) 905bool ExifData::scan(const QString & path)
906{ 906{
907 int ret; 907 int ret;
908 908
909 QFile f(path); 909 QFile f(path);
910 f.open(IO_ReadOnly); 910 f.open(IO_ReadOnly);
911 911
912 // Scan the JPEG headers. 912 // Scan the JPEG headers.
913 ret = ReadJpegSections(f, READ_EXIF); 913 ret = ReadJpegSections(f, READ_EXIF);
914 914
915 if (ret == false){ 915 if (ret == false){
916 qWarning( "Not JPEG file!" ); 916 qWarning( "Not JPEG file!" );
917 DiscardData(); 917 DiscardData();
918 f.close(); 918 f.close();
919 return false; 919 return false;
920 } 920 }
921 f.close(); 921 f.close();
922 DiscardData(); 922 DiscardData();
923 923
924 //now make the strings clean, 924 //now make the strings clean,
925 // for exmaple my Casio is a "QV-4000 " 925 // for exmaple my Casio is a "QV-4000 "
926 CameraMake = CameraMake.stripWhiteSpace(); 926 CameraMake = CameraMake.stripWhiteSpace();
927 CameraModel = CameraModel.stripWhiteSpace(); 927 CameraModel = CameraModel.stripWhiteSpace();
928 UserComment = UserComment.stripWhiteSpace(); 928 UserComment = UserComment.stripWhiteSpace();
929 Comment = Comment.stripWhiteSpace(); 929 Comment = Comment.stripWhiteSpace();
930 return true; 930 return true;
931} 931}
932 932
933//-------------------------------------------------------------------------- 933//--------------------------------------------------------------------------
934// Does the embedded thumbnail match the jpeg image? 934// Does the embedded thumbnail match the jpeg image?
935//-------------------------------------------------------------------------- 935//--------------------------------------------------------------------------
936#ifndef JPEG_TOL 936#ifndef JPEG_TOL
937#define JPEG_TOL 0.02 937#define JPEG_TOL 0.02
938#endif 938#endif
939bool ExifData::isThumbnailSane() { 939bool ExifData::isThumbnailSane() {
940 if (Thumbnail.isNull()) return false; 940 if (Thumbnail.isNull()) return false;
941 941
942 // check whether thumbnail dimensions match the image 942 // check whether thumbnail dimensions match the image
943 // not foolproof, but catches some altered images (jpegtran -rotate) 943 // not foolproof, but catches some altered images (jpegtran -rotate)
944 if (ExifImageLength != 0 && ExifImageLength != Height) return false; 944 if (ExifImageLength != 0 && ExifImageLength != Height) return false;
945 if (ExifImageWidth != 0 && ExifImageWidth != Width) return false; 945 if (ExifImageWidth != 0 && ExifImageWidth != Width) return false;
946 if (Thumbnail.width() == 0 || Thumbnail.height() == 0) return false; 946 if (Thumbnail.width() == 0 || Thumbnail.height() == 0) return false;
947 if (Height == 0 || Width == 0) return false; 947 if (Height == 0 || Width == 0) return false;
948 double d = (double)Height/Width*Thumbnail.width()/Thumbnail.height(); 948 double d = (double)Height/Width*Thumbnail.width()/Thumbnail.height();
949 return (1-JPEG_TOL < d) && (d < 1+JPEG_TOL); 949 return (1-JPEG_TOL < d) && (d < 1+JPEG_TOL);
950} 950}
951 951
952 952
953 953
954static QImage flip_image( const QImage& img ); 954static QImage flip_image( const QImage& img );
955static QImage rotate_90( const QImage& img ); 955static QImage rotate_90( const QImage& img );
956static QImage rotate_180( const QImage& ); 956static QImage rotate_180( const QImage& );
957static QImage rotate_270( const QImage& ); 957static QImage rotate_270( const QImage& );
958 958
959//-------------------------------------------------------------------------- 959//--------------------------------------------------------------------------
960// return a thumbnail that respects the orientation flag 960// return a thumbnail that respects the orientation flag
961// only if it seems sane 961// only if it seems sane
962//-------------------------------------------------------------------------- 962//--------------------------------------------------------------------------
963QImage ExifData::getThumbnail() { 963QImage ExifData::getThumbnail() {
964 if (!isThumbnailSane()) return NULL; 964 if (!isThumbnailSane()) return NULL;
965 if (!Orientation || Orientation == 1) return Thumbnail; 965 if (!Orientation || Orientation == 1) return Thumbnail;
966 966
967 // now fix orientation 967 // now fix orientation
968 968
969 QImage dest = Thumbnail; 969 QImage dest = Thumbnail;
970 switch (Orientation) { // notice intentional fallthroughs 970 switch (Orientation) { // notice intentional fallthroughs
971 case 2: dest = flip_image( dest ); break; 971 case 2: dest = flip_image( dest ); break;
972 case 4: dest = flip_image( dest ); 972 case 4: dest = flip_image( dest );
973 case 3: dest =rotate_180( dest ); break; 973 case 3: dest =rotate_180( dest ); break;
974 case 5: dest = flip_image( dest ); 974 case 5: dest = flip_image( dest );
975 case 6: dest = rotate_90( dest ); break; 975 case 6: dest = rotate_90( dest ); break;
976 case 7: dest = flip_image( dest ); 976 case 7: dest = flip_image( dest );
977 case 8: dest = rotate_270( dest ); break; 977 case 8: dest = rotate_270( dest ); break;
978 default: break; // should never happen 978 default: break; // should never happen
979 } 979 }
980 return dest; 980 return dest;
981} 981}
982 982
983 983
984/* 984/*
985 * 985 *
986 */ 986 */
987static QImage flip_image( const QImage& img ) { 987static QImage flip_image( const QImage& img ) {
988 return img.mirror( TRUE, FALSE ); 988 return img.mirror( TRUE, FALSE );
989} 989}
990 990
991 991
992static QImage dest; 992static QImage dest;
993static int x, y; 993static int x, y;
994static unsigned int *srcData, *destData; // we're not threaded anyway 994static unsigned int *srcData, *destData; // we're not threaded anyway
995static unsigned char *srcData8, *destData8; // 8 bit is char 995static unsigned char *srcData8, *destData8; // 8 bit is char
996static unsigned int *srcTable, *destTable; // destination table 996static unsigned int *srcTable, *destTable; // destination table
997 997
998 998
999static QImage rotate_90_8( const QImage &img ) { 999static QImage rotate_90_8( const QImage &img ) {
1000 dest.create(img.height(), img.width(), img.depth()); 1000 dest.create(img.height(), img.width(), img.depth());
1001 dest.setNumColors(img.numColors()); 1001 dest.setNumColors(img.numColors());
1002 srcTable = (unsigned int *)img.colorTable(); 1002 srcTable = (unsigned int *)img.colorTable();
1003 destTable = (unsigned int *)dest.colorTable(); 1003 destTable = (unsigned int *)dest.colorTable();
1004 for ( x=0; x < img.numColors(); ++x ) 1004 for ( x=0; x < img.numColors(); ++x )
1005 destTable[x] = srcTable[x]; 1005 destTable[x] = srcTable[x];
1006 for ( y=0; y < img.height(); ++y ){ 1006 for ( y=0; y < img.height(); ++y ){
1007 srcData8 = (unsigned char *)img.scanLine(y); 1007 srcData8 = (unsigned char *)img.scanLine(y);
1008 for ( x=0; x < img.width(); ++x ){ 1008 for ( x=0; x < img.width(); ++x ){
1009 destData8 = (unsigned char *)dest.scanLine(x); 1009 destData8 = (unsigned char *)dest.scanLine(x);
1010 destData8[img.height()-y-1] = srcData8[x]; 1010 destData8[img.height()-y-1] = srcData8[x];
1011 } 1011 }
1012 } 1012 }
1013 return dest; 1013 return dest;
1014} 1014}
1015 1015
1016static QImage rotate_90_all( const QImage& img ) { 1016static QImage rotate_90_all( const QImage& img ) {
1017 dest.create(img.height(), img.width(), img.depth()); 1017 dest.create(img.height(), img.width(), img.depth());
1018 for ( y=0; y < img.height(); ++y ) { 1018 for ( y=0; y < img.height(); ++y ) {
1019 srcData = (unsigned int *)img.scanLine(y); 1019 srcData = (unsigned int *)img.scanLine(y);
1020 for ( x=0; x < img.width(); ++x ) { 1020 for ( x=0; x < img.width(); ++x ) {
1021 destData = (unsigned int *)dest.scanLine(x); 1021 destData = (unsigned int *)dest.scanLine(x);
1022 destData[img.height()-y-1] = srcData[x]; 1022 destData[img.height()-y-1] = srcData[x];
1023 } 1023 }
1024 } 1024 }
1025 1025
1026 return dest; 1026 return dest;
1027} 1027}
1028 1028
1029 1029
1030static QImage rotate_90( const QImage & img ) { 1030static QImage rotate_90( const QImage & img ) {
1031 if ( img.depth() > 8) 1031 if ( img.depth() > 8)
1032 return rotate_90_all( img ); 1032 return rotate_90_all( img );
1033 else 1033 else
1034 return rotate_90_8( img ); 1034 return rotate_90_8( img );
1035} 1035}
1036 1036
1037static QImage rotate_180_all( const QImage& img ) { 1037static QImage rotate_180_all( const QImage& img ) {
1038 dest.create(img.width(), img.height(), img.depth()); 1038 dest.create(img.width(), img.height(), img.depth());
1039 for ( y=0; y < img.height(); ++y ){ 1039 for ( y=0; y < img.height(); ++y ){
1040 srcData = (unsigned int *)img.scanLine(y); 1040 srcData = (unsigned int *)img.scanLine(y);
1041 destData = (unsigned int *)dest.scanLine(img.height()-y-1); 1041 destData = (unsigned int *)dest.scanLine(img.height()-y-1);
1042 for ( x=0; x < img.width(); ++x ) 1042 for ( x=0; x < img.width(); ++x )
1043 destData[img.width()-x-1] = srcData[x]; 1043 destData[img.width()-x-1] = srcData[x];
1044 } 1044 }
1045 return dest; 1045 return dest;
1046} 1046}
1047 1047
1048static QImage rotate_180_8( const QImage& img ) { 1048static QImage rotate_180_8( const QImage& img ) {
1049 dest.create(img.width(), img.height(), img.depth()); 1049 dest.create(img.width(), img.height(), img.depth());
1050 dest.setNumColors(img.numColors()); 1050 dest.setNumColors(img.numColors());
1051 srcTable = (unsigned int *)img.colorTable(); 1051 srcTable = (unsigned int *)img.colorTable();
1052 destTable = (unsigned int *)dest.colorTable(); 1052 destTable = (unsigned int *)dest.colorTable();
1053 for ( x=0; x < img.numColors(); ++x ) 1053 for ( x=0; x < img.numColors(); ++x )
1054 destTable[x] = srcTable[x]; 1054 destTable[x] = srcTable[x];
1055 for ( y=0; y < img.height(); ++y ){ 1055 for ( y=0; y < img.height(); ++y ){
1056 srcData8 = (unsigned char *)img.scanLine(y); 1056 srcData8 = (unsigned char *)img.scanLine(y);
1057 destData8 = (unsigned char *)dest.scanLine(img.height()-y-1); 1057 destData8 = (unsigned char *)dest.scanLine(img.height()-y-1);
1058 for ( x=0; x < img.width(); ++x ) 1058 for ( x=0; x < img.width(); ++x )
1059 destData8[img.width()-x-1] = srcData8[x]; 1059 destData8[img.width()-x-1] = srcData8[x];
1060 } 1060 }
1061 return dest; 1061 return dest;
1062} 1062}
1063 1063
1064static QImage rotate_180( const QImage& img ) { 1064static QImage rotate_180( const QImage& img ) {
1065 if ( img.depth() > 8 ) 1065 if ( img.depth() > 8 )
1066 return rotate_180_all( img ); 1066 return rotate_180_all( img );
1067 else 1067 else
1068 return rotate_180_8( img ); 1068 return rotate_180_8( img );
1069} 1069}
1070 1070
1071 1071
1072static QImage rotate_270_8( const QImage& img ) { 1072static QImage rotate_270_8( const QImage& img ) {
1073 dest.create(img.height(), img.width(), img.depth()); 1073 dest.create(img.height(), img.width(), img.depth());
1074 dest.setNumColors(img.numColors()); 1074 dest.setNumColors(img.numColors());
1075 srcTable = (unsigned int *)img.colorTable(); 1075 srcTable = (unsigned int *)img.colorTable();
1076 destTable = (unsigned int *)dest.colorTable(); 1076 destTable = (unsigned int *)dest.colorTable();
1077 for ( x=0; x < img.numColors(); ++x ) 1077 for ( x=0; x < img.numColors(); ++x )
1078 destTable[x] = srcTable[x]; 1078 destTable[x] = srcTable[x];
1079 for ( y=0; y < img.height(); ++y ){ 1079 for ( y=0; y < img.height(); ++y ){
1080 srcData8 = (unsigned char *)img.scanLine(y); 1080 srcData8 = (unsigned char *)img.scanLine(y);
1081 for ( x=0; x < img.width(); ++x ){ 1081 for ( x=0; x < img.width(); ++x ){
1082 destData8 = (unsigned char *)dest.scanLine(img.width()-x-1); 1082 destData8 = (unsigned char *)dest.scanLine(img.width()-x-1);
1083 destData8[y] = srcData8[x]; 1083 destData8[y] = srcData8[x];
1084 } 1084 }
1085 } 1085 }
1086 1086
1087 return dest; 1087 return dest;
1088} 1088}
1089 1089
1090static QImage rotate_270_all( const QImage& img ) { 1090static QImage rotate_270_all( const QImage& img ) {
1091 dest.create(img.height(), img.width(), img.depth()); 1091 dest.create(img.height(), img.width(), img.depth());
1092 for ( y=0; y < img.height(); ++y ){ 1092 for ( y=0; y < img.height(); ++y ){
1093 srcData = (unsigned int *)img.scanLine(y); 1093 srcData = (unsigned int *)img.scanLine(y);
1094 for ( x=0; x < img.width(); ++x ){ 1094 for ( x=0; x < img.width(); ++x ){
1095 destData = (unsigned int *)dest.scanLine(img.width()-x-1); 1095 destData = (unsigned int *)dest.scanLine(img.width()-x-1);
1096 destData[y] = srcData[x]; 1096 destData[y] = srcData[x];
1097 } 1097 }
1098 } 1098 }
1099 return dest; 1099 return dest;
1100} 1100}
1101 1101
1102static QImage rotate_270( const QImage& img ) { 1102static QImage rotate_270( const QImage& img ) {
1103 if ( img.depth() > 8 ) 1103 if ( img.depth() > 8 )
1104 return rotate_270_all( img ); 1104 return rotate_270_all( img );
1105 else 1105 else
1106 return rotate_270_8( img ); 1106 return rotate_270_8( img );
1107} 1107}
1108 1108
1109 1109
1110static QString color_mode_to_string( bool b ) { 1110static QString color_mode_to_string( bool b ) {
1111 return b ? QObject::tr( "Colormode: Color\n" ) : QObject::tr( "Colormode: Black and white\n" ); 1111 return b ? QObject::tr( "Colormode: Color\n" ) : QObject::tr( "Colormode: Black and white\n" );
1112} 1112}
1113 1113
1114static QString compression_to_string( int level ) { 1114static QString compression_to_string( int level ) {
1115 QString str; 1115 QString str;
1116 switch( level ) { 1116 switch( level ) {
1117 case 1: 1117 case 1:
1118 str = QObject::tr( "Basic" ); 1118 str = QObject::tr( "Basic" );
1119 break; 1119 break;
1120 case 2: 1120 case 2:
1121 str = QObject::tr( "Normal" ); 1121 str = QObject::tr( "Normal" );
1122 break; 1122 break;
1123 case 4: 1123 case 4:
1124 str = QObject::tr( "Fine" ); 1124 str = QObject::tr( "Fine" );
1125 break; 1125 break;
1126 default: 1126 default:
1127 str = QObject::tr( "Unknown" ); 1127 str = QObject::tr( "Unknown" );
1128 1128
1129 } 1129 }
1130 return QObject::tr("Quality: %1\n").arg(str); 1130 return QObject::tr("Quality: %1\n").arg(str);
1131} 1131}
1132 1132
1133 1133
1134static QDateTime parseDateTime( const QString& string ) 1134static QDateTime parseDateTime( const QString& string )
1135{ 1135{
1136 QDateTime dt; 1136 QDateTime dt;
1137 if ( string.length() != 19 ) 1137 if ( string.length() != 19 )
1138 return dt; 1138 return dt;
1139 1139
1140 QString year = string.left( 4 ); 1140 QString year = string.left( 4 );
1141 QString month = string.mid( 5, 2 ); 1141 QString month = string.mid( 5, 2 );
1142 QString day = string.mid( 8, 2 ); 1142 QString day = string.mid( 8, 2 );
1143 QString hour = string.mid( 11, 2 ); 1143 QString hour = string.mid( 11, 2 );
1144 QString minute = string.mid( 14, 2 ); 1144 QString minute = string.mid( 14, 2 );
1145 QString seconds = string.mid( 18, 2 ); 1145 QString seconds = string.mid( 18, 2 );
1146 1146
1147 bool ok; 1147 bool ok;
1148 bool allOk = true; 1148 bool allOk = true;
1149 int y = year.toInt( &ok ); 1149 int y = year.toInt( &ok );
1150 allOk &= ok; 1150 allOk &= ok;
1151 1151
1152 int mo = month.toInt( &ok ); 1152 int mo = month.toInt( &ok );
1153 allOk &= ok; 1153 allOk &= ok;
1154 1154
1155 int d = day.toInt( &ok ); 1155 int d = day.toInt( &ok );
1156 allOk &= ok; 1156 allOk &= ok;
1157 1157
1158 int h = hour.toInt( &ok ); 1158 int h = hour.toInt( &ok );
1159 allOk &= ok; 1159 allOk &= ok;
1160 1160
1161 int mi = minute.toInt( &ok ); 1161 int mi = minute.toInt( &ok );
1162 allOk &= ok; 1162 allOk &= ok;
1163 1163
1164 int s = seconds.toInt( &ok ); 1164 int s = seconds.toInt( &ok );
1165 allOk &= ok; 1165 allOk &= ok;
1166 1166
1167 if ( allOk ) { 1167 if ( allOk ) {
1168 dt.setDate( QDate( y, mo, d ) ); 1168 dt.setDate( QDate( y, mo, d ) );
1169 dt.setTime( QTime( h, mi, s ) ); 1169 dt.setTime( QTime( h, mi, s ) );
1170 } 1170 }
1171 1171
1172 return dt; 1172 return dt;
1173} 1173}
1174 1174
1175static QString white_balance_string( int i ) { 1175static QString white_balance_string( int i ) {
1176 QString balance; 1176 QString balance;
1177 switch ( i ) { 1177 switch ( i ) {
1178 case 0: 1178 case 0:
1179 balance = QObject::tr( "Unknown" ); 1179 balance = QObject::tr( "Unknown" );
1180 break; 1180 break;
1181 case 1: 1181 case 1:
1182 balance = QObject::tr( "Daylight" ); 1182 balance = QObject::tr( "Daylight" );
1183 break; 1183 break;
1184 case 2: 1184 case 2:
1185 balance = QObject::tr( "Fluorescent" ); 1185 balance = QObject::tr( "Fluorescent" );
1186 break; 1186 break;
1187 case 3: 1187 case 3:
1188 balance = QObject::tr( "Tungsten" ); 1188 balance = QObject::tr( "Tungsten" );
1189 break; 1189 break;
1190 case 17: 1190 case 17:
1191 balance = QObject::tr( "Standard light A" ); 1191 balance = QObject::tr( "Standard light A" );
1192 break; 1192 break;
1193 case 18: 1193 case 18:
1194 balance = QObject::tr( "Standard light B" ); 1194 balance = QObject::tr( "Standard light B" );
1195 break; 1195 break;
1196 case 19: 1196 case 19:
1197 balance = QObject::tr( "Standard light C" ); 1197 balance = QObject::tr( "Standard light C" );
1198 break; 1198 break;
1199 case 20: 1199 case 20:
1200 balance = QObject::tr( "D55" ); 1200 balance = QObject::tr( "D55" );
1201 break; 1201 break;
1202 case 21: 1202 case 21:
1203 balance = QObject::tr( "D65" ); 1203 balance = QObject::tr( "D65" );
1204 break; 1204 break;
1205 case 22: 1205 case 22:
1206 balance = QObject::tr( "D75" ); 1206 balance = QObject::tr( "D75" );
1207 break; 1207 break;
1208 case 255: 1208 case 255:
1209 balance = QObject::tr( "Other" ); 1209 balance = QObject::tr( "Other" );
1210 break; 1210 break;
1211 default: 1211 default:
1212 balance = QObject::tr( "Unknown" ); 1212 balance = QObject::tr( "Unknown" );
1213 } 1213 }
1214 return QObject::tr( "White Balance: %1\n" ).arg( balance ); 1214 return QObject::tr( "White Balance: %1\n" ).arg( balance );
1215 1215
1216} 1216}
1217 1217
1218 1218
1219static QString metering_mode( int i) { 1219static QString metering_mode( int i) {
1220 QString meter; 1220 QString meter;
1221 switch( i ) { 1221 switch( i ) {
1222 case 0: 1222 case 0:
1223 meter = QObject::tr( "Unknown" ); 1223 meter = QObject::tr( "Unknown" );
1224 break; 1224 break;
1225 case 1: 1225 case 1:
1226 meter = QObject::tr( "Average" ); 1226 meter = QObject::tr( "Average" );
1227 break; 1227 break;
1228 case 2: 1228 case 2:
1229 meter = QObject::tr( "Center weighted average" ); 1229 meter = QObject::tr( "Center weighted average" );
1230 break; 1230 break;
1231 case 3: 1231 case 3:
1232 meter = QObject::tr( "Spot" ); 1232 meter = QObject::tr( "Spot" );
1233 break; 1233 break;
1234 case 4: 1234 case 4:
1235 meter = QObject::tr( "MultiSpot" ); 1235 meter = QObject::tr( "MultiSpot" );
1236 break; 1236 break;
1237 case 5: 1237 case 5:
1238 meter = QObject::tr( "Pattern" ); 1238 meter = QObject::tr( "Pattern" );
1239 break; 1239 break;
1240 case 6: 1240 case 6:
1241 meter = QObject::tr( "Partial" ); 1241 meter = QObject::tr( "Partial" );
1242 break; 1242 break;
1243 case 255: 1243 case 255:
1244 meter = QObject::tr( "Other" ); 1244 meter = QObject::tr( "Other" );
1245 break; 1245 break;
1246 default: 1246 default:
1247 meter = QObject::tr( "Unknown" ); 1247 meter = QObject::tr( "Unknown" );
1248 } 1248 }
1249 1249
1250 return QObject::tr( "Metering Mode: %1\n" ).arg( meter ); 1250 return QObject::tr( "Metering Mode: %1\n" ).arg( meter );
1251} 1251}
1252 1252
1253 1253
1254static QString exposure_program( int i ) { 1254static QString exposure_program( int i ) {
1255 QString exp; 1255 QString exp;
1256 switch( i ) { 1256 switch( i ) {
1257 case 0: 1257 case 0:
1258 exp = QObject::tr( "Not defined" ); 1258 exp = QObject::tr( "Not defined" );
1259 break; 1259 break;
1260 case 1: 1260 case 1:
1261 exp = QObject::tr( "Manual" ); 1261 exp = QObject::tr( "Manual" );
1262 break; 1262 break;
1263 case 2: 1263 case 2:
1264 exp = QObject::tr( "Normal progam" ); 1264 exp = QObject::tr( "Normal progam" );
1265 break; 1265 break;
1266 case 3: 1266 case 3:
1267 exp = QObject::tr( "Aperture priority" ); 1267 exp = QObject::tr( "Aperture priority" );
1268 break; 1268 break;
1269 case 4: 1269 case 4:
1270 exp = QObject::tr( "Shutter priority" ); 1270 exp = QObject::tr( "Shutter priority" );
1271 break; 1271 break;
1272 case 5: 1272 case 5:
1273 exp = QObject::tr( "Creative progam\n(biased toward fast shutter speed" ); 1273 exp = QObject::tr( "Creative progam\n(biased toward fast shutter speed" );
1274 break; 1274 break;
1275 case 6: 1275 case 6:
1276 exp = QObject::tr( "Action progam\n(biased toward fast shutter speed)" ); 1276 exp = QObject::tr( "Action progam\n(biased toward fast shutter speed)" );
1277 break; 1277 break;
1278 case 7: 1278 case 7:
1279 exp = QObject::tr( "Portrait mode\n(for closeup photos with the background out of focus)" ); 1279 exp = QObject::tr( "Portrait mode\n(for closeup photos with the background out of focus)" );
1280 break; 1280 break;
1281 case 8: 1281 case 8:
1282 exp = QObject::tr( "Landscape mode\n(for landscape photos with the background in focus)" ); 1282 exp = QObject::tr( "Landscape mode\n(for landscape photos with the background in focus)" );
1283 break; 1283 break;
1284 default: 1284 default:
1285 exp = QObject::tr( "Unknown" ); 1285 exp = QObject::tr( "Unknown" );
1286 } 1286 }
1287 1287
1288 return QObject::tr( "Exposure Program: %1\n" ).arg( exp ); 1288 return QObject::tr( "Exposure Program: %1\n" ).arg( exp );
1289} 1289}
1290 1290
1291JpegSlave::JpegSlave() 1291JpegSlave::JpegSlave()
1292 : SlaveInterface( QStringList::split( " ", "jpeg jpg" ) ) 1292 : SlaveInterface( QStringList::split( " ", "jpeg jpg" ) )
1293{} 1293{}
1294 1294
1295JpegSlave::~JpegSlave() {} 1295JpegSlave::~JpegSlave() {}
1296 1296
1297QString JpegSlave::iconViewName( const QString& path) { 1297QString JpegSlave::iconViewName( const QString& path) {
1298 ExifData ImageInfo; 1298 ExifData ImageInfo;
1299 if ( !ImageInfo.scan( path ) ) 1299 if ( !ImageInfo.scan( path ) )
1300 return QString::null; 1300 return QString::null;
1301 1301
1302 QString tag; 1302 QString tag;
1303 tag = QObject::tr( "<qt>Comment: %1\n" ).arg( ImageInfo.getComment() ); 1303 tag = QObject::tr( "Comment: %1\n" ).arg( ImageInfo.getComment() );
1304 { 1304 {
1305// ODP fixme 1305// ODP fixme
1306 QString timestring = TimeString::dateString( parseDateTime( ImageInfo.getDateTime() ), FALSE ); 1306 QString timestring = TimeString::dateString( parseDateTime( ImageInfo.getDateTime() ), FALSE );
1307 tag += QObject::tr( "Date/Time: %1\n" ).arg( timestring ); 1307 tag += QObject::tr( "Date/Time: %1\n" ).arg( timestring );
1308 } 1308 }
1309 tag += QObject::tr( "Dimensions: %1x%2\n" ).arg(ImageInfo.getWidth()) 1309 tag += QObject::tr( "Dimensions: %1x%2\n" ).arg(ImageInfo.getWidth())
1310 .arg(ImageInfo.getHeight() ); 1310 .arg(ImageInfo.getHeight() );
1311 1311
1312 tag += color_mode_to_string( ImageInfo.getIsColor() ); 1312 tag += color_mode_to_string( ImageInfo.getIsColor() );
1313 1313
1314 tag += compression_to_string( ImageInfo.getCompressionLevel() ); 1314 tag += compression_to_string( ImageInfo.getCompressionLevel() );
1315 tag += QObject::tr( "</qt>" );
1316 1315
1317 return tag; 1316 return tag;
1318} 1317}
1319 1318
1320 1319
1321/* 1320/*
1322 * messy messy string creation 1321 * messy messy string creation
1323 */ 1322 */
1324QString JpegSlave::fullImageInfo( const QString& path) { 1323QString JpegSlave::fullImageInfo( const QString& path) {
1325 ExifData ImageInfo; 1324 ExifData ImageInfo;
1326 if ( !ImageInfo.scan( path ) ) 1325 if ( !ImageInfo.scan( path ) )
1327 return QString::null; 1326 return QString::null;
1328 1327
1329 QString tag, tmp; 1328 QString tag, tmp;
1330 tag = QObject::tr( "Comment: %1\n" ).arg( ImageInfo.getComment() ); 1329 tag = QObject::tr( "<qt>Comment: %1\n" ).arg( ImageInfo.getComment() );
1331 1330
1332 tmp = ImageInfo.getCameraMake(); 1331 tmp = ImageInfo.getCameraMake();
1333 if ( tmp.length() ) 1332 if ( tmp.length() )
1334 tag += QObject::tr( "Manufacturer: %1\n" ).arg( tmp ); 1333 tag += QObject::tr( "Manufacturer: %1\n" ).arg( tmp );
1335 tmp = ImageInfo.getCameraModel(); 1334 tmp = ImageInfo.getCameraModel();
1336 if ( tmp.length() ) 1335 if ( tmp.length() )
1337 tag += QObject::tr( "Model: %1\n" ).arg( tmp ); 1336 tag += QObject::tr( "Model: %1\n" ).arg( tmp );
1338 { 1337 {
1339// ODP fixme 1338// ODP fixme
1340 tmp = TimeString::dateString( parseDateTime( ImageInfo.getDateTime() ), FALSE ); 1339 tmp = TimeString::dateString( parseDateTime( ImageInfo.getDateTime() ), FALSE );
1341 tag += QObject::tr( "Date/Time: %1\n" ).arg( tmp ); 1340 tag += QObject::tr( "Date/Time: %1\n" ).arg( tmp );
1342 } 1341 }
1343 tag += QObject::tr( "Dimensions: %1x%2\n" ).arg(ImageInfo.getWidth()) 1342 tag += QObject::tr( "Dimensions: %1x%2\n" ).arg(ImageInfo.getWidth())
1344 .arg(ImageInfo.getHeight() ); 1343 .arg(ImageInfo.getHeight() );
1345 1344
1346 tag += color_mode_to_string( ImageInfo.getIsColor() ); 1345 tag += color_mode_to_string( ImageInfo.getIsColor() );
1347 1346
1348 tag += compression_to_string( ImageInfo.getCompressionLevel() ); 1347 tag += compression_to_string( ImageInfo.getCompressionLevel() );
1349 if ( ImageInfo.getOrientation() ) 1348 if ( ImageInfo.getOrientation() )
1350 tag += QObject::tr( "Orientation: %1\n" ).arg(ImageInfo.getOrientation() ); 1349 tag += QObject::tr( "Orientation: %1\n" ).arg(ImageInfo.getOrientation() );
1351 1350
1352 1351
1353 { 1352 {
1354 int flash_used = ImageInfo.getFlashUsed(); 1353 int flash_used = ImageInfo.getFlashUsed();
1355 if ( flash_used >= 0 ) 1354 if ( flash_used >= 0 )
1356 tag += QObject::tr( "Flash used\n" ); 1355 tag += QObject::tr( "Flash used\n" );
1357 } 1356 }
1358 1357
1359 if ( ImageInfo.getFocalLength() ) { 1358 if ( ImageInfo.getFocalLength() ) {
1360 tag += QObject::tr( "Focal length: %1\n" ).arg( QString().sprintf( "%4.1f", ImageInfo.getFocalLength() ) ); 1359 tag += QObject::tr( "Focal length: %1\n" ).arg( QString().sprintf( "%4.1f", ImageInfo.getFocalLength() ) );
1361 if ( ImageInfo.getCCDWidth() ) 1360 if ( ImageInfo.getCCDWidth() )
1362 tag += QObject::tr( "35mm equivalent: %1\n" ).arg( (int)(ImageInfo.getFocalLength()/ImageInfo.getCCDWidth()*35 + 0.5) ); 1361 tag += QObject::tr( "35mm equivalent: %1\n" ).arg( (int)(ImageInfo.getFocalLength()/ImageInfo.getCCDWidth()*35 + 0.5) );
1363 1362
1364 } 1363 }
1365 1364
1366 if ( ImageInfo.getCCDWidth() ) 1365 if ( ImageInfo.getCCDWidth() )
1367 tag += QObject::tr( "CCD width: %1" ).arg( ImageInfo.getCCDWidth() ); 1366 tag += QObject::tr( "CCD width: %1" ).arg( ImageInfo.getCCDWidth() );
1368 if ( ImageInfo.getExposureTime() ) { 1367 if ( ImageInfo.getExposureTime() ) {
1369 tmp = QString().sprintf("%4.2f", ImageInfo.getExposureTime() ); 1368 tmp = QString().sprintf("%4.2f", ImageInfo.getExposureTime() );
1370 float exposureTime = ImageInfo.getExposureTime(); 1369 float exposureTime = ImageInfo.getExposureTime();
1371 if ( exposureTime > 0 && exposureTime <= 0.5 ) 1370 if ( exposureTime > 0 && exposureTime <= 0.5 )
1372 tmp += QString().sprintf(" (1/%d)", (int)(0.5 +1/exposureTime) ); 1371 tmp += QString().sprintf(" (1/%d)", (int)(0.5 +1/exposureTime) );
1373 tag += QObject::tr( "Exposure time: %1\n" ).arg( tmp ); 1372 tag += QObject::tr( "Exposure time: %1\n" ).arg( tmp );
1374 } 1373 }
1375 1374
1376 if ( ImageInfo.getApertureFNumber() ) 1375 if ( ImageInfo.getApertureFNumber() )
1377 tag += QObject::tr( "Aperture: %1\n" ).arg( QString().sprintf("f/%3.1f", (double)ImageInfo.getApertureFNumber() ) ); 1376 tag += QObject::tr( "Aperture: %1\n" ).arg( QString().sprintf("f/%3.1f", (double)ImageInfo.getApertureFNumber() ) );
1378 1377
1379 if ( ImageInfo.getDistance() ) { 1378 if ( ImageInfo.getDistance() ) {
1380 if ( ImageInfo.getDistance() < 0 ) 1379 if ( ImageInfo.getDistance() < 0 )
1381 tag += QObject::tr( "Distance: %1\n" ).arg( QObject::tr( "Infinite" ) ); 1380 tag += QObject::tr( "Distance: %1\n" ).arg( QObject::tr( "Infinite" ) );
1382 else 1381 else
1383 tag += QObject::tr( "Distance: %1\n" ).arg( QString().sprintf( "%5.2fm", (double)ImageInfo.getDistance() ) ); 1382 tag += QObject::tr( "Distance: %1\n" ).arg( QString().sprintf( "%5.2fm", (double)ImageInfo.getDistance() ) );
1384 } 1383 }
1385 1384
1386 if ( ImageInfo.getExposureBias() ) { 1385 if ( ImageInfo.getExposureBias() ) {
1387 tag += QObject::tr( "Exposure bias: %1\n", QString().sprintf("%4.2f", (double)ImageInfo.getExposureBias() ) ); 1386 tag += QObject::tr( "Exposure bias: %1\n", QString().sprintf("%4.2f", (double)ImageInfo.getExposureBias() ) );
1388 } 1387 }
1389 1388
1390 if ( ImageInfo.getWhitebalance() != -1 ) 1389 if ( ImageInfo.getWhitebalance() != -1 )
1391 tag += white_balance_string( ImageInfo.getWhitebalance() ); 1390 tag += white_balance_string( ImageInfo.getWhitebalance() );
1392 1391
1393 1392
1394 if( ImageInfo.getMeteringMode() != -1 ) 1393 if( ImageInfo.getMeteringMode() != -1 )
1395 tag += metering_mode( ImageInfo.getMeteringMode() ); 1394 tag += metering_mode( ImageInfo.getMeteringMode() );
1396 1395
1397 if ( ImageInfo.getExposureProgram() ) 1396 if ( ImageInfo.getExposureProgram() )
1398 tag += exposure_program( ImageInfo.getExposureProgram() ); 1397 tag += exposure_program( ImageInfo.getExposureProgram() );
1399 if ( ImageInfo.getISOequivalent() ) 1398 if ( ImageInfo.getISOequivalent() )
1400 tag += QObject::tr( "ISO equivalent: %1\n" ).arg( QString().sprintf("%2d", ImageInfo.getISOequivalent() ) ); 1399 tag += QObject::tr( "ISO equivalent: %1\n" ).arg( QString().sprintf("%2d", ImageInfo.getISOequivalent() ) );
1401 1400
1402 tmp = ImageInfo.getUserComment(); 1401 tmp = ImageInfo.getUserComment();
1403 if ( tmp.length() ) 1402 if ( tmp.length() )
1404 tag += QObject::tr( "EXIF comment: %1" ).arg( tmp ); 1403 tag += QObject::tr( "EXIF comment: %1" ).arg( tmp );
1405 1404
1406 tag += QObject::tr( "</qt>" ); 1405 tag += QObject::tr( "</qt>" );
1407 1406
1408 1407
1409 1408
1410 return tag; 1409 return tag;
1411} 1410}
1412 1411
1413QPixmap JpegSlave::pixmap( const QString& path, int wid, int hei) { 1412QPixmap JpegSlave::pixmap( const QString& path, int wid, int hei) {
1414 ExifData ImageInfo; 1413 ExifData ImageInfo;
1415 if ( !ImageInfo.scan( path ) || ImageInfo.isNullThumbnail() ) { 1414 if ( !ImageInfo.scan( path ) || ImageInfo.isNullThumbnail() ) {
1416 QImage img; 1415 QImage img;
1417 QImageIO iio( path, 0l ); 1416 QImageIO iio( path, 0l );
1418 QString str = QString( "Fast Shrink( 4 ) Scale( %1, %2, ScaleFree)" ).arg( wid ).arg( hei ); 1417 QString str = QString( "Fast Shrink( 4 ) Scale( %1, %2, ScaleFree)" ).arg( wid ).arg( hei );
1419 iio.setParameters( str.latin1() );// will be strdupped anyway 1418 iio.setParameters( str.latin1() );// will be strdupped anyway
1420 img = iio.read() ? iio.image() : QImage(); 1419 img = iio.read() ? iio.image() : QImage();
1421 return ThumbNailTool::scaleImage( img, wid,hei ); 1420 return ThumbNailTool::scaleImage( img, wid,hei );
1422 }else{ 1421 }else{
1423 QImage img = ImageInfo.getThumbnail(); 1422 QImage img = ImageInfo.getThumbnail();
1424 return ThumbNailTool::scaleImage( img, wid,hei ); 1423 return ThumbNailTool::scaleImage( img, wid,hei );
1425 } 1424 }
1426} 1425}
diff --git a/noncore/graphics/opie-eye/slave/png_slave.cpp b/noncore/graphics/opie-eye/slave/png_slave.cpp
index 72b93cc..86e1cdc 100644
--- a/noncore/graphics/opie-eye/slave/png_slave.cpp
+++ b/noncore/graphics/opie-eye/slave/png_slave.cpp
@@ -1,210 +1,211 @@
1#include "png_slave.h" 1#include "png_slave.h"
2 2
3#include "thumbnailtool.h" 3#include "thumbnailtool.h"
4 4
5#include <qobject.h> 5#include <qobject.h>
6#include <qfile.h> 6#include <qfile.h>
7#include <qimage.h> 7#include <qimage.h>
8#include <qpixmap.h> 8#include <qpixmap.h>
9#include <qstring.h> 9#include <qstring.h>
10 10
11/* 11/*
12 * GPLv2 from kfile plugin 12 * GPLv2 from kfile plugin
13 */ 13 */
14PHUNK_VIEW_INTERFACE( "PNG", PNGSlave ); 14PHUNK_VIEW_INTERFACE( "PNG", PNGSlave );
15 15
16#define CHUNK_SIZE(data, index) ((data[index ]<<24) + (data[index+1]<<16) + \ 16#define CHUNK_SIZE(data, index) ((data[index ]<<24) + (data[index+1]<<16) + \
17 (data[index+2]<< 8) + data[index+3]) 17 (data[index+2]<< 8) + data[index+3])
18#define CHUNK_TYPE(data, index) &data[index+4] 18#define CHUNK_TYPE(data, index) &data[index+4]
19#define CHUNK_HEADER_SIZE 12 19#define CHUNK_HEADER_SIZE 12
20#define CHUNK_DATA(data, index, offset) data[8+index+offset] 20#define CHUNK_DATA(data, index, offset) data[8+index+offset]
21 21
22/* TRANSLATOR QObject */ 22/* TRANSLATOR QObject */
23 23
24// known translations for common png keys 24// known translations for common png keys
25static const char* knownTranslations[] 25static const char* knownTranslations[]
26#ifdef __GNUC__ 26#ifdef __GNUC__
27__attribute__((unused)) 27__attribute__((unused))
28#endif 28#endif
29 = { 29 = {
30 QT_TR_NOOP("Title"), 30 QT_TR_NOOP("Title"),
31 QT_TR_NOOP("Author"), 31 QT_TR_NOOP("Author"),
32 QT_TR_NOOP("Description"), 32 QT_TR_NOOP("Description"),
33 QT_TR_NOOP("Copyright"), 33 QT_TR_NOOP("Copyright"),
34 QT_TR_NOOP("Creation Time"), 34 QT_TR_NOOP("Creation Time"),
35 QT_TR_NOOP("Software"), 35 QT_TR_NOOP("Software"),
36 QT_TR_NOOP("Disclaimer"), 36 QT_TR_NOOP("Disclaimer"),
37 QT_TR_NOOP("Warning"), 37 QT_TR_NOOP("Warning"),
38 QT_TR_NOOP("Source"), 38 QT_TR_NOOP("Source"),
39 QT_TR_NOOP("Comment") 39 QT_TR_NOOP("Comment")
40}; 40};
41 41
42// and for the colors 42// and for the colors
43static const char* colors[] = { 43static const char* colors[] = {
44 QT_TR_NOOP("Grayscale"), 44 QT_TR_NOOP("Grayscale"),
45 QT_TR_NOOP("Unknown"), 45 QT_TR_NOOP("Unknown"),
46 QT_TR_NOOP("RGB"), 46 QT_TR_NOOP("RGB"),
47 QT_TR_NOOP("Palette"), 47 QT_TR_NOOP("Palette"),
48 QT_TR_NOOP("Grayscale/Alpha"), 48 QT_TR_NOOP("Grayscale/Alpha"),
49 QT_TR_NOOP("Unknown"), 49 QT_TR_NOOP("Unknown"),
50 QT_TR_NOOP("RGB/Alpha") 50 QT_TR_NOOP("RGB/Alpha")
51}; 51};
52 52
53 // and compressions 53 // and compressions
54static const char* compressions[] = 54static const char* compressions[] =
55{ 55{
56 QT_TR_NOOP("Deflate") 56 QT_TR_NOOP("Deflate")
57}; 57};
58 58
59 // interlaced modes 59 // interlaced modes
60static const char* interlaceModes[] = { 60static const char* interlaceModes[] = {
61 QT_TR_NOOP("None"), 61 QT_TR_NOOP("None"),
62 QT_TR_NOOP("Adam7") 62 QT_TR_NOOP("Adam7")
63}; 63};
64 64
65 65
66static void read_comment( const QString& inf, 66static void read_comment( const QString& inf,
67 bool readComments, QString& str ) { 67 bool readComments, QString& str ) {
68 QFile f(inf); 68 QFile f(inf);
69 f.open(IO_ReadOnly); 69 f.open(IO_ReadOnly);
70 70
71 if (f.size() < 26) return; 71 if (f.size() < 26) return;
72 // the technical group will be read from the first 26 bytes. If the file 72 // the technical group will be read from the first 26 bytes. If the file
73 // is smaller, we can't even read this. 73 // is smaller, we can't even read this.
74 74
75 uchar *data = new uchar[f.size()+1]; 75 uchar *data = new uchar[f.size()+1];
76 f.readBlock(reinterpret_cast<char*>(data), f.size()); 76 f.readBlock(reinterpret_cast<char*>(data), f.size());
77 data[f.size()]='\n'; 77 data[f.size()]='\n';
78 78
79 // find the start 79 // find the start
80 if (data[0] == 137 && data[1] == 80 && data[2] == 78 && data[3] == 71 && 80 if (data[0] == 137 && data[1] == 80 && data[2] == 78 && data[3] == 71 &&
81 data[4] == 13 && data[5] == 10 && data[6] == 26 && data[7] == 10 ) 81 data[4] == 13 && data[5] == 10 && data[6] == 26 && data[7] == 10 )
82 { 82 {
83 // ok 83 // ok
84 // the IHDR chunk should be the first 84 // the IHDR chunk should be the first
85 if (!strncmp((char*)&data[12], "IHDR", 4)) 85 if (!strncmp((char*)&data[12], "IHDR", 4))
86 { 86 {
87 // we found it, get the dimensions 87 // we found it, get the dimensions
88 ulong x,y; 88 ulong x,y;
89 x = (data[16]<<24) + (data[17]<<16) + (data[18]<<8) + data[19]; 89 x = (data[16]<<24) + (data[17]<<16) + (data[18]<<8) + data[19];
90 y = (data[20]<<24) + (data[21]<<16) + (data[22]<<8) + data[23]; 90 y = (data[20]<<24) + (data[21]<<16) + (data[22]<<8) + data[23];
91 91
92 uint type = data[25]; 92 uint type = data[25];
93 uint bpp = data[24]; 93 uint bpp = data[24];
94 94
95 // the bpp are only per channel, so we need to multiply the with 95 // the bpp are only per channel, so we need to multiply the with
96 // the channel count 96 // the channel count
97 switch (type) 97 switch (type)
98 { 98 {
99 case 0: break; // Grayscale 99 case 0: break; // Grayscale
100 case 2: bpp *= 3; break; // RGB 100 case 2: bpp *= 3; break; // RGB
101 case 3: break; // palette 101 case 3: break; // palette
102 case 4: bpp *= 2; break; // grayscale w. alpha 102 case 4: bpp *= 2; break; // grayscale w. alpha
103 case 6: bpp *= 4; break; // RGBA 103 case 6: bpp *= 4; break; // RGBA
104 104
105 default: // we don't get any sensible value here 105 default: // we don't get any sensible value here
106 bpp = 0; 106 bpp = 0;
107 } 107 }
108 108
109 109
110 str = QObject::tr("Dimensions: %1x%2\n" ).arg(x).arg(y); 110 str = QObject::tr("Dimensions: %1x%2\n" ).arg(x).arg(y);
111 str += QObject::tr("Depth: %1\n" ).arg(bpp); 111 str += QObject::tr("Depth: %1\n" ).arg(bpp);
112 str += QObject::tr("ColorMode: %1\n").arg( 112 str += QObject::tr("ColorMode: %1\n").arg(
113 (type < sizeof(colors)/sizeof(colors[0])) 113 (type < sizeof(colors)/sizeof(colors[0]))
114 ? QObject::tr(colors[data[25]]) : QObject::tr("Unknown") ); 114 ? QObject::tr(colors[data[25]]) : QObject::tr("Unknown") );
115 115
116 str += QObject::tr("Compression: %1\n").arg( 116 str += QObject::tr("Compression: %1\n").arg(
117 (data[26] < sizeof(compressions)/sizeof(compressions[0])) 117 (data[26] < sizeof(compressions)/sizeof(compressions[0]))
118 ? QObject::tr(compressions[data[26]]) : QObject::tr("Unknown") ); 118 ? QObject::tr(compressions[data[26]]) : QObject::tr("Unknown") );
119 119
120 str += QObject::tr("InterlaceMode: %1\n" ).arg( 120 str += QObject::tr("InterlaceMode: %1\n" ).arg(
121 (data[28] < sizeof(interlaceModes)/sizeof(interlaceModes[0])) 121 (data[28] < sizeof(interlaceModes)/sizeof(interlaceModes[0]))
122 ? QObject::tr(interlaceModes[data[28]]) : QObject::tr("Unknown")); 122 ? QObject::tr(interlaceModes[data[28]]) : QObject::tr("Unknown"));
123 } 123 }
124 124
125 if ( readComments ) { 125 if ( readComments ) {
126 uint index = 8; 126 uint index = 8;
127 index += CHUNK_SIZE(data, index) + CHUNK_HEADER_SIZE; 127 index += CHUNK_SIZE(data, index) + CHUNK_HEADER_SIZE;
128 128
129 while(index<f.size()-12) 129 while(index<f.size()-12)
130 { 130 {
131 while (index < f.size() - 12 && 131 while (index < f.size() - 12 &&
132 strncmp((char*)CHUNK_TYPE(data,index), "tEXt", 4)) 132 strncmp((char*)CHUNK_TYPE(data,index), "tEXt", 4))
133 { 133 {
134 if (!strncmp((char*)CHUNK_TYPE(data,index), "IEND", 4)) 134 if (!strncmp((char*)CHUNK_TYPE(data,index), "IEND", 4))
135 goto end; 135 goto end;
136 136
137 index += CHUNK_SIZE(data, index) + CHUNK_HEADER_SIZE; 137 index += CHUNK_SIZE(data, index) + CHUNK_HEADER_SIZE;
138 } 138 }
139 139
140 if (index < f.size() - 12) 140 if (index < f.size() - 12)
141 { 141 {
142 // we found a tEXt field 142 // we found a tEXt field
143 // get the key, it's a null terminated string at the 143 // get the key, it's a null terminated string at the
144 // chunk start 144 // chunk start
145 145
146 uchar* key = &CHUNK_DATA(data,index,0); 146 uchar* key = &CHUNK_DATA(data,index,0);
147 147
148 int keysize=0; 148 int keysize=0;
149 for (;key[keysize]!=0; keysize++) 149 for (;key[keysize]!=0; keysize++)
150 // look if we reached the end of the file 150 // look if we reached the end of the file
151 // (it might be corrupted) 151 // (it might be corrupted)
152 if (8+index+keysize>=f.size()) 152 if (8+index+keysize>=f.size())
153 goto end; 153 goto end;
154 154
155 // the text comes after the key, but isn't null terminated 155 // the text comes after the key, but isn't null terminated
156 uchar* text = &CHUNK_DATA(data,index, keysize+1); 156 uchar* text = &CHUNK_DATA(data,index, keysize+1);
157 uint textsize = CHUNK_SIZE(data, index)-keysize-1; 157 uint textsize = CHUNK_SIZE(data, index)-keysize-1;
158 158
159 // security check, also considering overflow wraparound from the addition -- 159 // security check, also considering overflow wraparound from the addition --
160 // we may endup with a /smaller/ index if we wrap all the way around 160 // we may endup with a /smaller/ index if we wrap all the way around
161 uint firstIndex = (uint)(text - data); 161 uint firstIndex = (uint)(text - data);
162 uint onePastLastIndex = firstIndex + textsize; 162 uint onePastLastIndex = firstIndex + textsize;
163 163
164 if ( onePastLastIndex > f.size() || onePastLastIndex <= firstIndex) 164 if ( onePastLastIndex > f.size() || onePastLastIndex <= firstIndex)
165 goto end; 165 goto end;
166 166
167 QByteArray arr(textsize); 167 QByteArray arr(textsize);
168 arr = QByteArray(textsize).duplicate((const char*)text, 168 arr = QByteArray(textsize).duplicate((const char*)text,
169 textsize); 169 textsize);
170 str += QObject::tr( 170 str += QObject::tr(
171 QString(reinterpret_cast<char*>(key)), 171 QString(reinterpret_cast<char*>(key)),
172 QString(arr) ); 172 QString(arr) );
173 173
174 index += CHUNK_SIZE(data, index) + CHUNK_HEADER_SIZE; 174 index += CHUNK_SIZE(data, index) + CHUNK_HEADER_SIZE;
175 } 175 }
176 } 176 }
177 } 177 }
178 } 178 }
179end: 179end:
180 delete[] data; 180 delete[] data;
181 181
182} 182}
183 183
184 184
185PNGSlave::PNGSlave() 185PNGSlave::PNGSlave()
186 : SlaveInterface("png") 186 : SlaveInterface("png")
187{ 187{
188} 188}
189PNGSlave::~PNGSlave() { 189PNGSlave::~PNGSlave() {
190} 190}
191QString PNGSlave::iconViewName( const QString& path) { 191QString PNGSlave::iconViewName( const QString& path) {
192 QString str; 192 QString str;
193 read_comment( path, false, str ); 193 read_comment( path, false, str );
194 return str; 194 return str;
195} 195}
196 196
197QString PNGSlave::fullImageInfo( const QString& path) { 197QString PNGSlave::fullImageInfo( const QString& path) {
198 QString str; 198 QString str = "<qt>";
199 read_comment( path, true, str ); 199 read_comment( path, true, str );
200 str += "</qt>";
200 return str; 201 return str;
201} 202}
202 203
203 204
204QPixmap PNGSlave::pixmap( const QString& path, int width, int height) { 205QPixmap PNGSlave::pixmap( const QString& path, int width, int height) {
205 QImage img; img.load( path ); 206 QImage img; img.load( path );
206 if ( img.isNull() ) 207 if ( img.isNull() )
207 return QPixmap(); 208 return QPixmap();
208 else 209 else
209 return ThumbNailTool::scaleImage( img, width,height ); 210 return ThumbNailTool::scaleImage( img, width,height );
210} 211}