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 KPixmap::~KPixmap()
00187 {
00188 }
00189
00190 bool KPixmap::load( const QString& fileName, const char *format,
00191 int conversion_flags )
00192 {
00193 QImageIO io( fileName, format );
00194
00195 bool result = io.read();
00196
00197 if ( result ) {
00198 detach();
00199 result = convertFromImage( io.image(), conversion_flags );
00200 }
00201 return result;
00202 }
00203
00204 bool KPixmap::load( const QString& fileName, const char *format,
00205 ColorMode mode )
00206 {
00207 int conversion_flags = 0;
00208 switch (mode) {
00209 case Color:
00210 conversion_flags |= ColorOnly;
00211 break;
00212 case Mono:
00213 conversion_flags |= MonoOnly;
00214 break;
00215 case LowColor:
00216 conversion_flags |= LowOnly;
00217 break;
00218 case WebColor:
00219 conversion_flags |= WebOnly;
00220 break;
00221 default:
00222 break;
00223 }
00224 return load( fileName, format, conversion_flags );
00225 }
00226
00227 bool KPixmap::convertFromImage( const QImage &img, ColorMode mode )
00228 {
00229 int conversion_flags = 0;
00230 switch (mode) {
00231 case Color:
00232 conversion_flags |= ColorOnly;
00233 break;
00234 case Mono:
00235 conversion_flags |= MonoOnly;
00236 break;
00237 case LowColor:
00238 conversion_flags |= LowOnly;
00239 break;
00240 case WebColor:
00241 conversion_flags |= WebOnly;
00242 break;
00243 default:
00244 break;
00245 }
00246 return convertFromImage( img, conversion_flags );
00247 }
00248
00249 bool KPixmap::convertFromImage( const QImage &img, int conversion_flags )
00250 {
00251 if ( img.isNull() ) {
00252 #if defined(CHECK_NULL)
00253 qWarning( "KPixmap::convertFromImage: Cannot convert a null image" );
00254 #endif
00255 return false;
00256 }
00257 detach();
00258
00259 int dd = defaultDepth();
00260
00261
00262 if ( ( conversion_flags & KColorMode_Mask ) != LowOnly &&
00263 ( conversion_flags & KColorMode_Mask ) != WebOnly ) {
00264 return QPixmap::convertFromImage ( img, conversion_flags );
00265 }
00266
00267
00268
00269 if ( dd > 8 ) {
00270 if ( ( conversion_flags & KColorMode_Mask ) == LowOnly ||
00271 ( conversion_flags & KColorMode_Mask ) == WebOnly )
00272 conversion_flags = (conversion_flags & ~KColorMode_Mask) | Auto;
00273 return QPixmap::convertFromImage ( img, conversion_flags );
00274 }
00275
00276 if ( ( conversion_flags & KColorMode_Mask ) == LowOnly ) {
00277
00278
00279
00280
00281
00282
00283 if( img.numColors() > 0 && img.numColors() <=40 ) {
00284 if ( checkColorTable( img ) )
00285 return QPixmap::convertFromImage( img, QPixmap::Auto );
00286 }
00287
00288 QBitmap mask;
00289 bool isMask = false;
00290
00291 QImage image = img.convertDepth(32);
00292 QImage tImage( image.width(), image.height(), 8, 256 );
00293
00294 if( img.hasAlphaBuffer() ) {
00295 image.setAlphaBuffer( true );
00296 tImage.setAlphaBuffer( true );
00297 isMask = mask.convertFromImage( img.createAlphaMask() );
00298 }
00299
00300 kdither_32_to_8( &image, &tImage );
00301
00302 if( QPixmap::convertFromImage( tImage ) ) {
00303 if ( isMask ) QPixmap::setMask( mask );
00304 return true;
00305 } else
00306 return false;
00307 } else {
00308 QImage image = img.convertDepth( 32 );
00309 image.setAlphaBuffer( img.hasAlphaBuffer() );
00310 conversion_flags = (conversion_flags & ~ColorMode_Mask) | Auto;
00311 return QPixmap::convertFromImage ( image, conversion_flags );
00312 }
00313 }
00314
00315 static QColor* kpixmap_iconPalette = 0;
00316
00317 bool KPixmap::checkColorTable( const QImage &image )
00318 {
00319 int i = 0;
00320
00321 if (kpixmap_iconPalette == 0) {
00322 kpixmap_iconPalette = new QColor[40];
00323
00324
00325 kpixmap_iconPalette[i++] = red;
00326 kpixmap_iconPalette[i++] = green;
00327 kpixmap_iconPalette[i++] = blue;
00328 kpixmap_iconPalette[i++] = cyan;
00329 kpixmap_iconPalette[i++] = magenta;
00330 kpixmap_iconPalette[i++] = yellow;
00331 kpixmap_iconPalette[i++] = darkRed;
00332 kpixmap_iconPalette[i++] = darkGreen;
00333 kpixmap_iconPalette[i++] = darkBlue;
00334 kpixmap_iconPalette[i++] = darkCyan;
00335 kpixmap_iconPalette[i++] = darkMagenta;
00336 kpixmap_iconPalette[i++] = darkYellow;
00337 kpixmap_iconPalette[i++] = white;
00338 kpixmap_iconPalette[i++] = lightGray;
00339 kpixmap_iconPalette[i++] = gray;
00340 kpixmap_iconPalette[i++] = darkGray;
00341 kpixmap_iconPalette[i++] = black;
00342
00343
00344 kpixmap_iconPalette[i++] = QColor( 255, 192, 192 );
00345 kpixmap_iconPalette[i++] = QColor( 192, 255, 192 );
00346 kpixmap_iconPalette[i++] = QColor( 192, 192, 255 );
00347 kpixmap_iconPalette[i++] = QColor( 255, 255, 192 );
00348 kpixmap_iconPalette[i++] = QColor( 255, 192, 255 );
00349 kpixmap_iconPalette[i++] = QColor( 192, 255, 255 );
00350
00351
00352 kpixmap_iconPalette[i++] = QColor( 64, 0, 0 );
00353 kpixmap_iconPalette[i++] = QColor( 192, 0, 0 );
00354
00355
00356 kpixmap_iconPalette[i++] = QColor( 255, 128, 0 );
00357 kpixmap_iconPalette[i++] = QColor( 192, 88, 0 );
00358 kpixmap_iconPalette[i++] = QColor( 255, 168, 88 );
00359 kpixmap_iconPalette[i++] = QColor( 255, 220, 168 );
00360
00361
00362 kpixmap_iconPalette[i++] = QColor( 0, 0, 192 );
00363
00364
00365 kpixmap_iconPalette[i++] = QColor( 0, 64, 64 );
00366 kpixmap_iconPalette[i++] = QColor( 0, 192, 192 );
00367
00368
00369 kpixmap_iconPalette[i++] = QColor( 64, 64, 0 );
00370 kpixmap_iconPalette[i++] = QColor( 192, 192, 0 );
00371
00372
00373 kpixmap_iconPalette[i++] = QColor( 0, 64, 0 );
00374 kpixmap_iconPalette[i++] = QColor( 0, 192, 0 );
00375
00376
00377 kpixmap_iconPalette[i++] = QColor( 192, 0, 192 );
00378
00379
00380 kpixmap_iconPalette[i++] = QColor( 88, 88, 88 );
00381 kpixmap_iconPalette[i++] = QColor( 48, 48, 48 );
00382 kpixmap_iconPalette[i++] = QColor( 220, 220, 220 );
00383
00384 }
00385
00386 QRgb* ctable = image.colorTable();
00387
00388 int ncols = image.numColors();
00389 int j;
00390
00391
00392 int failures = 0;
00393
00394 for ( i=0; i<ncols; i++ ) {
00395 for ( j=0; j<40; j++ ) {
00396 if ( kpixmap_iconPalette[j].red() == qRed( ctable[i] ) &&
00397 kpixmap_iconPalette[j].green() == qGreen( ctable[i] ) &&
00398 kpixmap_iconPalette[j].blue() == qBlue( ctable[i] ) ) {
00399 break;
00400 }
00401 }
00402
00403 if ( j == 40 ) {
00404 failures ++;
00405 }
00406 }
00407
00408 return ( failures <= 1 );
00409
00410 }
00411
00412 KPixmap::KPixmap(const QPixmap& p)
00413 : QPixmap(p)
00414 {
00415 }