/* * This file is part of the KDE libraries * Copyright (C) 1998 Mark Donohoe * Stephan Kulow * * $Id$ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include "kpixmap.h" // Fast diffuse dither to 3x3x3 color cube // Based on Qt's image conversion functions static bool kdither_32_to_8( const TQImage *src, TQImage *dst ) { // register QRgb *p; uchar *b; int y; if ( !dst->create(src->width(), src->height(), 8, 256) ) { tqWarning("KPixmap: destination image not valid\n"); return false; } dst->setNumColors( 256 ); #define MAX_R 2 #define MAX_G 2 #define MAX_B 2 #define INDEXOF(r,g,b) (((r)*(MAX_G+1)+(g))*(MAX_B+1)+(b)) int rc, gc, bc; for ( rc=0; rc<=MAX_R; rc++ ) // build 2x2x2 color cube for ( gc=0; gc<=MAX_G; gc++ ) for ( bc=0; bc<=MAX_B; bc++ ) { dst->setColor( INDEXOF(rc,gc,bc), tqRgb( rc*255/MAX_R, gc*255/MAX_G, bc*255/MAX_B ) ); } int sw = src->width(); int* line1[3]; int* line2[3]; int* pv[3]; line1[0] = new int[src->width()]; line2[0] = new int[src->width()]; line1[1] = new int[src->width()]; line2[1] = new int[src->width()]; line1[2] = new int[src->width()]; line2[2] = new int[src->width()]; pv[0] = new int[sw]; pv[1] = new int[sw]; pv[2] = new int[sw]; for ( y=0; y < src->height(); y++ ) { // p = (QRgb *)src->scanLine(y); b = dst->scanLine(y); int endian = (TQImage::systemBitOrder() == TQImage::BigEndian); int x; uchar* q = const_cast(src)->scanLine(y); uchar* q2 = const_cast(src)->scanLine(y+1 < src->height() ? y + 1 : 0); for (int chan = 0; chan < 3; chan++) { b = dst->scanLine(y); int *l1 = (y&1) ? line2[chan] : line1[chan]; int *l2 = (y&1) ? line1[chan] : line2[chan]; if ( y == 0 ) { for (int i=0; iheight() ) { for (int i=0; i>4; l2[x+1] += err>>4; } l2[x]+=(err*5)>>4; if (x>1) l2[x-1]+=(err*3)>>4; } } else { for (x=sw; x-->0; ) { int pix = TQMAX(TQMIN(2, (l1[x] * 2 + 128)/ 255), 0); int err = l1[x] - pix * 255 / 2; pv[chan][x] = pix; // Spread the error around... if ( x > 0 ) { l1[x-1] += (err*7)>>4; l2[x-1] += err>>4; } l2[x]+=(err*5)>>4; if (x+1 < sw) l2[x+1]+=(err*3)>>4; } } } if (!endian) { for (x=0; x 8 ) { if ( ( conversion_flags & KColorMode_Mask ) == LowOnly || ( conversion_flags & KColorMode_Mask ) == WebOnly ) conversion_flags = (conversion_flags & ~KColorMode_Mask) | Auto; return TQPixmap::convertFromImage ( img, conversion_flags ); } if ( ( conversion_flags & KColorMode_Mask ) == LowOnly ) { // Here we skimp a little on the possible conversion modes // Don't offer ordered or threshold dither of RGB channels or // diffuse or ordered dither of alpha channel. It hardly seems // worth the effort for this specialized mode. // If image uses icon palette don't dither it. if( img.numColors() > 0 && img.numColors() <=40 ) { if ( checkColorTable( img ) ) return TQPixmap::convertFromImage( img, TQPixmap::Auto ); } TQBitmap mask; bool isMask = false; TQImage image = img.convertDepth(32); TQImage tImage( image.width(), image.height(), 8, 256 ); if( img.hasAlphaBuffer() ) { image.setAlphaBuffer( true ); tImage.setAlphaBuffer( true ); isMask = mask.convertFromImage( img.createAlphaMask() ); } kdither_32_to_8( &image, &tImage ); if( TQPixmap::convertFromImage( tImage ) ) { if ( isMask ) TQPixmap::setMask( mask ); return true; } else return false; } else { TQImage image = img.convertDepth( 32 ); image.setAlphaBuffer( img.hasAlphaBuffer() ); conversion_flags = (conversion_flags & ~ColorMode_Mask) | Auto; return TQPixmap::convertFromImage ( image, conversion_flags ); } } static TQColor* kpixmap_iconPalette = 0; bool KPixmap::checkColorTable( const TQImage &image ) { int i = 0; if (kpixmap_iconPalette == 0) { kpixmap_iconPalette = new TQColor[40]; // Standard palette kpixmap_iconPalette[i++] = red; kpixmap_iconPalette[i++] = green; kpixmap_iconPalette[i++] = blue; kpixmap_iconPalette[i++] = cyan; kpixmap_iconPalette[i++] = magenta; kpixmap_iconPalette[i++] = yellow; kpixmap_iconPalette[i++] = darkRed; kpixmap_iconPalette[i++] = darkGreen; kpixmap_iconPalette[i++] = darkBlue; kpixmap_iconPalette[i++] = darkCyan; kpixmap_iconPalette[i++] = darkMagenta; kpixmap_iconPalette[i++] = darkYellow; kpixmap_iconPalette[i++] = white; kpixmap_iconPalette[i++] = lightGray; kpixmap_iconPalette[i++] = gray; kpixmap_iconPalette[i++] = darkGray; kpixmap_iconPalette[i++] = black; // Pastels kpixmap_iconPalette[i++] = TQColor( 255, 192, 192 ); kpixmap_iconPalette[i++] = TQColor( 192, 255, 192 ); kpixmap_iconPalette[i++] = TQColor( 192, 192, 255 ); kpixmap_iconPalette[i++] = TQColor( 255, 255, 192 ); kpixmap_iconPalette[i++] = TQColor( 255, 192, 255 ); kpixmap_iconPalette[i++] = TQColor( 192, 255, 255 ); // Reds kpixmap_iconPalette[i++] = TQColor( 64, 0, 0 ); kpixmap_iconPalette[i++] = TQColor( 192, 0, 0 ); // Oranges kpixmap_iconPalette[i++] = TQColor( 255, 128, 0 ); kpixmap_iconPalette[i++] = TQColor( 192, 88, 0 ); kpixmap_iconPalette[i++] = TQColor( 255, 168, 88 ); kpixmap_iconPalette[i++] = TQColor( 255, 220, 168 ); // Blues kpixmap_iconPalette[i++] = TQColor( 0, 0, 192 ); // Turquoise kpixmap_iconPalette[i++] = TQColor( 0, 64, 64 ); kpixmap_iconPalette[i++] = TQColor( 0, 192, 192 ); // Yellows kpixmap_iconPalette[i++] = TQColor( 64, 64, 0 ); kpixmap_iconPalette[i++] = TQColor( 192, 192, 0 ); // Greens kpixmap_iconPalette[i++] = TQColor( 0, 64, 0 ); kpixmap_iconPalette[i++] = TQColor( 0, 192, 0 ); // Purples kpixmap_iconPalette[i++] = TQColor( 192, 0, 192 ); // Greys kpixmap_iconPalette[i++] = TQColor( 88, 88, 88 ); kpixmap_iconPalette[i++] = TQColor( 48, 48, 48 ); kpixmap_iconPalette[i++] = TQColor( 220, 220, 220 ); } TQRgb* ctable = image.tqcolorTable(); int ncols = image.numColors(); int j; // Allow one failure which could be transparent background int failures = 0; for ( i=0; i