• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

kdefx

kpixmap.cpp

Go to the documentation of this file.
00001 /*
00002  *  This file is part of the KDE libraries
00003  *  Copyright (C) 1998  Mark Donohoe <donohoe@kde.org>
00004  *          Stephan Kulow <coolo@kde.org>
00005  *
00006  *  $Id$
00007  *
00008  *  This library is free software; you can redistribute it and/or
00009  *  modify it under the terms of the GNU Library General Public
00010  *  License as published by the Free Software Foundation; either
00011  *  version 2 of the License, or (at your option) any later version.
00012  *
00013  *  This library is distributed in the hope that it will be useful,
00014  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  *  Library General Public License for more details.
00017  *
00018  *  You should have received a copy of the GNU Library General Public License
00019  *  along with this library; see the file COPYING.LIB.  If not, write to
00020  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00021  *  Boston, MA 02110-1301, USA.
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 // Fast diffuse dither to 3x3x3 color cube
00034 // Based on Qt's image conversion functions
00035 static bool kdither_32_to_8( const QImage *src, QImage *dst )
00036 {
00037     // register QRgb *p;
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++ )       // build 2x2x2 color cube
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     // p = (QRgb *)src->scanLine(y);
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         // Bi-directional error diffusion
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             // Spread the error around...
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             // Spread the error around...
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;// Nothing.
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;  // Nothing.
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();                   // detach other references
00232     
00233     int dd = defaultDepth();
00234 
00235     // If color mode not one of KPixmaps extra modes nothing to do
00236     if ( ( conversion_flags & KColorMode_Mask ) != LowOnly &&
00237      ( conversion_flags & KColorMode_Mask ) != WebOnly ) {
00238         return QPixmap::convertFromImage ( img, conversion_flags );
00239     }
00240 
00241     // If the default pixmap depth is not 8bpp, KPixmap color modes have no
00242     // effect. Ignore them and use AutoColor instead.
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     // Here we skimp a little on the possible conversion modes
00252     // Don't offer ordered or threshold dither of RGB channels or
00253     // diffuse or ordered dither of alpha channel. It hardly seems
00254     // worth the effort for this specialized mode.
00255     
00256     // If image uses icon palette don't dither it.
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     // Standard palette
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     // Pastels
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     // Reds
00326     kpixmap_iconPalette[i++] = QColor( 64,   0,   0 );
00327     kpixmap_iconPalette[i++] = QColor( 192,  0,   0 );
00328 
00329     // Oranges
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     // Blues
00336     kpixmap_iconPalette[i++] = QColor(   0,   0, 192 );
00337 
00338     // Turquoise
00339     kpixmap_iconPalette[i++] = QColor(   0,  64,  64 );
00340     kpixmap_iconPalette[i++] = QColor(   0, 192, 192 );
00341 
00342     // Yellows
00343     kpixmap_iconPalette[i++] = QColor(  64,  64,   0 );
00344     kpixmap_iconPalette[i++] = QColor( 192, 192,   0 );
00345 
00346     // Greens
00347     kpixmap_iconPalette[i++] = QColor(   0,  64,   0 );
00348     kpixmap_iconPalette[i++] = QColor(   0, 192,   0 );
00349 
00350     // Purples
00351     kpixmap_iconPalette[i++] = QColor( 192,   0, 192 );
00352 
00353     // Greys
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     // Allow one failure which could be transparent background
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 }

kdefx

Skip menu "kdefx"
  • Main Page
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal