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