00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <qpixmap.h>
00025 #include <qpainter.h>
00026 #include <qimage.h>
00027 #include <qbitmap.h>
00028 #include <qcolor.h>
00029
00030 #include <stdlib.h>
00031 #include "kpixmap.h"
00032
00033
00034
00035 static bool kdither_32_to_8( const QImage *src, QImage *dst )
00036 {
00037
00038 uchar *b;
00039 int y;
00040
00041 if ( !dst->create(src->width(), src->height(), 8, 256) ) {
00042 qWarning("KPixmap: destination image not valid\n");
00043 return false;
00044 }
00045
00046 dst->setNumColors( 256 );
00047
00048 #define MAX_R 2
00049 #define MAX_G 2
00050 #define MAX_B 2
00051 #define INDEXOF(r,g,b) (((r)*(MAX_G+1)+(g))*(MAX_B+1)+(b))
00052
00053 int rc, gc, bc;
00054
00055 for ( rc=0; rc<=MAX_R; rc++ )
00056 for ( gc=0; gc<=MAX_G; gc++ )
00057 for ( bc=0; bc<=MAX_B; bc++ ) {
00058 dst->setColor( INDEXOF(rc,gc,bc),
00059 qRgb( rc*255/MAX_R, gc*255/MAX_G, bc*255/MAX_B ) );
00060 }
00061
00062 int sw = src->width();
00063 int* line1[3];
00064 int* line2[3];
00065 int* pv[3];
00066
00067 line1[0] = new int[src->width()];
00068 line2[0] = new int[src->width()];
00069 line1[1] = new int[src->width()];
00070 line2[1] = new int[src->width()];
00071 line1[2] = new int[src->width()];
00072 line2[2] = new int[src->width()];
00073 pv[0] = new int[sw];
00074 pv[1] = new int[sw];
00075 pv[2] = new int[sw];
00076
00077 for ( y=0; y < src->height(); y++ ) {
00078
00079 b = dst->scanLine(y);
00080 int endian = (QImage::systemBitOrder() == QImage::BigEndian);
00081 int x;
00082 uchar* q = src->scanLine(y);
00083 uchar* q2 = src->scanLine(y+1 < src->height() ? y + 1 : 0);
00084
00085 for (int chan = 0; chan < 3; chan++) {
00086 b = dst->scanLine(y);
00087 int *l1 = (y&1) ? line2[chan] : line1[chan];
00088 int *l2 = (y&1) ? line1[chan] : line2[chan];
00089 if ( y == 0 ) {
00090 for (int i=0; i<sw; i++)
00091 l1[i] = q[i*4+chan+endian];
00092 }
00093 if ( y+1 < src->height() ) {
00094 for (int i=0; i<sw; i++)
00095 l2[i] = q2[i*4+chan+endian];
00096 }
00097
00098
00099 if ( y&1 ) {
00100 for (x=0; x<sw; x++) {
00101 int pix = QMAX(QMIN(2, (l1[x] * 2 + 128)/ 255), 0);
00102 int err = l1[x] - pix * 255 / 2;
00103 pv[chan][x] = pix;
00104
00105
00106 if ( x+1<sw ) {
00107 l1[x+1] += (err*7)>>4;
00108 l2[x+1] += err>>4;
00109 }
00110 l2[x]+=(err*5)>>4;
00111 if (x>1)
00112 l2[x-1]+=(err*3)>>4;
00113 }
00114 } else {
00115 for (x=sw; x-->0; ) {
00116 int pix = QMAX(QMIN(2, (l1[x] * 2 + 128)/ 255), 0);
00117 int err = l1[x] - pix * 255 / 2;
00118 pv[chan][x] = pix;
00119
00120
00121 if ( x > 0 ) {
00122 l1[x-1] += (err*7)>>4;
00123 l2[x-1] += err>>4;
00124 }
00125 l2[x]+=(err*5)>>4;
00126 if (x+1 < sw)
00127 l2[x+1]+=(err*3)>>4;
00128 }
00129 }
00130 }
00131
00132 if (!endian) {
00133 for (x=0; x<sw; x++)
00134 *b++ = INDEXOF(pv[2][x],pv[1][x],pv[0][x]);
00135 } else {
00136 for (x=0; x<sw; x++)
00137 *b++ = INDEXOF(pv[0][x],pv[1][x],pv[2][x]);
00138 }
00139
00140 }
00141
00142 delete [] line1[0];
00143 delete [] line2[0];
00144 delete [] line1[1];
00145 delete [] line2[1];
00146 delete [] line1[2];
00147 delete [] line2[2];
00148 delete [] pv[0];
00149 delete [] pv[1];
00150 delete [] pv[2];
00151
00152 #undef MAX_R
00153 #undef MAX_G
00154 #undef MAX_B
00155 #undef INDEXOF
00156
00157 return true;
00158 }
00159
00160 KPixmap::~KPixmap()
00161 {
00162 }
00163
00164 bool KPixmap::load( const QString& fileName, const char *format,
00165 int conversion_flags )
00166 {
00167 QImageIO io( fileName, format );
00168
00169 bool result = io.read();
00170
00171 if ( result ) {
00172 detach();
00173 result = convertFromImage( io.image(), conversion_flags );
00174 }
00175 return result;
00176 }
00177
00178 bool KPixmap::load( const QString& fileName, const char *format,
00179 ColorMode mode )
00180 {
00181 int conversion_flags = 0;
00182 switch (mode) {
00183 case Color:
00184 conversion_flags |= ColorOnly;
00185 break;
00186 case Mono:
00187 conversion_flags |= MonoOnly;
00188 break;
00189 case LowColor:
00190 conversion_flags |= LowOnly;
00191 break;
00192 case WebColor:
00193 conversion_flags |= WebOnly;
00194 break;
00195 default:
00196 break;
00197 }
00198 return load( fileName, format, conversion_flags );
00199 }
00200
00201 bool KPixmap::convertFromImage( const QImage &img, ColorMode mode )
00202 {
00203 int conversion_flags = 0;
00204 switch (mode) {
00205 case Color:
00206 conversion_flags |= ColorOnly;
00207 break;
00208 case Mono:
00209 conversion_flags |= MonoOnly;
00210 break;
00211 case LowColor:
00212 conversion_flags |= LowOnly;
00213 break;
00214 case WebColor:
00215 conversion_flags |= WebOnly;
00216 break;
00217 default:
00218 break;
00219 }
00220 return convertFromImage( img, conversion_flags );
00221 }
00222
00223 bool KPixmap::convertFromImage( const QImage &img, int conversion_flags )
00224 {
00225 if ( img.isNull() ) {
00226 #if defined(CHECK_NULL)
00227 qWarning( "KPixmap::convertFromImage: Cannot convert a null image" );
00228 #endif
00229 return false;
00230 }
00231 detach();
00232
00233 int dd = defaultDepth();
00234
00235
00236 if ( ( conversion_flags & KColorMode_Mask ) != LowOnly &&
00237 ( conversion_flags & KColorMode_Mask ) != WebOnly ) {
00238 return QPixmap::convertFromImage ( img, conversion_flags );
00239 }
00240
00241
00242
00243 if ( dd > 8 ) {
00244 if ( ( conversion_flags & KColorMode_Mask ) == LowOnly ||
00245 ( conversion_flags & KColorMode_Mask ) == WebOnly )
00246 conversion_flags = (conversion_flags & ~KColorMode_Mask) | Auto;
00247 return QPixmap::convertFromImage ( img, conversion_flags );
00248 }
00249
00250 if ( ( conversion_flags & KColorMode_Mask ) == LowOnly ) {
00251
00252
00253
00254
00255
00256
00257 if( img.numColors() > 0 && img.numColors() <=40 ) {
00258 if ( checkColorTable( img ) )
00259 return QPixmap::convertFromImage( img, QPixmap::Auto );
00260 }
00261
00262 QBitmap mask;
00263 bool isMask = false;
00264
00265 QImage image = img.convertDepth(32);
00266 QImage tImage( image.width(), image.height(), 8, 256 );
00267
00268 if( img.hasAlphaBuffer() ) {
00269 image.setAlphaBuffer( true );
00270 tImage.setAlphaBuffer( true );
00271 isMask = mask.convertFromImage( img.createAlphaMask() );
00272 }
00273
00274 kdither_32_to_8( &image, &tImage );
00275
00276 if( QPixmap::convertFromImage( tImage ) ) {
00277 if ( isMask ) QPixmap::setMask( mask );
00278 return true;
00279 } else
00280 return false;
00281 } else {
00282 QImage image = img.convertDepth( 32 );
00283 image.setAlphaBuffer( img.hasAlphaBuffer() );
00284 conversion_flags = (conversion_flags & ~ColorMode_Mask) | Auto;
00285 return QPixmap::convertFromImage ( image, conversion_flags );
00286 }
00287 }
00288
00289 static QColor* kpixmap_iconPalette = 0;
00290
00291 bool KPixmap::checkColorTable( const QImage &image )
00292 {
00293 int i = 0;
00294
00295 if (kpixmap_iconPalette == 0) {
00296 kpixmap_iconPalette = new QColor[40];
00297
00298
00299 kpixmap_iconPalette[i++] = red;
00300 kpixmap_iconPalette[i++] = green;
00301 kpixmap_iconPalette[i++] = blue;
00302 kpixmap_iconPalette[i++] = cyan;
00303 kpixmap_iconPalette[i++] = magenta;
00304 kpixmap_iconPalette[i++] = yellow;
00305 kpixmap_iconPalette[i++] = darkRed;
00306 kpixmap_iconPalette[i++] = darkGreen;
00307 kpixmap_iconPalette[i++] = darkBlue;
00308 kpixmap_iconPalette[i++] = darkCyan;
00309 kpixmap_iconPalette[i++] = darkMagenta;
00310 kpixmap_iconPalette[i++] = darkYellow;
00311 kpixmap_iconPalette[i++] = white;
00312 kpixmap_iconPalette[i++] = lightGray;
00313 kpixmap_iconPalette[i++] = gray;
00314 kpixmap_iconPalette[i++] = darkGray;
00315 kpixmap_iconPalette[i++] = black;
00316
00317
00318 kpixmap_iconPalette[i++] = QColor( 255, 192, 192 );
00319 kpixmap_iconPalette[i++] = QColor( 192, 255, 192 );
00320 kpixmap_iconPalette[i++] = QColor( 192, 192, 255 );
00321 kpixmap_iconPalette[i++] = QColor( 255, 255, 192 );
00322 kpixmap_iconPalette[i++] = QColor( 255, 192, 255 );
00323 kpixmap_iconPalette[i++] = QColor( 192, 255, 255 );
00324
00325
00326 kpixmap_iconPalette[i++] = QColor( 64, 0, 0 );
00327 kpixmap_iconPalette[i++] = QColor( 192, 0, 0 );
00328
00329
00330 kpixmap_iconPalette[i++] = QColor( 255, 128, 0 );
00331 kpixmap_iconPalette[i++] = QColor( 192, 88, 0 );
00332 kpixmap_iconPalette[i++] = QColor( 255, 168, 88 );
00333 kpixmap_iconPalette[i++] = QColor( 255, 220, 168 );
00334
00335
00336 kpixmap_iconPalette[i++] = QColor( 0, 0, 192 );
00337
00338
00339 kpixmap_iconPalette[i++] = QColor( 0, 64, 64 );
00340 kpixmap_iconPalette[i++] = QColor( 0, 192, 192 );
00341
00342
00343 kpixmap_iconPalette[i++] = QColor( 64, 64, 0 );
00344 kpixmap_iconPalette[i++] = QColor( 192, 192, 0 );
00345
00346
00347 kpixmap_iconPalette[i++] = QColor( 0, 64, 0 );
00348 kpixmap_iconPalette[i++] = QColor( 0, 192, 0 );
00349
00350
00351 kpixmap_iconPalette[i++] = QColor( 192, 0, 192 );
00352
00353
00354 kpixmap_iconPalette[i++] = QColor( 88, 88, 88 );
00355 kpixmap_iconPalette[i++] = QColor( 48, 48, 48 );
00356 kpixmap_iconPalette[i++] = QColor( 220, 220, 220 );
00357
00358 }
00359
00360 QRgb* ctable = image.colorTable();
00361
00362 int ncols = image.numColors();
00363 int j;
00364
00365
00366 int failures = 0;
00367
00368 for ( i=0; i<ncols; i++ ) {
00369 for ( j=0; j<40; j++ ) {
00370 if ( kpixmap_iconPalette[j].red() == qRed( ctable[i] ) &&
00371 kpixmap_iconPalette[j].green() == qGreen( ctable[i] ) &&
00372 kpixmap_iconPalette[j].blue() == qBlue( ctable[i] ) ) {
00373 break;
00374 }
00375 }
00376
00377 if ( j == 40 ) {
00378 failures ++;
00379 }
00380 }
00381
00382 return ( failures <= 1 );
00383
00384 }
00385
00386 KPixmap::KPixmap(const QPixmap& p)
00387 : QPixmap(p)
00388 {
00389 }