summaryrefslogtreecommitdiff
path: root/noncore/graphics/opie-eye/slave/png_slave.cpp
authorzecke <zecke>2004-03-22 23:32:41 (UTC)
committer zecke <zecke>2004-03-22 23:32:41 (UTC)
commit428b687982966dc2efabaf6dbcc55ad0ea30aa10 (patch) (unidiff)
tree86da20abd2e4b97a59dc32e17996bde5ee74cc91 /noncore/graphics/opie-eye/slave/png_slave.cpp
parent7ce623c6351646ce738a81e103632d73c5454ecc (diff)
downloadopie-428b687982966dc2efabaf6dbcc55ad0ea30aa10.zip
opie-428b687982966dc2efabaf6dbcc55ad0ea30aa10.tar.gz
opie-428b687982966dc2efabaf6dbcc55ad0ea30aa10.tar.bz2
Initial Check in of the Eye Of Zilla. This ImageViewer features
Image Infos, EXIF, Jpeg,Png,Gif support. It supports scaled loading of Jpegs. an smart image cache.... GUI needs some work and we need to find a bug in QCOP as well. TODO: Add Image Service for example Mailer Add ImageCanvas/Zoomer/Display
Diffstat (limited to 'noncore/graphics/opie-eye/slave/png_slave.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/graphics/opie-eye/slave/png_slave.cpp210
1 files changed, 210 insertions, 0 deletions
diff --git a/noncore/graphics/opie-eye/slave/png_slave.cpp b/noncore/graphics/opie-eye/slave/png_slave.cpp
new file mode 100644
index 0000000..72b93cc
--- a/dev/null
+++ b/noncore/graphics/opie-eye/slave/png_slave.cpp
@@ -0,0 +1,210 @@
1#include "png_slave.h"
2
3#include "thumbnailtool.h"
4
5#include <qobject.h>
6#include <qfile.h>
7#include <qimage.h>
8#include <qpixmap.h>
9#include <qstring.h>
10
11/*
12 * GPLv2 from kfile plugin
13 */
14PHUNK_VIEW_INTERFACE( "PNG", PNGSlave );
15
16#define CHUNK_SIZE(data, index) ((data[index ]<<24) + (data[index+1]<<16) + \
17 (data[index+2]<< 8) + data[index+3])
18#define CHUNK_TYPE(data, index) &data[index+4]
19#define CHUNK_HEADER_SIZE 12
20#define CHUNK_DATA(data, index, offset) data[8+index+offset]
21
22/* TRANSLATOR QObject */
23
24// known translations for common png keys
25static const char* knownTranslations[]
26#ifdef __GNUC__
27__attribute__((unused))
28#endif
29 = {
30 QT_TR_NOOP("Title"),
31 QT_TR_NOOP("Author"),
32 QT_TR_NOOP("Description"),
33 QT_TR_NOOP("Copyright"),
34 QT_TR_NOOP("Creation Time"),
35 QT_TR_NOOP("Software"),
36 QT_TR_NOOP("Disclaimer"),
37 QT_TR_NOOP("Warning"),
38 QT_TR_NOOP("Source"),
39 QT_TR_NOOP("Comment")
40};
41
42// and for the colors
43static const char* colors[] = {
44 QT_TR_NOOP("Grayscale"),
45 QT_TR_NOOP("Unknown"),
46 QT_TR_NOOP("RGB"),
47 QT_TR_NOOP("Palette"),
48 QT_TR_NOOP("Grayscale/Alpha"),
49 QT_TR_NOOP("Unknown"),
50 QT_TR_NOOP("RGB/Alpha")
51};
52
53 // and compressions
54static const char* compressions[] =
55{
56 QT_TR_NOOP("Deflate")
57};
58
59 // interlaced modes
60static const char* interlaceModes[] = {
61 QT_TR_NOOP("None"),
62 QT_TR_NOOP("Adam7")
63};
64
65
66static void read_comment( const QString& inf,
67 bool readComments, QString& str ) {
68 QFile f(inf);
69 f.open(IO_ReadOnly);
70
71 if (f.size() < 26) return;
72 // the technical group will be read from the first 26 bytes. If the file
73 // is smaller, we can't even read this.
74
75 uchar *data = new uchar[f.size()+1];
76 f.readBlock(reinterpret_cast<char*>(data), f.size());
77 data[f.size()]='\n';
78
79 // find the start
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 )
82 {
83 // ok
84 // the IHDR chunk should be the first
85 if (!strncmp((char*)&data[12], "IHDR", 4))
86 {
87 // we found it, get the dimensions
88 ulong x,y;
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];
91
92 uint type = data[25];
93 uint bpp = data[24];
94
95 // the bpp are only per channel, so we need to multiply the with
96 // the channel count
97 switch (type)
98 {
99 case 0: break; // Grayscale
100 case 2: bpp *= 3; break; // RGB
101 case 3: break; // palette
102 case 4: bpp *= 2; break; // grayscale w. alpha
103 case 6: bpp *= 4; break; // RGBA
104
105 default: // we don't get any sensible value here
106 bpp = 0;
107 }
108
109
110 str = QObject::tr("Dimensions: %1x%2\n" ).arg(x).arg(y);
111 str += QObject::tr("Depth: %1\n" ).arg(bpp);
112 str += QObject::tr("ColorMode: %1\n").arg(
113 (type < sizeof(colors)/sizeof(colors[0]))
114 ? QObject::tr(colors[data[25]]) : QObject::tr("Unknown") );
115
116 str += QObject::tr("Compression: %1\n").arg(
117 (data[26] < sizeof(compressions)/sizeof(compressions[0]))
118 ? QObject::tr(compressions[data[26]]) : QObject::tr("Unknown") );
119
120 str += QObject::tr("InterlaceMode: %1\n" ).arg(
121 (data[28] < sizeof(interlaceModes)/sizeof(interlaceModes[0]))
122 ? QObject::tr(interlaceModes[data[28]]) : QObject::tr("Unknown"));
123 }
124
125 if ( readComments ) {
126 uint index = 8;
127 index += CHUNK_SIZE(data, index) + CHUNK_HEADER_SIZE;
128
129 while(index<f.size()-12)
130 {
131 while (index < f.size() - 12 &&
132 strncmp((char*)CHUNK_TYPE(data,index), "tEXt", 4))
133 {
134 if (!strncmp((char*)CHUNK_TYPE(data,index), "IEND", 4))
135 goto end;
136
137 index += CHUNK_SIZE(data, index) + CHUNK_HEADER_SIZE;
138 }
139
140 if (index < f.size() - 12)
141 {
142 // we found a tEXt field
143 // get the key, it's a null terminated string at the
144 // chunk start
145
146 uchar* key = &CHUNK_DATA(data,index,0);
147
148 int keysize=0;
149 for (;key[keysize]!=0; keysize++)
150 // look if we reached the end of the file
151 // (it might be corrupted)
152 if (8+index+keysize>=f.size())
153 goto end;
154
155 // the text comes after the key, but isn't null terminated
156 uchar* text = &CHUNK_DATA(data,index, keysize+1);
157 uint textsize = CHUNK_SIZE(data, index)-keysize-1;
158
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
161 uint firstIndex = (uint)(text - data);
162 uint onePastLastIndex = firstIndex + textsize;
163
164 if ( onePastLastIndex > f.size() || onePastLastIndex <= firstIndex)
165 goto end;
166
167 QByteArray arr(textsize);
168 arr = QByteArray(textsize).duplicate((const char*)text,
169 textsize);
170 str += QObject::tr(
171 QString(reinterpret_cast<char*>(key)),
172 QString(arr) );
173
174 index += CHUNK_SIZE(data, index) + CHUNK_HEADER_SIZE;
175 }
176 }
177 }
178 }
179end:
180 delete[] data;
181
182}
183
184
185PNGSlave::PNGSlave()
186 : SlaveInterface("png")
187{
188}
189PNGSlave::~PNGSlave() {
190}
191QString PNGSlave::iconViewName( const QString& path) {
192 QString str;
193 read_comment( path, false, str );
194 return str;
195}
196
197QString PNGSlave::fullImageInfo( const QString& path) {
198 QString str;
199 read_comment( path, true, str );
200 return str;
201}
202
203
204QPixmap PNGSlave::pixmap( const QString& path, int width, int height) {
205 QImage img; img.load( path );
206 if ( img.isNull() )
207 return QPixmap();
208 else
209 return ThumbNailTool::scaleImage( img, width,height );
210}