KImgIO
xview.cpp
Go to the documentation of this file.
00001 00009 #include "xview.h" 00010 00011 #include <stdio.h> 00012 #include <string.h> 00013 #include <stdlib.h> 00014 #include <QtGui/QImage> 00015 00016 #define BUFSIZE 1024 00017 00018 static const int b_255_3[]= {0,85,170,255}, // index*255/3 00019 rg_255_7[]={0,36,72,109,145,182,218,255}; // index *255/7 00020 00021 00022 XVHandler::XVHandler() 00023 { 00024 } 00025 00026 bool XVHandler::canRead() const 00027 { 00028 if (canRead(device())) { 00029 setFormat("xv"); 00030 return true; 00031 } 00032 return false; 00033 } 00034 00035 bool XVHandler::read(QImage *retImage) 00036 { 00037 int x=-1; 00038 int y=-1; 00039 int maxval=-1; 00040 QIODevice *iodev = device(); 00041 00042 char str[ BUFSIZE ]; 00043 00044 // magic number must be "P7 332" 00045 iodev->readLine( str, BUFSIZE ); 00046 if (strncmp(str,"P7 332",6)) 00047 return false; 00048 00049 // next line #XVVERSION 00050 iodev->readLine( str, BUFSIZE ); 00051 if (strncmp(str, "#XVVERSION", 10)) 00052 return false; 00053 00054 // now it gets interesting, #BUILTIN means we are out. 00055 // if IMGINFO comes, we are happy! 00056 iodev->readLine( str, BUFSIZE ); 00057 if (strncmp(str, "#IMGINFO:", 9)) 00058 return false; 00059 00060 // after this an #END_OF_COMMENTS signals everything to be ok! 00061 iodev->readLine( str, BUFSIZE ); 00062 if (strncmp(str, "#END_OF", 7)) 00063 return false; 00064 00065 // now a last line with width, height, maxval which is 00066 // supposed to be 255 00067 iodev->readLine( str, BUFSIZE ); 00068 sscanf(str, "%d %d %d", &x, &y, &maxval); 00069 00070 if (maxval != 255) 00071 return false; 00072 int blocksize = x*y; 00073 if(x < 0 || y < 0 || blocksize < x || blocksize < y) 00074 return false; 00075 00076 // now follows a binary block of x*y bytes. 00077 char *block = (char*) malloc(blocksize); 00078 if(!block) 00079 return false; 00080 00081 if (iodev->read(block, blocksize) != blocksize ) 00082 { 00083 free(block); 00084 return false; 00085 } 00086 00087 // Create the image 00088 QImage image( x, y, QImage::Format_Indexed8 ); 00089 int numColors; 00090 numColors = qMin( maxval + 1, 0 ); 00091 numColors = qMax( 0, maxval + 1 ); 00092 image.setNumColors( numColors ); 00093 00094 // how do the color handling? they are absolute 24bpp 00095 // or at least can be calculated as such. 00096 int r,g,b; 00097 00098 for ( int j = 0; j < 256; j++ ) 00099 { 00100 r = rg_255_7[((j >> 5) & 0x07)]; 00101 g = rg_255_7[((j >> 2) & 0x07)]; 00102 b = b_255_3[((j >> 0) & 0x03)]; 00103 image.setColor( j, qRgb( r, g, b ) ); 00104 } 00105 00106 for ( int py = 0; py < y; py++ ) 00107 { 00108 uchar *data = image.scanLine( py ); 00109 memcpy( data, block + py * x, x ); 00110 } 00111 00112 *retImage = image; 00113 00114 free(block); 00115 return true; 00116 } 00117 00118 bool XVHandler::write(const QImage &image) 00119 { 00120 QIODevice& f = *( device() ); 00121 00122 // Removed "f.open(...)" and "f.close()" (tanghus) 00123 00124 int w = image.width(), h = image.height(); 00125 00126 char str[ 1024 ]; 00127 00128 // magic number must be "P7 332" 00129 f.write( "P7 332\n", 7 ); 00130 00131 // next line #XVVERSION 00132 f.write( "#XVVERSION:\n", 12 ); 00133 00134 // now it gets interesting, #BUILTIN means we are out. 00135 // if IMGINFO comes, we are happy! 00136 f.write( "#IMGINFO:\n", 10 ); 00137 00138 // after this an #END_OF_COMMENTS signals everything to be ok! 00139 f.write( "#END_OF_COMMENTS:\n", 18 ); 00140 00141 // now a last line with width, height, maxval which is supposed to be 255 00142 sprintf( str, "%i %i 255\n", w, h ); 00143 f.write( str, strlen( str ) ); 00144 00145 00146 QImage tmpImage( image ); 00147 if ( image.depth() == 1 ) 00148 tmpImage = image.convertToFormat( QImage::Format_Indexed8, Qt::AutoColor ); 00149 00150 uchar* buffer = new uchar[ w ]; 00151 00152 for ( int py = 0; py < h; py++ ) 00153 { 00154 const uchar *data = tmpImage.scanLine( py ); 00155 for ( int px = 0; px < w; px++ ) 00156 { 00157 int r, g, b; 00158 if ( tmpImage.depth() == 32 ) 00159 { 00160 const QRgb *data32 = (QRgb*) data; 00161 r = qRed( *data32 ) >> 5; 00162 g = qGreen( *data32 ) >> 5; 00163 b = qBlue( *data32 ) >> 6; 00164 data += sizeof( QRgb ); 00165 } 00166 else 00167 { 00168 QRgb color = tmpImage.color( *data ); 00169 r = qRed( color ) >> 5; 00170 g = qGreen( color ) >> 5; 00171 b = qBlue( color ) >> 6; 00172 data++; 00173 } 00174 buffer[ px ] = ( r << 5 ) | ( g << 2 ) | b; 00175 } 00176 f.write( (const char*)buffer, w ); 00177 } 00178 delete[] buffer; 00179 00180 return true; 00181 } 00182 00183 QByteArray XVHandler::name() const 00184 { 00185 return "xv"; 00186 } 00187 00188 bool XVHandler::canRead(QIODevice *device) 00189 { 00190 if (!device) { 00191 qWarning("XVHandler::canRead() called with no device"); 00192 return false; 00193 } 00194 00195 qint64 oldPos = device->pos(); 00196 00197 char head[6]; 00198 qint64 readBytes = device->read(head, sizeof(head)); 00199 if (readBytes != sizeof(head)) { 00200 if (device->isSequential()) { 00201 while (readBytes > 0) 00202 device->ungetChar(head[readBytes-- - 1]); 00203 } else { 00204 device->seek(oldPos); 00205 } 00206 return false; 00207 } 00208 00209 if (device->isSequential()) { 00210 while (readBytes > 0) 00211 device->ungetChar(head[readBytes-- - 1]); 00212 } else { 00213 device->seek(oldPos); 00214 } 00215 00216 return qstrncmp(head, "P7 332", 6) == 0; 00217 } 00218 00219 00220 class XVPlugin : public QImageIOPlugin 00221 { 00222 public: 00223 QStringList keys() const; 00224 Capabilities capabilities(QIODevice *device, const QByteArray &format) const; 00225 QImageIOHandler *create(QIODevice *device, const QByteArray &format = QByteArray()) const; 00226 }; 00227 00228 QStringList XVPlugin::keys() const 00229 { 00230 return QStringList() << "xv"; 00231 } 00232 00233 QImageIOPlugin::Capabilities XVPlugin::capabilities(QIODevice *device, const QByteArray &format) const 00234 { 00235 if (format == "xv") 00236 return Capabilities(CanRead | CanWrite); 00237 if (!format.isEmpty()) 00238 return 0; 00239 if (!device->isOpen()) 00240 return 0; 00241 00242 Capabilities cap; 00243 if (device->isReadable() && XVHandler::canRead(device)) 00244 cap |= CanRead; 00245 if (device->isWritable()) 00246 cap |= CanWrite; 00247 return cap; 00248 } 00249 00250 QImageIOHandler *XVPlugin::create(QIODevice *device, const QByteArray &format) const 00251 { 00252 QImageIOHandler *handler = new XVHandler; 00253 handler->setDevice(device); 00254 handler->setFormat(format); 00255 return handler; 00256 } 00257 00258 Q_EXPORT_STATIC_PLUGIN(XVPlugin) 00259 Q_EXPORT_PLUGIN2(xv, XVPlugin)
KDE 4.6 API Reference