author | zecke <zecke> | 2004-03-22 23:32:41 (UTC) |
---|---|---|
committer | zecke <zecke> | 2004-03-22 23:32:41 (UTC) |
commit | 428b687982966dc2efabaf6dbcc55ad0ea30aa10 (patch) (side-by-side diff) | |
tree | 86da20abd2e4b97a59dc32e17996bde5ee74cc91 /noncore/graphics/opie-eye/slave/png_slave.cpp | |
parent | 7ce623c6351646ce738a81e103632d73c5454ecc (diff) | |
download | opie-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) (show whitespace changes)
-rw-r--r-- | noncore/graphics/opie-eye/slave/png_slave.cpp | 210 |
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 @@ +#include "png_slave.h" + +#include "thumbnailtool.h" + +#include <qobject.h> +#include <qfile.h> +#include <qimage.h> +#include <qpixmap.h> +#include <qstring.h> + +/* + * GPLv2 from kfile plugin + */ +PHUNK_VIEW_INTERFACE( "PNG", PNGSlave ); + +#define CHUNK_SIZE(data, index) ((data[index ]<<24) + (data[index+1]<<16) + \ + (data[index+2]<< 8) + data[index+3]) +#define CHUNK_TYPE(data, index) &data[index+4] +#define CHUNK_HEADER_SIZE 12 +#define CHUNK_DATA(data, index, offset) data[8+index+offset] + +/* TRANSLATOR QObject */ + +// known translations for common png keys +static const char* knownTranslations[] +#ifdef __GNUC__ +__attribute__((unused)) +#endif + = { + QT_TR_NOOP("Title"), + QT_TR_NOOP("Author"), + QT_TR_NOOP("Description"), + QT_TR_NOOP("Copyright"), + QT_TR_NOOP("Creation Time"), + QT_TR_NOOP("Software"), + QT_TR_NOOP("Disclaimer"), + QT_TR_NOOP("Warning"), + QT_TR_NOOP("Source"), + QT_TR_NOOP("Comment") +}; + +// and for the colors +static const char* colors[] = { + QT_TR_NOOP("Grayscale"), + QT_TR_NOOP("Unknown"), + QT_TR_NOOP("RGB"), + QT_TR_NOOP("Palette"), + QT_TR_NOOP("Grayscale/Alpha"), + QT_TR_NOOP("Unknown"), + QT_TR_NOOP("RGB/Alpha") +}; + + // and compressions +static const char* compressions[] = +{ + QT_TR_NOOP("Deflate") +}; + + // interlaced modes +static const char* interlaceModes[] = { + QT_TR_NOOP("None"), + QT_TR_NOOP("Adam7") +}; + + +static void read_comment( const QString& inf, + bool readComments, QString& str ) { + QFile f(inf); + f.open(IO_ReadOnly); + + if (f.size() < 26) return; + // the technical group will be read from the first 26 bytes. If the file + // is smaller, we can't even read this. + + uchar *data = new uchar[f.size()+1]; + f.readBlock(reinterpret_cast<char*>(data), f.size()); + data[f.size()]='\n'; + + // find the start + if (data[0] == 137 && data[1] == 80 && data[2] == 78 && data[3] == 71 && + data[4] == 13 && data[5] == 10 && data[6] == 26 && data[7] == 10 ) + { + // ok + // the IHDR chunk should be the first + if (!strncmp((char*)&data[12], "IHDR", 4)) + { + // we found it, get the dimensions + ulong x,y; + x = (data[16]<<24) + (data[17]<<16) + (data[18]<<8) + data[19]; + y = (data[20]<<24) + (data[21]<<16) + (data[22]<<8) + data[23]; + + uint type = data[25]; + uint bpp = data[24]; + + // the bpp are only per channel, so we need to multiply the with + // the channel count + switch (type) + { + case 0: break; // Grayscale + case 2: bpp *= 3; break; // RGB + case 3: break; // palette + case 4: bpp *= 2; break; // grayscale w. alpha + case 6: bpp *= 4; break; // RGBA + + default: // we don't get any sensible value here + bpp = 0; + } + + + str = QObject::tr("Dimensions: %1x%2\n" ).arg(x).arg(y); + str += QObject::tr("Depth: %1\n" ).arg(bpp); + str += QObject::tr("ColorMode: %1\n").arg( + (type < sizeof(colors)/sizeof(colors[0])) + ? QObject::tr(colors[data[25]]) : QObject::tr("Unknown") ); + + str += QObject::tr("Compression: %1\n").arg( + (data[26] < sizeof(compressions)/sizeof(compressions[0])) + ? QObject::tr(compressions[data[26]]) : QObject::tr("Unknown") ); + + str += QObject::tr("InterlaceMode: %1\n" ).arg( + (data[28] < sizeof(interlaceModes)/sizeof(interlaceModes[0])) + ? QObject::tr(interlaceModes[data[28]]) : QObject::tr("Unknown")); + } + + if ( readComments ) { + uint index = 8; + index += CHUNK_SIZE(data, index) + CHUNK_HEADER_SIZE; + + while(index<f.size()-12) + { + while (index < f.size() - 12 && + strncmp((char*)CHUNK_TYPE(data,index), "tEXt", 4)) + { + if (!strncmp((char*)CHUNK_TYPE(data,index), "IEND", 4)) + goto end; + + index += CHUNK_SIZE(data, index) + CHUNK_HEADER_SIZE; + } + + if (index < f.size() - 12) + { + // we found a tEXt field + // get the key, it's a null terminated string at the + // chunk start + + uchar* key = &CHUNK_DATA(data,index,0); + + int keysize=0; + for (;key[keysize]!=0; keysize++) + // look if we reached the end of the file + // (it might be corrupted) + if (8+index+keysize>=f.size()) + goto end; + + // the text comes after the key, but isn't null terminated + uchar* text = &CHUNK_DATA(data,index, keysize+1); + uint textsize = CHUNK_SIZE(data, index)-keysize-1; + + // security check, also considering overflow wraparound from the addition -- + // we may endup with a /smaller/ index if we wrap all the way around + uint firstIndex = (uint)(text - data); + uint onePastLastIndex = firstIndex + textsize; + + if ( onePastLastIndex > f.size() || onePastLastIndex <= firstIndex) + goto end; + + QByteArray arr(textsize); + arr = QByteArray(textsize).duplicate((const char*)text, + textsize); + str += QObject::tr( + QString(reinterpret_cast<char*>(key)), + QString(arr) ); + + index += CHUNK_SIZE(data, index) + CHUNK_HEADER_SIZE; + } + } + } + } +end: + delete[] data; + +} + + +PNGSlave::PNGSlave() + : SlaveInterface("png") +{ +} +PNGSlave::~PNGSlave() { +} +QString PNGSlave::iconViewName( const QString& path) { + QString str; + read_comment( path, false, str ); + return str; +} + +QString PNGSlave::fullImageInfo( const QString& path) { + QString str; + read_comment( path, true, str ); + return str; +} + + +QPixmap PNGSlave::pixmap( const QString& path, int width, int height) { + QImage img; img.load( path ); + if ( img.isNull() ) + return QPixmap(); + else + return ThumbNailTool::scaleImage( img, width,height ); +} |