From dba036816b279bc1539a9f3894fbc414665d2bce Mon Sep 17 00:00:00 2001 From: Michele Calgaro Date: Sun, 21 Apr 2019 23:22:20 +0900 Subject: Removed unnecessary and/or TDE-unrelated code. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michele Calgaro Signed-off-by: Slávek Banko --- tqtinterface/qt4/src/kernel/tqimage.cpp | 9526 ------------------------------- 1 file changed, 9526 deletions(-) delete mode 100644 tqtinterface/qt4/src/kernel/tqimage.cpp (limited to 'tqtinterface/qt4/src/kernel/tqimage.cpp') diff --git a/tqtinterface/qt4/src/kernel/tqimage.cpp b/tqtinterface/qt4/src/kernel/tqimage.cpp deleted file mode 100644 index 843f49e..0000000 --- a/tqtinterface/qt4/src/kernel/tqimage.cpp +++ /dev/null @@ -1,9526 +0,0 @@ -/**************************************************************************** -** -** Implementation of TQImage and TQImageIO classes -** -** Created : 950207 -** -** Copyright (C) 2010 Timothy Pearson and (C) 1992-2008 Trolltech ASA. -** -** This file is part of the kernel module of the TQt GUI Toolkit. -** -** This file may be used under the terms of the GNU General -** Public License versions 2.0 or 3.0 as published by the Free -** Software Foundation and appearing in the files LICENSE.GPL2 -** and LICENSE.GPL3 included in the packaging of this file. -** Alternatively you may (at your option) use any later version -** of the GNU General Public License if such license has been -** publicly approved by Trolltech ASA (or its successors, if any) -** and the KDE Free TQt Foundation. -** -** Please review the following information to ensure GNU General -** Public Licensing requirements will be met: -** http://trolltech.com/products/qt/licenses/licensing/opensource/. -** If you are unsure which license is appropriate for your use, please -** review the following information: -** http://trolltech.com/products/qt/licenses/licensing/licensingoverview -** or contact the sales department at sales@trolltech.com. -** -** This file may be used under the terms of the Q Public License as -** defined by Trolltech ASA and appearing in the file LICENSE.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** Commercial License Agreement provided with the Software. -** -** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, -** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted -** herein. -** -**********************************************************************/ - -#include -// Nasty, nasty horrid HACK to get access to QImage's private members -// This is TERRIBLE and I wish there was a way around it -// This is a good example of the new, broken & irritating Qt4 API, -// and the corresponding loss in functionality versus Qt3. -// See also tqrect.cpp -#define private protected -#include -#undef private - -#include "tqimage.h" -#include "tqregexp.h" -#include "tqfile.h" -#include "tqdatastream.h" -#include "tqtextstream.h" -#include "tqbuffer.h" -#include "tqptrlist.h" -#include "tqasyncimageio.h" -#include "tqpngio.h" -#include "tqmngio.h" -#include "tqjpegio.h" -#include "tqmap.h" -#include -#include "tqimageformatinterface_p.h" -#include "tqwmatrix.h" -#include "tqapplication.h" -#include "tqmime.h" -#include "tqdragobject.h" -#include -#include - -#ifdef TQ_WS_TQWS -#include "tqgfx_qws.h" -#endif - -#ifdef USE_QT4 - -#include - -#include "private/tqt_x11_p.h" -#include "private/qt4_qimage_p.h" - -QImage::Format TQImage::formatFor(int depth, TQImage::Endian bitOrder) -{ - QImage::Format format; - if (depth == 1) { - format = bitOrder == TQImage::BigEndian ? QImage::Format_Mono : QImage::Format_MonoLSB; - } else if (depth == 8) { - format = QImage::Format_Indexed8; - } else if (depth == 32) { - format = QImage::Format_ARGB32; - } else if (depth == 24) { - format = QImage::Format_RGB888; - } else if (depth == 16) { - format = QImage::Format_RGB16; - } else { - qWarning("QImage: Depth %d not supported", depth); - format = QImage::Format_Invalid; - } - return format; -} - -static QImage::Format tqformatFor(int depth, TQImage::Endian bitOrder) -{ - QImage::Format format; - if (depth == 1) { - format = bitOrder == TQImage::BigEndian ? QImage::Format_Mono : QImage::Format_MonoLSB; - } else if (depth == 8) { - format = QImage::Format_Indexed8; - } else if (depth == 32) { - format = QImage::Format_RGB32; - } else if (depth == 24) { - format = QImage::Format_RGB888; - } else if (depth == 16) { - format = QImage::Format_RGB16; - } else { - qWarning("QImage: Depth %d not supported", depth); - format = QImage::Format_Invalid; - } - return format; -} - -/*! - Converts the depth (bpp) of the image to the given \a depth and - returns the converted image. The original image is not changed. - Returns this image if \a depth is equal to the image depth, or a - null image if this image cannot be converted. The \a depth - argument must be 1, 8 or 32. If the image needs to be modified to - fit in a lower-resolution result (e.g. converting from 32-bit to - 8-bit), use the \a flags to specify how you'd prefer this to - happen. - - Use the convertToFormat() function instead. -*/ - -TQImage TQImage::convertDepth(int newdepth, Qt::ImageConversionFlags flags) const -{ - if (depth() == newdepth) - return *this; - - Format format = tqformatFor(newdepth, LittleEndian); - return convertToFormat(format, flags); -} - -#ifndef TQT_NO_IMAGEIO -/*! - Returns a string that specifies the image format of the file \a - fileName, or 0 if the file cannot be read or if the format is not - recognized. - - The TQImageIO documentation lists the guaranteed supported image - formats, or use TQImage::inputFormats() and TQImage::outputFormats() - to get lists that include the installed formats. - - \sa load() save() -*/ - -const char* TQImage::imageFormat( const TQString &fileName ) -{ - return TQImageIO::imageFormat( fileName ); -} -#endif - -/*! - Returns true if alpha buffer mode is enabled; otherwise returns - false. - - Use the hasAlphaChannel() function instead. - -*/ -bool TQImage::hasAlphaBuffer() const -{ - switch (format()) { - case Format_ARGB32: - case Format_ARGB32_Premultiplied: - case Format_ARGB8565_Premultiplied: - case Format_ARGB8555_Premultiplied: - case Format_ARGB6666_Premultiplied: - case Format_ARGB4444_Premultiplied: - return true; - default: - return false; - } -} - -/*! - Enables alpha buffer mode if \a enable is true, otherwise disables - it. The alpha buffer is used to set a mask when a QImage is - translated to a QPixmap. - - If a monochrome or indexed 8-bit image has alpha channels in their - color tables they will automatically detect that they have an - alpha channel, so this function is not required. To force alpha - channels on 32-bit images, use the convertToFormat() function. -*/ - -void TQImage::setAlphaBuffer(bool enable) -{ - if (format() == Format_Mono - || format() == Format_MonoLSB - || format() == Format_Indexed8) - return; - if (enable && (format() == Format_ARGB32 || - format() == Format_ARGB32_Premultiplied || - format() == Format_ARGB8565_Premultiplied || - format() == Format_ARGB6666_Premultiplied || - format() == Format_ARGB8555_Premultiplied || - format() == Format_ARGB4444_Premultiplied)) - { - return; - } - else { - // Emulate Ye Olde Tyme Qt3.x behaviour, where the alpha channel is always present - // in bits 24:31. This is to allow code that purposefully shuts down the alpha channel - // so that it may be initialized unhindered to function correctly under Qt4. - // The only side effect that I am aware of is that disabling the alpha channel will clear it out. - if (format() == Format_ARGB32 || - format() == Format_ARGB32_Premultiplied || - format() == Format_ARGB8565_Premultiplied || - format() == Format_ARGB6666_Premultiplied || - format() == Format_ARGB8555_Premultiplied || - format() == Format_ARGB4444_Premultiplied) - { - if (!enable) { - // Set the alpha buffer to opaque - // This may be a bit slow/memory intensive! Alternative suggestions are welcome. - detach(); - *this=convertToFormat(Format_RGB32); - detach(); - *this=convertToFormat(Format_ARGB32); - } - } - // As mentioned above, we get an alpha channel whether we wanted one or not! - detach(); - *this=convertToFormat(Format_ARGB32); - } -} - -/*! - Returns a pointer to the scanline pointer table. This is the - beginning of the data block for the image. - Returns 0 in case of an error. - - Use the bits() or scanLine() function instead. -*/ -uchar **TQImage::jumpTable() -{ -// if (!d) -// return 0; -// detach(); -// -// // in case detach() ran out of memory.. -// if (!d) -// return 0; -// -// if (!d->jumptable) { -// d->jumptable = (uchar **)malloc(d->height*sizeof(uchar *)); -// if (!d->jumptable) -// return 0; -// uchar *data = d->data; -// int height = d->height; -// uchar **p = d->jumptable; -// while (height--) { -// *p++ = data; -// data += d->bytes_per_line; -// } -// } -// return d->jumptable; - - // Qt4 does not have native jumpTable support; here is an approximate replacement - // We essentially reconstruct the jumptable here - if (jumptable) - free(jumptable); - jumptable = (uchar **)malloc(height()*sizeof(uchar *)); - if (!jumptable) - return 0; - uchar *data = scanLine(0); - int h = height(); - uchar **p = jumptable; - while (h--) { - *p++ = data; - data += bytesPerLine(); - } - return jumptable; -} - -/*! - \overload -*/ -const uchar * const *TQImage::jumpTable() const -{ -// if (!d) -// return 0; -// if (!d->jumptable) { -// d->jumptable = (uchar **)malloc(d->height*sizeof(uchar *)); -// if (!d->jumptable) -// return 0; -// uchar *data = d->data; -// int height = d->height; -// uchar **p = d->jumptable; -// while (height--) { -// *p++ = data; -// data += d->bytes_per_line; -// } -// } -// return d->jumptable; - - - // Qt4 does not have native jumpTable support; here is an approximate replacement - // We essentially reconstruct the jumptable here - if (jumptable) - free(jumptable); - jumptable = (uchar **)malloc(height()*sizeof(uchar *)); - if (!jumptable) - return 0; - const uchar *data = scanLine(0); - int h = height(); - uchar **p = jumptable; - while (h--) { - *p++ = const_cast(data); - data += bytesPerLine(); - } - return jumptable; -} - -/*! - \internal - Deallocates the image data and sets the bits pointer to 0. -*/ - -void TQImage::freeBits() -{ -// if ( data->bits ) { // dealloc image bits -// free( data->bits ); -// data->bits = 0; -// } - - // [FIXME] - printf("[WARNING] TQImage::freeBits() unimplemented\n\r"); -} - -void TQImage::reinit() -{ -// data->w = data->h = data->d = data->ncols = 0; -// data->nbytes = 0; -// data->ctbl = 0; -// data->bits = 0; -// data->bitordr = TQImage::IgnoreEndian; -// data->alpha = FALSE; -// #ifndef TQT_NO_IMAGE_TEXT -// data->misc = 0; -// #endif -// data->dpmx = 0; -// data->dpmy = 0; -// data->offset = TQPoint(0,0); - - // [FIXME] - printf("[WARNING] TQImage::reinit() unimplemented\n\r"); -} - -/*! - \fn bool TQImage::create(int width, int height, int depth, int numColors, Endian bitOrder) - - Sets the image \a width, \a height, \a depth, its number of colors - (in \a numColors), and bit order. Returns true if successful, or - false if the parameters are incorrect or if memory cannot be - allocated. - - The \a width and \a height is limited to 32767. \a depth must be - 1, 8, or 32. If \a depth is 1, \a bitOrder must be set to - either QImage::LittleEndian or QImage::BigEndian. For other depths - \a bitOrder must be QImage::IgnoreEndian. - - This function allocates a color table and a buffer for the image - data. The image data is not initialized. The image buffer is - allocated as a single block that consists of a table of scanLine() - pointers (jumpTable()) and the image data (bits()). - - Use a QImage constructor instead. -*/ -bool TQImage::create(int width, int height, int depth, int numColors, Endian bitOrder) -{ - if (d && !d->ref.deref()) - delete d; - d = QImageData::create(QSize(width, height), formatFor(depth, bitOrder), numColors); - return true; -} - -/*! - \fn bool TQImage::create(const QSize& size, int depth, int numColors, Endian bitOrder) - \overload - - The width and height are specified in the \a size argument. - - Use a QImage constructor instead. -*/ -bool TQImage::create(const TQSize& size, int depth, int numColors, TQImage::Endian bitOrder) -{ - if (d && !d->ref.deref()) - delete d; - d = QImageData::create(size, formatFor(depth, bitOrder), numColors); - return true; -} - -// [FIXME] [CRITICAL] [MEMLEAK] Memory leak! -// BUT any attempt to define this destructor will cause a glibc invalid pointer crash -// [FIXME] [CRITICAL] [MEMLEAK] -// TQImage::~TQImage() -// { -// if (jumptable) -// free(jumptable); -// jumptable = 0; -// } - -#if 0 -/*! - Sets the image IO status to \a status. A non-zero value indicates - an error, whereas 0 means that the IO operation was successful. - - \sa status() -*/ - -void TQImageIO::setqStatus( int status ) -{ - static_cast(QImageReader::device())->setqStatus(status); - static_cast(QImageWriter::device())->setqStatus(status); -} -#else - -/*! - Returns a list of image formats that are supported for image - input. - - \sa outputFormats() inputFormatList() TQImageIO -*/ -TQStrList TQImage::inputFormats() -{ - return TQImageIO::inputFormats(); -} -#ifndef TQT_NO_STRINGLIST -/*! - Returns a list of image formats that are supported for image - input. - - Note that if you want to iterate over the list, you should iterate - over a copy, e.g. - \code - TQStringList list = myImage.inputFormatList(); - TQStringList::Iterator it = list.begin(); - while( it != list.end() ) { - myProcessing( *it ); - ++it; - } - \endcode - - \sa outputFormatList() inputFormats() TQImageIO -*/ -TQStringList TQImage::inputFormatList() -{ - return TQStringList::fromStrList(TQImageIO::inputFormats()); -} - - -/*! - Returns a list of image formats that are supported for image - output. - - Note that if you want to iterate over the list, you should iterate - over a copy, e.g. - \code - TQStringList list = myImage.outputFormatList(); - TQStringList::Iterator it = list.begin(); - while( it != list.end() ) { - myProcessing( *it ); - ++it; - } - \endcode - - \sa inputFormatList() outputFormats() TQImageIO -*/ -TQStringList TQImage::outputFormatList() -{ - return TQStringList::fromStrList(TQImageIO::outputFormats()); -} -#endif //TQT_NO_STRINGLIST - -/*! - Returns a list of image formats that are supported for image - output. - - \sa inputFormats() outputFormatList() TQImageIO -*/ -TQStrList TQImage::outputFormats() -{ - return TQImageIO::outputFormats(); -} - - -/*! - Loads an image from the file \a fileName. Returns TRUE if the - image was successfully loaded; otherwise returns FALSE. - - If \a format is specified, the loader attempts to read the image - using the specified format. If \a format is not specified (which - is the default), the loader reads a few bytes from the header to - guess the file format. - - The TQImageIO documentation lists the supported image formats and - explains how to add extra formats. - - \sa loadFromData() save() imageFormat() TQPixmap::load() TQImageIO -*/ - -bool TQImage::load( const TQString &fileName, const char* format ) -{ - TQImageIO io( fileName, format ); - bool result = io.read(); - if ( result ) - operator=( io.image() ); - return result; -} - -/*! - Loads an image from the first \a len bytes of binary data in \a - buf. Returns TRUE if the image was successfully loaded; otherwise - returns FALSE. - - If \a format is specified, the loader attempts to read the image - using the specified format. If \a format is not specified (which - is the default), the loader reads a few bytes from the header to - guess the file format. - - The TQImageIO documentation lists the supported image formats and - explains how to add extra formats. - - \sa load() save() imageFormat() TQPixmap::loadFromData() TQImageIO -*/ - -bool TQImage::loadFromData( const uchar *buf, uint len, const char *format ) -{ - TQByteArray a; - a.setRawData( (char *)buf, len ); - TQBuffer b( a ); - b.open( IO_ReadOnly ); - TQImageIO io( &b, format ); - bool result = io.read(); - b.close(); - a.resetRawData( (char *)buf, len ); - if ( result ) - operator=( io.image() ); - return result; -} - -/*! - \overload - - Loads an image from the TQByteArray \a buf. -*/ -bool TQImage::loadFromData( TQByteArray buf, const char *format ) -{ - return loadFromData( (const uchar *)(buf.data()), buf.size(), format ); -} - -/*! - Saves the image to the file \a fileName, using the image file - format \a format and a quality factor of \a quality. \a quality - must be in the range 0..100 or -1. Specify 0 to obtain small - compressed files, 100 for large uncompressed files, and -1 (the - default) to use the default settings. - - Returns TRUE if the image was successfully saved; otherwise - returns FALSE. - - \sa load() loadFromData() imageFormat() TQPixmap::save() TQImageIO -*/ - -bool TQImage::save( const TQString &fileName, const char* format, int quality ) const -{ - if ( isNull() ) - return FALSE; // nothing to save - TQImageIO io( fileName, format ); - return doImageIO( &io, quality ); -} - -/*! - \overload - - This function writes a TQImage to the TQIODevice, \a tqdevice. This - can be used, for example, to save an image directly into a - TQByteArray: - \code - TQImage image; - TQByteArray ba; - TQBuffer buffer( ba ); - buffer.open( IO_WriteOnly ); - image.save( &buffer, "PNG" ); // writes image into ba in PNG format - \endcode -*/ - -bool TQImage::save( QIODevice* tqdevice, const char* format, int quality ) const -{ - if ( isNull() ) - return FALSE; // nothing to save - TQImageIO io( tqdevice, format ); - return doImageIO( &io, quality ); -} - -/* \internal -*/ - -bool TQImage::doImageIO( TQImageIO* io, int quality ) const -{ - if ( !io ) - return FALSE; - io->setImage( *this ); -#if defined(TQT_CHECK_RANGE) - if ( quality > 100 || quality < -1 ) - qWarning( "TQPixmap::save: quality out of range [-1,100]" ); -#endif - if ( quality >= 0 ) - io->setQuality( TQMIN(quality,100) ); - return io->write(); -} - -/***************************************************************************** - Standard image io handlers (defined below) - *****************************************************************************/ - -// standard image io handlers (defined below) -#ifndef TQT_NO_IMAGEIO_BMP -static void read_bmp_image( TQImageIO * ); -static void write_bmp_image( TQImageIO * ); -#endif -#ifndef TQT_NO_IMAGEIO_PPM -static void read_pbm_image( TQImageIO * ); -static void write_pbm_image( TQImageIO * ); -#endif -#ifndef TQT_NO_IMAGEIO_XBM -static void read_xbm_image( TQImageIO * ); -static void write_xbm_image( TQImageIO * ); -#endif -#ifndef TQT_NO_IMAGEIO_XPM -static void read_xpm_image( TQImageIO * ); -static void write_xpm_image( TQImageIO * ); -#endif - -#ifndef TQT_NO_ASYNC_IMAGE_IO -static void read_async_image( TQImageIO * ); // Not in table of handlers -#endif - -/***************************************************************************** - Misc. utility functions - *****************************************************************************/ -#if !defined(TQT_NO_IMAGEIO_XPM) || !defined(TQT_NO_IMAGEIO_XBM) -static TQString fbname( const TQString &fileName ) // get file basename (sort of) -{ - TQString s = fileName; - if ( !s.isEmpty() ) { - int i; - if ( (i = s.findRev('/')) >= 0 ) - s = s.mid( i ); - if ( (i = s.findRev('\\')) >= 0 ) - s = s.mid( i ); - TQRegExp r( TQString::tqfromLatin1("[a-zA-Z][a-zA-Z0-9_]*") ); - int p = r.search( s ); - if ( p == -1 ) - s.truncate( 0 ); - else - s = s.mid( p, r.matchedLength() ); - } - if ( s.isEmpty() ) - s = TQString::tqfromLatin1( "dummy" ); - return s; -} -#endif - -#ifndef TQT_NO_IMAGEIO_BMP -static void swapPixel01( TQImage *image ) // 1-bpp: swap 0 and 1 pixels -{ - int i; - if ( image->depth() == 1 && image->numColors() == 2 ) { - register uint *p = (uint *)image->bits(); - int nbytes = image->numBytes(); - for ( i=0; icolor(0); // swap color 0 and 1 - image->setColor( 0, image->color(1) ); - image->setColor( 1, t ); - } -} -#endif - - -/***************************************************************************** - TQImageIO member functions - *****************************************************************************/ - -/*! - \class TQImageIO tqimage.h - - \brief The TQImageIO class contains parameters for loading and - saving images. - - \ingroup images - \ingroup graphics - \ingroup io - - TQImageIO contains a TQIODevice object that is used for image data - I/O. The programmer can install new image file formats in addition - to those that TQt provides. - - TQt currently supports the following image file formats: PNG, BMP, - XBM, XPM and PNM. It may also support JPEG, MNG and GIF, if - specially configured during compilation. The different PNM formats - are: PBM (P1 or P4), PGM (P2 or P5), and PPM (P3 or P6). - - You don't normally need to use this class; TQPixmap::load(), - TQPixmap::save(), and TQImage contain sufficient functionality. - - For image files that contain sequences of images, only the first - is read. See TQMovie for loading multiple images. - - PBM, PGM, and PPM format \e output is always in the more condensed - raw format. PPM and PGM files with more than 256 levels of - intensity are scaled down when reading. - - \warning If you are in a country which recognizes software patents - and in which Unisys holds a patent on LZW compression and/or - decompression and you want to use GIF, Unisys may require you to - license the technology. Such countries include Canada, Japan, the - USA, France, Germany, Italy and the UK. It is believed that as of - this writing (March 15, 2011) all GIF software patents have expired. - However, this does not constitute legal advice! Check with a lawyer - if you want to know if the patents have expired in your country. - - GIF support may be removed completely in a future version of TQt. - We strongly recommend using the lossless PNG format. - - \sa TQImage TQPixmap TQFile TQMovie -*/ - -#ifndef TQT_NO_IMAGEIO -struct TQImageIOData -{ - const char *parameters; - int quality; - float gamma; -}; - -/*! - Constructs a TQImageIO object with all parameters set to zero. -*/ - -TQImageIO::TQImageIO() -{ - init(); -} - -/*! - Constructs a TQImageIO object with the I/O tqdevice \a ioDevice and a - \a format tag. -*/ - -TQImageIO::TQImageIO( QIODevice *ioDevice, const char *format ) - : frmt(format) -{ - init(); - iodev = TQT_TQIODEVICE(ioDevice); -} - -/*! - Constructs a TQImageIO object with the file name \a fileName and a - \a format tag. -*/ - -TQImageIO::TQImageIO( const TQString &fileName, const char* format ) - : frmt(format), fname(fileName) -{ - init(); -} - -/*! - Contains initialization common to all TQImageIO constructors. -*/ - -void TQImageIO::init() -{ - d = new TQImageIOData(); - d->parameters = 0; - d->quality = -1; // default quality of the current format - d->gamma=0.0f; - iostat = 0; - iodev = 0; -} - -/*! - Destroys the object and all related data. -*/ - -TQImageIO::~TQImageIO() -{ - if ( d->parameters ) - delete [] (char*)d->parameters; - delete d; -} - - -/***************************************************************************** - TQImageIO image handler functions - *****************************************************************************/ - -class TQImageHandler -{ -public: - TQImageHandler( const char *f, const char *h, const TQCString& fl, - image_io_handler r, image_io_handler w ); - TQCString format; // image format - TQRegExp header; // image header pattern - enum TMode { Untranslated=0, TranslateIn, TranslateInOut } text_mode; - image_io_handler read_image; // image read function - image_io_handler write_image; // image write function - bool obsolete; // support not "published" -}; - -TQImageHandler::TQImageHandler( const char *f, const char *h, const TQCString& fl, - image_io_handler r, image_io_handler w ) - : format(f), header(TQString::tqfromLatin1(h)) -{ - text_mode = Untranslated; - if ( fl.contains('t') ) - text_mode = TranslateIn; - else if ( fl.contains('T') ) - text_mode = TranslateInOut; - obsolete = fl.contains('O'); - read_image = r; - write_image = w; -} - -typedef TQPtrList TQIHList;// list of image handlers -static TQIHList *imageHandlers = 0; -#ifndef TQT_NO_COMPONENT -static TQPluginManager *plugin_manager = 0; -#else -static void *plugin_manager = 0; -#endif - -void qt_init_image_plugins() -{ -#ifndef TQT_NO_COMPONENT - if ( plugin_manager ) - return; - - plugin_manager = new TQPluginManager( IID_TQImageFormat, TQApplication::libraryPaths(), "/imageformats" ); - - TQStringList features = plugin_manager->featureList(); - TQStringList::Iterator it = features.begin(); - while ( it != features.end() ) { - TQString str = *it; - ++it; - TQInterfacePtr iface; - plugin_manager->queryInterface( str, &iface ); - if ( iface ) - iface->installIOHandler( str ); - } -#endif -} - -static void cleanup() -{ - // make sure that image handlers are deleted before plugin manager - delete imageHandlers; - imageHandlers = 0; -#ifndef TQT_NO_COMPONENT - delete plugin_manager; - plugin_manager = 0; -#endif -} - -void qt_init_image_handlers() // initialize image handlers -{ - if ( !imageHandlers ) { - imageHandlers = new TQIHList; - TQ_CHECK_PTR( imageHandlers ); - imageHandlers->setAutoDelete( TRUE ); - qAddPostRoutine( cleanup ); -#ifndef TQT_NO_IMAGEIO_BMP - TQImageIO::defineIOHandler( "BMP", "^BM", 0, - read_bmp_image, write_bmp_image ); -#endif -#ifndef TQT_NO_IMAGEIO_PPM - TQImageIO::defineIOHandler( "PBM", "^P1", "t", - read_pbm_image, write_pbm_image ); - TQImageIO::defineIOHandler( "PBMRAW", "^P4", "O", - read_pbm_image, write_pbm_image ); - TQImageIO::defineIOHandler( "PGM", "^P2", "t", - read_pbm_image, write_pbm_image ); - TQImageIO::defineIOHandler( "PGMRAW", "^P5", "O", - read_pbm_image, write_pbm_image ); - TQImageIO::defineIOHandler( "PPM", "^P3", "t", - read_pbm_image, write_pbm_image ); - TQImageIO::defineIOHandler( "PPMRAW", "^P6", "O", - read_pbm_image, write_pbm_image ); -#endif -#ifndef TQT_NO_IMAGEIO_XBM - TQImageIO::defineIOHandler( "XBM", "^((/\\*(?!.XPM.\\*/))|#define)", "T", - read_xbm_image, write_xbm_image ); -#endif -#ifndef TQT_NO_IMAGEIO_XPM - TQImageIO::defineIOHandler( "XPM", "/\\*.XPM.\\*/", "T", - read_xpm_image, write_xpm_image ); -#endif -#ifndef TQT_NO_IMAGEIO_MNG - qInitMngIO(); -#endif -#ifndef TQT_NO_IMAGEIO_PNG - qInitPngIO(); -#endif -#ifndef TQT_NO_IMAGEIO_JPEG - qInitJpegIO(); -#endif - } -} - -static TQImageHandler *get_image_handler( const char *format ) -{ // get pointer to handler - qt_init_image_handlers(); - qt_init_image_plugins(); - register TQImageHandler *p = imageHandlers->first(); - while ( p ) { // traverse list - if ( p->format == format ) - return p; - p = imageHandlers->next(); - } - return 0; // no such handler -} - - -/*! - Defines an image I/O handler for the image format called \a - format, which is recognized using the \link tqregexp.html#details - regular expression\endlink \a header, read using \a readImage and - written using \a writeImage. - - \a flags is a string of single-character flags for this format. - The only flag defined currently is T (upper case), so the only - legal value for \a flags are "T" and the empty string. The "T" - flag means that the image file is a text file, and TQt should treat - all newline conventions as equivalent. (XPM files and some PPM - files are text files for example.) - - \a format is used to select a handler to write a TQImage; \a header - is used to select a handler to read an image file. - - If \a readImage is a null pointer, the TQImageIO will not be able - to read images in \a format. If \a writeImage is a null pointer, - the TQImageIO will not be able to write images in \a format. If - both are null, the TQImageIO object is valid but useless. - - Example: - \code - void readGIF( TQImageIO *image ) - { - // read the image using the image->ioDevice() - } - - void writeGIF( TQImageIO *image ) - { - // write the image using the image->ioDevice() - } - - // add the GIF image handler - - TQImageIO::defineIOHandler( "GIF", - "^GIF[0-9][0-9][a-z]", - 0, - readGIF, - writeGIF ); - \endcode - - Before the regex test, all the 0 bytes in the file header are - converted to 1 bytes. This is done because when TQt was - ASCII-based, TQRegExp could not handle 0 bytes in strings. - - The regexp is only applied on the first 14 bytes of the file. - - Note that TQt assumes that there is only one handler per format; if - two handlers support the same format, TQt will choose one - arbitrarily. It is not possible to have one handler support - reading, and another support writing. -*/ - -void TQImageIO::defineIOHandler( const char *format, - const char *header, - const char *flags, - image_io_handler readImage, - image_io_handler writeImage ) -{ - qt_init_image_handlers(); - TQImageHandler *p; - p = new TQImageHandler( format, header, flags, - readImage, writeImage ); - TQ_CHECK_PTR( p ); - imageHandlers->insert( 0, p ); -} - - -/***************************************************************************** - TQImageIO normal member functions - *****************************************************************************/ - -/*! - \fn const TQImage &TQImageIO::image() const - - Returns the image currently set. - - \sa setImage() -*/ - -/*! - \fn int TQImageIO::status() const - - Returns the image's IO status. A non-zero value indicates an - error, whereas 0 means that the IO operation was successful. - - \sa setqStatus() -*/ - -/*! - \fn const char *TQImageIO::format() const - - Returns the image format string or 0 if no format has been - explicitly set. -*/ - -/*! - \fn TQIODevice *TQImageIO::ioDevice() const - - Returns the IO tqdevice currently set. - - \sa setIODevice() -*/ - -/*! - \fn TQString TQImageIO::fileName() const - - Returns the file name currently set. - - \sa setFileName() -*/ - -/*! - \fn TQString TQImageIO::description() const - - Returns the image description string. - - \sa setDescription() -*/ - - -/*! - Sets the image to \a image. - - \sa image() -*/ - -void TQImageIO::setImage( const QImage &image ) -{ - im = image; -} - -/*! - Sets the image IO status to \a status. A non-zero value indicates - an error, whereas 0 means that the IO operation was successful. - - \sa status() -*/ - -void TQImageIO::setqStatus( int status ) -{ - iostat = status; -} - -/*! - Sets the image format to \a format for the image to be read or - written. - - It is necessary to specify a format before writing an image, but - it is not necessary to specify a format before reading an image. - - If no format has been set, TQt guesses the image format before - reading it. If a format is set the image will only be read if it - has that format. - - \sa read() write() format() -*/ - -void TQImageIO::setFormat( const char *format ) -{ - frmt = format; -} - -/*! - Sets the IO tqdevice to be used for reading or writing an image. - - Setting the IO tqdevice allows images to be read/written to any - block-oriented TQIODevice. - - If \a ioDevice is not null, this IO tqdevice will override file name - settings. - - \sa setFileName() -*/ - -void TQImageIO::setIODevice( TQIODevice *ioDevice ) -{ - iodev = ioDevice; -} - -/*! - Sets the name of the file to read or write an image from to \a - fileName. - - \sa setIODevice() -*/ - -void TQImageIO::setFileName( const TQString &fileName ) -{ - fname = fileName; -} - -/*! - Returns the quality of the written image, related to the - compression ratio. - - \sa setQuality() TQImage::save() -*/ - -int TQImageIO::quality() const -{ - return d->quality; -} - -/*! - Sets the quality of the written image to \a q, related to the - compression ratio. - - \a q must be in the range -1..100. Specify 0 to obtain small - compressed files, 100 for large uncompressed files. (-1 signifies - the default compression.) - - \sa quality() TQImage::save() -*/ - -void TQImageIO::setQuality( int q ) -{ - d->quality = q; -} - -/*! - Returns the image's parameters string. - - \sa setParameters() -*/ - -const char *TQImageIO::parameters() const -{ - return d->parameters; -} - -/*! - Sets the image's parameter string to \a parameters. This is for - image handlers that require special parameters. - - Although the current image formats supported by TQt ignore the - parameters string, it may be used in future extensions or by - contributions (for example, JPEG). - - \sa parameters() -*/ - -void TQImageIO::setParameters( const char *parameters ) -{ - if ( d && d->parameters ) - delete [] (char*)d->parameters; - d->parameters = qstrdup( parameters ); -} - -/*! - Sets the gamma value at which the image will be viewed to \a - gamma. If the image format stores a gamma value for which the - image is intended to be used, then this setting will be used to - modify the image. Setting to 0.0 will disable gamma correction - (i.e. any specification in the file will be ignored). - - The default value is 0.0. - - \sa gamma() -*/ -void TQImageIO::setGamma( float gamma ) -{ - d->gamma=gamma; -} - -/*! - Returns the gamma value at which the image will be viewed. - - \sa setGamma() -*/ -float TQImageIO::gamma() const -{ - return d->gamma; -} - -/*! - Sets the image description string for image handlers that support - image descriptions to \a description. - - Currently, no image format supported by TQt uses the description - string. -*/ - -void TQImageIO::setDescription( const TQString &description ) -{ - descr = description; -} - - -/*! - Returns a string that specifies the image format of the file \a - fileName, or null if the file cannot be read or if the format is - not recognized. -*/ - -const char* TQImageIO::imageFormat( const TQString &fileName ) -{ - TQFile file( fileName ); - if ( !file.open(IO_ReadOnly) ) - return 0; - const char* format = imageFormat( TQT_TQIODEVICE(&file) ); - file.close(); - return format; -} - -/*! - \overload - - Returns a string that specifies the image format of the image read - from IO tqdevice \a d, or 0 if the tqdevice cannot be read or if the - format is not recognized. - - Make sure that \a d is at the right position in the tqdevice (for - example, at the beginning of the file). - - \sa TQIODevice::at() -*/ - -const char *TQImageIO::imageFormat( TQIODevice *d ) -{ - // if you change this change the documentation for defineIOHandler() - const int buflen = 14; - - char buf[buflen]; - char buf2[buflen]; - qt_init_image_handlers(); - qt_init_image_plugins(); - int pos = d->at(); // save position - int rdlen = d->readBlock( buf, buflen ); // read a few bytes - - if ( rdlen != buflen ) - return 0; - - memcpy( buf2, buf, buflen ); - - const char* format = 0; - for ( int n = 0; n < rdlen; n++ ) - if ( buf[n] == '\0' ) - buf[n] = '\001'; - if ( d->status() == IO_Ok && rdlen > 0 ) { - buf[rdlen - 1] = '\0'; - TQString bufStr = TQString::tqfromLatin1(buf); - TQImageHandler *p = imageHandlers->first(); - int bestMatch = -1; - while ( p ) { - if ( p->read_image && p->header.search(bufStr) != -1 ) { - // try match with header if a read function is available - if (p->header.matchedLength() > bestMatch) { - // keep looking for best match - format = p->format; - bestMatch = p->header.matchedLength(); - } - } - p = imageHandlers->next(); - } - } - d->at( pos ); // restore position -#ifndef TQT_NO_ASYNC_IMAGE_IO - if ( !format ) - format = TQImageDecoder::formatName( (uchar*)buf2, rdlen ); -#endif - - return format; -} - -/*! - Returns a sorted list of image formats that are supported for - image input. -*/ -TQStrList TQImageIO::inputFormats() -{ - TQStrList result; - - qt_init_image_handlers(); - qt_init_image_plugins(); - -#ifndef TQT_NO_ASYNC_IMAGE_IO - // Include asynchronous loaders first. - result = TQImageDecoder::inputFormats(); -#endif - - TQImageHandler *p = imageHandlers->first(); - while ( p ) { - if ( p->read_image - && !p->obsolete - && !result.contains(p->format) ) - { - result.inSort(p->format); - } - p = imageHandlers->next(); - } - - return result; -} - -/*! - Returns a sorted list of image formats that are supported for - image output. -*/ -TQStrList TQImageIO::outputFormats() -{ - TQStrList result; - - qt_init_image_handlers(); - qt_init_image_plugins(); - - // Include asynchronous writers (!) first. - // (None) - - TQImageHandler *p = imageHandlers->first(); - while ( p ) { - if ( p->write_image - && !p->obsolete - && !result.contains(p->format) ) - { - result.inSort(p->format); - } - p = imageHandlers->next(); - } - - return result; -} - - - -/*! - Reads an image into memory and returns TRUE if the image was - successfully read; otherwise returns FALSE. - - Before reading an image you must set an IO tqdevice or a file name. - If both an IO tqdevice and a file name have been set, the IO tqdevice - will be used. - - Setting the image file format string is optional. - - Note that this function does \e not set the \link format() - format\endlink used to read the image. If you need that - information, use the imageFormat() static functions. - - Example: - - \code - TQImageIO iio; - TQPixmap pixmap; - iio.setFileName( "vegeburger.bmp" ); - if ( image.read() ) // ok - pixmap = iio.image(); // convert to pixmap - \endcode - - \sa setIODevice() setFileName() setFormat() write() TQPixmap::load() -*/ - -bool TQImageIO::read() -{ - TQFile file; - const char *image_format; - TQImageHandler *h; - - if ( iodev ) { // read from io tqdevice - // ok, already open - } else if ( !fname.isEmpty() ) { // read from file - file.setName( fname ); - if ( !file.open(IO_ReadOnly) ) - return FALSE; // cannot open file - iodev = TQT_TQIODEVICE(&file); - } else { // no file name or io tqdevice - return FALSE; - } - if (frmt.isEmpty()) { - // Try to guess format - image_format = imageFormat( iodev ); // get image format - if ( !image_format ) { - if ( file.isOpen() ) { // unknown format - file.close(); - iodev = 0; - } - return FALSE; - } - } else { - image_format = frmt; - } - - h = get_image_handler( image_format ); - if ( file.isOpen() ) { -#if !defined(TQ_OS_UNIX) - if ( h && h->text_mode ) { // reopen in translated mode - file.close(); - file.open( IO_ReadOnly | IO_Translate ); - } - else -#endif - file.at( 0 ); // position to start - } - iostat = 1; // assume error - - if ( h && h->read_image ) { - (*h->read_image)( this ); - } -#ifndef TQT_NO_ASYNC_IMAGE_IO - else { - // Format name, but no handler - must be an asychronous reader - read_async_image( this ); - } -#endif - - if ( file.isOpen() ) { // image was read using file - file.close(); - iodev = 0; - } - return iostat == 0; // image successfully read? -} - - -/*! - Writes an image to an IO tqdevice and returns TRUE if the image was - successfully written; otherwise returns FALSE. - - Before writing an image you must set an IO tqdevice or a file name. - If both an IO tqdevice and a file name have been set, the IO tqdevice - will be used. - - The image will be written using the specified image format. - - Example: - \code - TQImageIO iio; - TQImage im; - im = pixmap; // convert to image - iio.setImage( im ); - iio.setFileName( "vegeburger.bmp" ); - iio.setFormat( "BMP" ); - if ( iio.write() ) - // returned TRUE if written successfully - \endcode - - \sa setIODevice() setFileName() setFormat() read() TQPixmap::save() -*/ - -bool TQImageIO::write() -{ - if ( frmt.isEmpty() ) - return FALSE; - TQImageHandler *h = get_image_handler( frmt ); - if ( !h && !plugin_manager) { - qt_init_image_plugins(); - h = get_image_handler( frmt ); - } - if ( !h || !h->write_image ) { -#if defined(TQT_CHECK_RANGE) - qWarning( "TQImageIO::write: No such image format handler: %s", - format() ); -#endif - return FALSE; - } - TQFile file; - if ( !iodev && !fname.isEmpty() ) { - file.setName( fname ); - bool translate = h->text_mode==TQImageHandler::TranslateInOut; - int fmode = translate ? IO_WriteOnly|IO_Translate : IO_WriteOnly; - if ( !file.open(fmode) ) // couldn't create file - return FALSE; - iodev = TQT_TQIODEVICE(&file); - } - iostat = 1; - (*h->write_image)( this ); - if ( file.isOpen() ) { // image was written using file - file.close(); - iodev = 0; - } - return iostat == 0; // image successfully written? -} - -#ifndef TQT_NO_IMAGEIO_BMP - -/***************************************************************************** - BMP (DIB) image read/write functions - *****************************************************************************/ - -const int BMP_FILEHDR_SIZE = 14; // size of BMP_FILEHDR data - -struct BMP_FILEHDR { // BMP file header - char bfType[2]; // "BM" - TQ_INT32 bfSize; // size of file - TQ_INT16 bfReserved1; - TQ_INT16 bfReserved2; - TQ_INT32 bfOffBits; // pointer to the pixmap bits -}; - -TQDataStream &operator>>( TQDataStream &s, BMP_FILEHDR &bf ) -{ // read file header - s.readRawBytes( bf.bfType, 2 ); - s >> bf.bfSize >> bf.bfReserved1 >> bf.bfReserved2 >> bf.bfOffBits; - return s; -} - -TQDataStream &operator<<( TQDataStream &s, const BMP_FILEHDR &bf ) -{ // write file header - s.writeRawBytes( bf.bfType, 2 ); - s << bf.bfSize << bf.bfReserved1 << bf.bfReserved2 << bf.bfOffBits; - return s; -} - - -const int BMP_OLD = 12; // old Windows/OS2 BMP size -const int BMP_WIN = 40; // new Windows BMP size -const int BMP_OS2 = 64; // new OS/2 BMP size - -const int BMP_RGB = 0; // no compression -const int BMP_RLE8 = 1; // run-length encoded, 8 bits -const int BMP_RLE4 = 2; // run-length encoded, 4 bits -const int BMP_BITFIELDS = 3; // RGB values encoded in data as bit-fields - -struct BMP_INFOHDR { // BMP information header - TQ_INT32 biSize; // size of this struct - TQ_INT32 biWidth; // pixmap width - TQ_INT32 biHeight; // pixmap height - TQ_INT16 biPlanes; // should be 1 - TQ_INT16 biBitCount; // number of bits per pixel - TQ_INT32 biCompression; // compression method - TQ_INT32 biSizeImage; // size of image - TQ_INT32 biXPelsPerMeter; // horizontal resolution - TQ_INT32 biYPelsPerMeter; // vertical resolution - TQ_INT32 biClrUsed; // number of colors used - TQ_INT32 biClrImportant; // number of important colors -}; - - -TQDataStream &operator>>( TQDataStream &s, BMP_INFOHDR &bi ) -{ - s >> bi.biSize; - if ( bi.biSize == BMP_WIN || bi.biSize == BMP_OS2 ) { - s >> bi.biWidth >> bi.biHeight >> bi.biPlanes >> bi.biBitCount; - s >> bi.biCompression >> bi.biSizeImage; - s >> bi.biXPelsPerMeter >> bi.biYPelsPerMeter; - s >> bi.biClrUsed >> bi.biClrImportant; - } - else { // probably old Windows format - TQ_INT16 w, h; - s >> w >> h >> bi.biPlanes >> bi.biBitCount; - bi.biWidth = w; - bi.biHeight = h; - bi.biCompression = BMP_RGB; // no compression - bi.biSizeImage = 0; - bi.biXPelsPerMeter = bi.biYPelsPerMeter = 0; - bi.biClrUsed = bi.biClrImportant = 0; - } - return s; -} - -TQDataStream &operator<<( TQDataStream &s, const BMP_INFOHDR &bi ) -{ - s << bi.biSize; - s << bi.biWidth << bi.biHeight; - s << bi.biPlanes; - s << bi.biBitCount; - s << bi.biCompression; - s << bi.biSizeImage; - s << bi.biXPelsPerMeter << bi.biYPelsPerMeter; - s << bi.biClrUsed << bi.biClrImportant; - return s; -} - -static -int calc_shift(int mask) -{ - int result = 0; - while (!(mask & 1)) { - result++; - mask >>= 1; - } - return result; -} - -static -bool read_dib( TQDataStream& s, int offset, int startpos, TQImage& image ) -{ - BMP_INFOHDR bi; - TQIODevice* d = s.tqdevice(); - - s >> bi; // read BMP info header - if ( d->atEnd() ) // end of stream/file - return FALSE; -#if 0 - qDebug( "offset...........%d", offset ); - qDebug( "startpos.........%d", startpos ); - qDebug( "biSize...........%d", bi.biSize ); - qDebug( "biWidth..........%d", bi.biWidth ); - qDebug( "biHeight.........%d", bi.biHeight ); - qDebug( "biPlanes.........%d", bi.biPlanes ); - qDebug( "biBitCount.......%d", bi.biBitCount ); - qDebug( "biCompression....%d", bi.biCompression ); - qDebug( "biSizeImage......%d", bi.biSizeImage ); - qDebug( "biXPelsPerMeter..%d", bi.biXPelsPerMeter ); - qDebug( "biYPelsPerMeter..%d", bi.biYPelsPerMeter ); - qDebug( "biClrUsed........%d", bi.biClrUsed ); - qDebug( "biClrImportant...%d", bi.biClrImportant ); -#endif - int w = bi.biWidth, h = bi.biHeight, nbits = bi.biBitCount; - int t = bi.biSize, comp = bi.biCompression; - int red_mask, green_mask, blue_mask; - int red_shift = 0; - int green_shift = 0; - int blue_shift = 0; - int red_scale = 0; - int green_scale = 0; - int blue_scale = 0; - - if ( !(nbits == 1 || nbits == 4 || nbits == 8 || nbits == 16 || nbits == 24 || nbits == 32) || - bi.biPlanes != 1 || comp > BMP_BITFIELDS ) - return FALSE; // weird BMP image - if ( !(comp == BMP_RGB || (nbits == 4 && comp == BMP_RLE4) || - (nbits == 8 && comp == BMP_RLE8) || ((nbits == 16 || nbits == 32) && comp == BMP_BITFIELDS)) ) - return FALSE; // weird compression type - - int ncols; - int depth; - switch ( nbits ) { - case 32: - case 24: - case 16: - depth = 32; - break; - case 8: - case 4: - depth = 8; - break; - default: - depth = 1; - } - if ( depth == 32 ) // there's no colormap - ncols = 0; - else // # colors used - ncols = bi.biClrUsed ? bi.biClrUsed : 1 << nbits; - - image.create( w, h, depth, ncols, nbits == 1 ? - TQImage::BigEndian : TQImage::IgnoreEndian ); - if ( image.isNull() ) // could not create image - return FALSE; - - image.setDotsPerMeterX( bi.biXPelsPerMeter ); - image.setDotsPerMeterY( bi.biYPelsPerMeter ); - - d->at( startpos + BMP_FILEHDR_SIZE + bi.biSize ); // goto start of colormap - - if ( ncols > 0 ) { // read color table - uchar rgb[4]; - int rgb_len = t == BMP_OLD ? 3 : 4; - for ( int i=0; ireadBlock( (char *)rgb, rgb_len ) != rgb_len ) - return FALSE; - image.setColor( i, tqRgb(rgb[2],rgb[1],rgb[0]) ); - if ( d->atEnd() ) // truncated file - return FALSE; - } - } else if (comp == BMP_BITFIELDS && (nbits == 16 || nbits == 32)) { - if ( (TQ_ULONG)d->readBlock( (char *)&red_mask, sizeof(red_mask) ) != sizeof(red_mask) ) - return FALSE; - if ( (TQ_ULONG)d->readBlock( (char *)&green_mask, sizeof(green_mask) ) != sizeof(green_mask) ) - return FALSE; - if ( (TQ_ULONG)d->readBlock( (char *)&blue_mask, sizeof(blue_mask) ) != sizeof(blue_mask) ) - return FALSE; - red_shift = calc_shift(red_mask); - red_scale = 256 / ((red_mask >> red_shift) + 1); - green_shift = calc_shift(green_mask); - green_scale = 256 / ((green_mask >> green_shift) + 1); - blue_shift = calc_shift(blue_mask); - blue_scale = 256 / ((blue_mask >> blue_shift) + 1); - } else if (comp == BMP_RGB && (nbits == 24 || nbits == 32)) { - blue_mask = 0x000000ff; - green_mask = 0x0000ff00; - red_mask = 0x00ff0000; - blue_shift = 0; - green_shift = 8; - red_shift = 16; - blue_scale = green_scale = red_scale = 1; - } else if (comp == BMP_RGB && nbits == 16) // don't support RGB values for 15/16 bpp - return FALSE; - - // offset can be bogus, be careful - if (offset>=0 && startpos + offset > (TQ_LONG)d->at() ) - d->at( startpos + offset ); // start of image data - - int bpl = image.bytesPerLine(); -#ifdef TQ_WS_TQWS - // - // Guess the number of bytes-per-line if we don't know how much - // image data is in the file (bogus image ?). - // - int bmpbpl = bi.biSizeImage > 0 ? - bi.biSizeImage / bi.biHeight : - (d->size() - offset) / bi.biHeight; - int pad = bmpbpl-bpl; -#endif - uchar **line = image.jumpTable(); - - if ( nbits == 1 ) { // 1 bit BMP image - while ( --h >= 0 ) { - if ( d->readBlock((char*)line[h],bpl) != bpl ) - break; -#ifdef TQ_WS_TQWS - if ( pad > 0 ) - d->at(d->at()+pad); -#endif - } - if ( ncols == 2 && tqGray(image.color(0)) < tqGray(image.color(1)) ) - swapPixel01( &image ); // pixel 0 is white! - } - - else if ( nbits == 4 ) { // 4 bit BMP image - int buflen = ((w+7)/8)*4; - uchar *buf = new uchar[buflen]; - TQ_CHECK_PTR( buf ); - if ( comp == BMP_RLE4 ) { // run length compression - int x=0, y=0, b, c, i; - register uchar *p = line[h-1]; - uchar *endp = line[h-1]+w; - while ( y < h ) { - if ( (b=d->getch()) == EOF ) - break; - if ( b == 0 ) { // escape code - switch ( (b=d->getch()) ) { - case 0: // end of line - x = 0; - y++; - p = line[h-y-1]; - break; - case 1: // end of image - case EOF: // end of file - y = h; // exit loop - break; - case 2: // delta (jump) - x += d->getch(); - y += d->getch(); - - // Protection - if ( (uint)x >= (uint)w ) - x = w-1; - if ( (uint)y >= (uint)h ) - y = h-1; - - p = line[h-y-1] + x; - break; - default: // absolute mode - // Protection - if ( p + b > endp ) - b = endp-p; - - i = (c = b)/2; - while ( i-- ) { - b = d->getch(); - *p++ = b >> 4; - *p++ = b & 0x0f; - } - if ( c & 1 ) - *p++ = d->getch() >> 4; - if ( (((c & 3) + 1) & 2) == 2 ) - d->getch(); // align on word boundary - x += c; - } - } else { // encoded mode - // Protection - if ( p + b > endp ) - b = endp-p; - - i = (c = b)/2; - b = d->getch(); // 2 pixels to be repeated - while ( i-- ) { - *p++ = b >> 4; - *p++ = b & 0x0f; - } - if ( c & 1 ) - *p++ = b >> 4; - x += c; - } - } - } else if ( comp == BMP_RGB ) { // no compression - while ( --h >= 0 ) { - if ( d->readBlock((char*)buf,buflen) != buflen ) - break; - register uchar *p = line[h]; - uchar *b = buf; - for ( int i=0; i> 4; - *p++ = *b++ & 0x0f; - } - if ( w & 1 ) // the last nibble - *p = *b >> 4; - } - } - delete [] buf; - } - - else if ( nbits == 8 ) { // 8 bit BMP image - if ( comp == BMP_RLE8 ) { // run length compression - int x=0, y=0, b; - register uchar *p = line[h-1]; - const uchar *endp = line[h-1]+w; - while ( y < h ) { - if ( (b=d->getch()) == EOF ) - break; - if ( b == 0 ) { // escape code - switch ( (b=d->getch()) ) { - case 0: // end of line - x = 0; - y++; - p = line[h-y-1]; - break; - case 1: // end of image - case EOF: // end of file - y = h; // exit loop - break; - case 2: // delta (jump) - x += d->getch(); - y += d->getch(); - - // Protection - if ( (uint)x >= (uint)w ) - x = w-1; - if ( (uint)y >= (uint)h ) - y = h-1; - - p = line[h-y-1] + x; - break; - default: // absolute mode - // Protection - if ( p + b > endp ) - b = endp-p; - - if ( d->readBlock( (char *)p, b ) != b ) - return FALSE; - if ( (b & 1) == 1 ) - d->getch(); // align on word boundary - x += b; - p += b; - } - } else { // encoded mode - // Protection - if ( p + b > endp ) - b = endp-p; - - memset( p, d->getch(), b ); // repeat pixel - x += b; - p += b; - } - } - } else if ( comp == BMP_RGB ) { // uncompressed - while ( --h >= 0 ) { - if ( d->readBlock((char *)line[h],bpl) != bpl ) - break; -#ifdef TQ_WS_TQWS - if ( pad > 0 ) - d->at(d->at()+pad); -#endif - } - } - } - - else if ( nbits == 16 || nbits == 24 || nbits == 32 ) { // 16,24,32 bit BMP image - register TQRgb *p; - TQRgb *end; - uchar *buf24 = new uchar[bpl]; - int bpl24 = ((w*nbits+31)/32)*4; - uchar *b; - int c; - - while ( --h >= 0 ) { - p = (TQRgb *)line[h]; - end = p + w; - if ( d->readBlock( (char *)buf24,bpl24) != bpl24 ) - break; - b = buf24; - while ( p < end ) { - c = *(uchar*)b | (*(uchar*)(b+1)<<8); - if (nbits != 16) - c |= *(uchar*)(b+2)<<16; - *p++ = tqRgb(((c & red_mask) >> red_shift) * red_scale, - ((c & green_mask) >> green_shift) * green_scale, - ((c & blue_mask) >> blue_shift) * blue_scale); - b += nbits/8; - } - } - delete[] buf24; - } - - return TRUE; -} - -bool qt_read_dib( TQDataStream& s, TQImage& image ) -{ - return read_dib(s,-1,-BMP_FILEHDR_SIZE,image); -} - - -static void read_bmp_image( TQImageIO *iio ) -{ - TQIODevice *d = iio->ioDevice(); - TQDataStream s( d ); - BMP_FILEHDR bf; - int startpos = d->at(); - - s.setByteOrder( TQDataStream::LittleEndian );// Intel byte order - s >> bf; // read BMP file header - - if ( tqstrncmp(bf.bfType,"BM",2) != 0 ) // not a BMP image - return; - - TQImage image; - if (read_dib( s, bf.bfOffBits, startpos, image )) { - iio->setImage( image ); - iio->setqStatus( 0 ); // image ok - } -} - -bool qt_write_dib( TQDataStream& s, TQImage image ) -{ - int nbits; - int bpl_bmp; - int bpl = image.bytesPerLine(); - - TQIODevice* d = s.tqdevice(); - - if ( image.depth() == 8 && image.numColors() <= 16 ) { - bpl_bmp = (((bpl+1)/2+3)/4)*4; - nbits = 4; - } else if ( image.depth() == 32 ) { - bpl_bmp = ((image.width()*24+31)/32)*4; - nbits = 24; -#ifdef TQ_WS_TQWS - } else if ( image.depth() == 1 || image.depth() == 8 ) { - // TQt/E doesn't word align. - bpl_bmp = ((image.width()*image.depth()+31)/32)*4; - nbits = image.depth(); -#endif - } else { - bpl_bmp = bpl; - nbits = image.depth(); - } - - BMP_INFOHDR bi; - bi.biSize = BMP_WIN; // build info header - bi.biWidth = image.width(); - bi.biHeight = image.height(); - bi.biPlanes = 1; - bi.biBitCount = nbits; - bi.biCompression = BMP_RGB; - bi.biSizeImage = bpl_bmp*image.height(); - bi.biXPelsPerMeter = image.dotsPerMeterX() ? image.dotsPerMeterX() - : 2834; // 72 dpi default - bi.biYPelsPerMeter = image.dotsPerMeterY() ? image.dotsPerMeterY() : 2834; - bi.biClrUsed = image.numColors(); - bi.biClrImportant = image.numColors(); - s << bi; // write info header - - if ( image.depth() != 32 ) { // write color table - uchar *color_table = new uchar[4*image.numColors()]; - uchar *rgb = color_table; - TQRgb *c = image.tqcolorTable(); - for ( int i=0; iwriteBlock( (char *)color_table, 4*image.numColors() ); - delete [] color_table; - } - - if ( image.depth() == 1 && image.bitOrder() != TQImage::BigEndian ) - image = image.convertBitOrder( TQImage::BigEndian ); - - int y; - - if ( nbits == 1 || nbits == 8 ) { // direct output -#ifdef TQ_WS_TQWS - // TQt/E doesn't word align. - int pad = bpl_bmp - bpl; - char padding[4]; -#endif - for ( y=image.height()-1; y>=0; y-- ) { - d->writeBlock( (char*)image.scanLine(y), bpl ); -#ifdef TQ_WS_TQWS - d->writeBlock( padding, pad ); -#endif - } - return TRUE; - } - - uchar *buf = new uchar[bpl_bmp]; - uchar *b, *end; - register uchar *p; - - memset( buf, 0, bpl_bmp ); - for ( y=image.height()-1; y>=0; y-- ) { // write the image bits - if ( nbits == 4 ) { // convert 8 -> 4 bits - p = image.scanLine(y); - b = buf; - end = b + image.width()/2; - while ( b < end ) { - *b++ = (*p << 4) | (*(p+1) & 0x0f); - p += 2; - } - if ( image.width() & 1 ) - *b = *p << 4; - } else { // 32 bits - TQRgb *p = (TQRgb *)image.scanLine( y ); - TQRgb *end = p + image.width(); - b = buf; - while ( p < end ) { - *b++ = tqBlue(*p); - *b++ = tqGreen(*p); - *b++ = tqRed(*p); - p++; - } - } - if ( bpl_bmp != d->writeBlock( (char*)buf, bpl_bmp ) ) { - delete[] buf; - return FALSE; - } - } - delete[] buf; - return TRUE; -} - - -static void write_bmp_image( TQImageIO *iio ) -{ - TQIODevice *d = iio->ioDevice(); - TQImage image = iio->image(); - TQDataStream s( d ); - BMP_FILEHDR bf; - int bpl_bmp; - int bpl = image.bytesPerLine(); - - // Code partially repeated in qt_write_dib - if ( image.depth() == 8 && image.numColors() <= 16 ) { - bpl_bmp = (((bpl+1)/2+3)/4)*4; - } else if ( image.depth() == 32 ) { - bpl_bmp = ((image.width()*24+31)/32)*4; - } else { - bpl_bmp = bpl; - } - - iio->setqStatus( 0 ); - s.setByteOrder( TQDataStream::LittleEndian );// Intel byte order - strncpy( bf.bfType, "BM", 2 ); // build file header - bf.bfReserved1 = bf.bfReserved2 = 0; // reserved, should be zero - bf.bfOffBits = BMP_FILEHDR_SIZE + BMP_WIN + image.numColors()*4; - bf.bfSize = bf.bfOffBits + bpl_bmp*image.height(); - s << bf; // write file header - - if ( !qt_write_dib( s, image ) ) - iio->setqStatus( 1 ); - -} - -#endif // TQT_NO_IMAGEIO_BMP - -#ifndef TQT_NO_IMAGEIO_PPM - -/***************************************************************************** - PBM/PGM/PPM (ASCII and RAW) image read/write functions - *****************************************************************************/ - -static int read_pbm_int( TQIODevice *d ) -{ - int c; - int val = -1; - bool digit; - const int buflen = 100; - char buf[buflen]; - for ( ;; ) { - if ( (c=d->getch()) == EOF ) // end of file - break; - digit = isdigit( (uchar) c ); - if ( val != -1 ) { - if ( digit ) { - val = 10*val + c - '0'; - continue; - } else { - if ( c == '#' ) // comment - d->readLine( buf, buflen ); - break; - } - } - if ( digit ) // first digit - val = c - '0'; - else if ( isspace((uchar) c) ) - continue; - else if ( c == '#' ) - d->readLine( buf, buflen ); - else - break; - } - return val; -} - -static void read_pbm_image( TQImageIO *iio ) // read PBM image data -{ - const int buflen = 300; - char buf[buflen]; - TQIODevice *d = iio->ioDevice(); - int w, h, nbits, mcc, y; - int pbm_bpl; - char type; - bool raw; - TQImage image; - - if ( d->readBlock( buf, 3 ) != 3 ) // read P[1-6] - return; - if ( !(buf[0] == 'P' && isdigit((uchar) buf[1]) && isspace((uchar) buf[2])) ) - return; - switch ( (type=buf[1]) ) { - case '1': // ascii PBM - case '4': // raw PBM - nbits = 1; - break; - case '2': // ascii PGM - case '5': // raw PGM - nbits = 8; - break; - case '3': // ascii PPM - case '6': // raw PPM - nbits = 32; - break; - default: - return; - } - raw = type >= '4'; - w = read_pbm_int( d ); // get image width - h = read_pbm_int( d ); // get image height - if ( nbits == 1 ) - mcc = 1; // ignore max color component - else - mcc = read_pbm_int( d ); // get max color component - if ( w <= 0 || w > 32767 || h <= 0 || h > 32767 || mcc <= 0 ) - return; // weird P.M image - - int maxc = mcc; - if ( maxc > 255 ) - maxc = 255; - image.create( w, h, nbits, 0, - nbits == 1 ? TQImage::BigEndian : TQImage::IgnoreEndian ); - if ( image.isNull() ) - return; - - pbm_bpl = (nbits*w+7)/8; // bytes per scanline in PBM - - if ( raw ) { // read raw data - if ( nbits == 32 ) { // type 6 - pbm_bpl = 3*w; - uchar *buf24 = new uchar[pbm_bpl], *b; - TQRgb *p; - TQRgb *end; - for ( y=0; yreadBlock( (char *)buf24, pbm_bpl ) != pbm_bpl ) { - delete[] buf24; - return; - } - p = (TQRgb *)image.scanLine( y ); - end = p + w; - b = buf24; - while ( p < end ) { - *p++ = tqRgb(b[0],b[1],b[2]); - b += 3; - } - } - delete[] buf24; - } else { // type 4,5 - for ( y=0; yreadBlock( (char *)image.scanLine(y), pbm_bpl ) - != pbm_bpl ) - return; - } - } - } else { // read ascii data - register uchar *p; - int n; - for ( y=0; ysetImage( image ); - iio->setqStatus( 0 ); // image ok -} - - -static void write_pbm_image( TQImageIO *iio ) -{ - TQIODevice* out = iio->ioDevice(); - TQCString str; - - TQImage image = iio->image(); - TQCString format = iio->format(); - format = format.left(3); // ignore RAW part - bool gray = format == "PGM"; - - if ( format == "PBM" ) { - image = image.convertDepth(1); - } else if ( image.depth() == 1 ) { - image = image.convertDepth(8); - } - - if ( image.depth() == 1 && image.numColors() == 2 ) { - if ( tqGray(image.color(0)) < tqGray(image.color(1)) ) { - // 0=dark/black, 1=light/white - invert - image.detach(); - for ( int y=0; ywriteBlock(str, str.length()) != str.length()) { - iio->setqStatus(1); - return; - } - w = (w+7)/8; - for (uint y=0; ywriteBlock((char*)line, w) ) { - iio->setqStatus(1); - return; - } - } - } - break; - - case 8: { - str.insert(1, gray ? '5' : '6'); - str.append("255\n"); - if ((uint)out->writeBlock(str, str.length()) != str.length()) { - iio->setqStatus(1); - return; - } - TQRgb *color = image.tqcolorTable(); - uint bpl = w*(gray ? 1 : 3); - uchar *buf = new uchar[bpl]; - for (uint y=0; ywriteBlock((char*)buf, bpl) ) { - iio->setqStatus(1); - return; - } - } - delete [] buf; - } - break; - - case 32: { - str.insert(1, gray ? '5' : '6'); - str.append("255\n"); - if ((uint)out->writeBlock(str, str.length()) != str.length()) { - iio->setqStatus(1); - return; - } - uint bpl = w*(gray ? 1 : 3); - uchar *buf = new uchar[bpl]; - for (uint y=0; ywriteBlock((char*)buf, bpl) ) { - iio->setqStatus(1); - return; - } - } - delete [] buf; - } - } - - iio->setqStatus(0); -} - -#endif // TQT_NO_IMAGEIO_PPM - -#ifndef TQT_NO_ASYNC_IMAGE_IO - -class TQImageIOFrameGrabber : public TQImageConsumer { -public: - TQImageIOFrameGrabber() : framecount(0) { } - - TQImageDecoder *decoder; - int framecount; - - void changed(const TQRect&) { } - void end() { } - void frameDone(const TQPoint&, const TQRect&) { framecount++; } - void frameDone() { framecount++; } - void setLooping(int) { } - void setFramePeriod(int) { } - void setSize(int, int) { } -}; - -static void read_async_image( TQImageIO *iio ) -{ - const int buf_len = 2048; - uchar buffer[buf_len]; - TQIODevice *d = iio->ioDevice(); - TQImageIOFrameGrabber* consumer = new TQImageIOFrameGrabber(); - TQImageDecoder *decoder = new TQImageDecoder(consumer); - consumer->decoder = decoder; - int startAt = d->at(); - int totLen = 0; - - for (;;) { - int length = d->readBlock((char*)buffer, buf_len); - if ( length <= 0 ) { - iio->setqStatus(length); - break; - } - uchar* b = buffer; - int r = -1; - while (length > 0 && consumer->framecount==0) { - r = decoder->decode(b, length); - if ( r <= 0 ) break; - b += r; - totLen += r; - length -= r; - } - if ( consumer->framecount ) { - // Stopped after first frame - if ( d->isDirectAccess() ) - d->at( startAt + totLen ); - else { - // ### We have (probably) read too much from the stream into - // the buffer, and there is no way to put it back! - } - iio->setImage(decoder->image()); - iio->setqStatus(0); - break; - } - if ( r <= 0 ) { - iio->setqStatus(r); - break; - } - } - - consumer->decoder = 0; - delete decoder; - delete consumer; -} - -#endif // TQT_NO_ASYNC_IMAGE_IO - -#ifndef TQT_NO_IMAGEIO_XBM - -/***************************************************************************** - X bitmap image read/write functions - *****************************************************************************/ - -static inline int hex2byte( register char *p ) -{ - return ( (isdigit((uchar) *p) ? *p - '0' : toupper((uchar) *p) - 'A' + 10) << 4 ) | - ( isdigit((uchar) *(p+1)) ? *(p+1) - '0' : toupper((uchar) *(p+1)) - 'A' + 10 ); -} - -static void read_xbm_image( TQImageIO *iio ) -{ - const int buflen = 300; - char buf[buflen]; - TQRegExp r1, r2; - TQIODevice *d = iio->ioDevice(); - int w=-1, h=-1; - TQImage image; - - r1 = TQString::tqfromLatin1("^#define[ \t]+[a-zA-Z0-9._]+[ \t]+"); - r2 = TQString::tqfromLatin1("[0-9]+"); - d->readLine( buf, buflen ); // "#define .._width " - - while (!d->atEnd() && buf[0] != '#') //skip leading comment, if any - d->readLine( buf, buflen ); - - TQString sbuf; - sbuf = TQString::tqfromLatin1(buf); - - if ( r1.search(sbuf) == 0 && - r2.search(sbuf, r1.matchedLength()) == r1.matchedLength() ) - w = atoi( &buf[r1.matchedLength()] ); - - d->readLine( buf, buflen ); // "#define .._height " - sbuf = TQString::tqfromLatin1(buf); - - if ( r1.search(sbuf) == 0 && - r2.search(sbuf, r1.matchedLength()) == r1.matchedLength() ) - h = atoi( &buf[r1.matchedLength()] ); - - if ( w <= 0 || w > 32767 || h <= 0 || h > 32767 ) - return; // format error - - for ( ;; ) { // scan for data - if ( d->readLine(buf, buflen) <= 0 ) // end of file - return; - if ( strstr(buf,"0x") != 0 ) // does line contain data? - break; - } - - image.create( w, h, 1, 2, TQImage::LittleEndian ); - if ( image.isNull() ) - return; - - image.setColor( 0, tqRgb(255,255,255) ); // white - image.setColor( 1, tqRgb(0,0,0) ); // black - - int x = 0, y = 0; - uchar *b = image.scanLine(0); - char *p = strstr( buf, "0x" ); - w = (w+7)/8; // byte width - - while ( y < h ) { // for all encoded bytes... - if ( p ) { // p = "0x.." - *b++ = hex2byte(p+2); - p += 2; - if ( ++x == w && ++y < h ) { - b = image.scanLine(y); - x = 0; - } - p = strstr( p, "0x" ); - } else { // read another line - if ( d->readLine(buf,buflen) <= 0 ) // EOF ==> truncated image - break; - p = strstr( buf, "0x" ); - } - } - - iio->setImage( image ); - iio->setqStatus( 0 ); // image ok -} - - -static void write_xbm_image( TQImageIO *iio ) -{ - TQIODevice *d = iio->ioDevice(); - TQImage image = iio->image(); - int w = image.width(); - int h = image.height(); - int i; - TQString s = fbname(iio->fileName()); // get file base name - char *buf = new char[s.length() + 100]; - - sprintf( buf, "#define %s_width %d\n", s.ascii(), w ); - d->writeBlock( buf, tqstrlen(buf) ); - sprintf( buf, "#define %s_height %d\n", s.ascii(), h ); - d->writeBlock( buf, tqstrlen(buf) ); - sprintf( buf, "static char %s_bits[] = {\n ", s.ascii() ); - d->writeBlock( buf, tqstrlen(buf) ); - - iio->setqStatus( 0 ); - - if ( image.depth() != 1 ) - image = image.convertDepth( 1 ); // dither - if ( image.bitOrder() != TQImage::LittleEndian ) - image = image.convertBitOrder( TQImage::LittleEndian ); - - bool invert = tqGray(image.color(0)) < tqGray(image.color(1)); - char hexrep[16]; - for ( i=0; i<10; i++ ) - hexrep[i] = '0' + i; - for ( i=10; i<16; i++ ) - hexrep[i] = 'a' -10 + i; - if ( invert ) { - char t; - for ( i=0; i<8; i++ ) { - t = hexrep[15-i]; - hexrep[15-i] = hexrep[i]; - hexrep[i] = t; - } - } - int bcnt = 0; - register char *p = buf; - int bpl = (w+7)/8; - for (int y = 0; y < h; ++y) { - uchar *b = image.scanLine(y); - for (i = 0; i < bpl; ++i) { - *p++ = '0'; *p++ = 'x'; - *p++ = hexrep[*b >> 4]; - *p++ = hexrep[*b++ & 0xf]; - - if ( i < bpl - 1 || y < h - 1 ) { - *p++ = ','; - if ( ++bcnt > 14 ) { - *p++ = '\n'; - *p++ = ' '; - *p = '\0'; - if ( (int)tqstrlen(buf) != d->writeBlock( buf, tqstrlen(buf) ) ) { - iio->setqStatus( 1 ); - delete [] buf; - return; - } - p = buf; - bcnt = 0; - } - } - } - } - strcpy( p, " };\n" ); - if ( (int)tqstrlen(buf) != d->writeBlock( buf, tqstrlen(buf) ) ) - iio->setqStatus( 1 ); - delete [] buf; -} - -#endif // TQT_NO_IMAGEIO_XBM - - -#ifndef TQT_NO_IMAGEIO_XPM - -/***************************************************************************** - XPM image read/write functions - *****************************************************************************/ - - -// Skip until ", read until the next ", return the rest in *buf -// Returns FALSE on error, TRUE on success - -static bool read_xpm_string( TQCString &buf, TQIODevice *d, - const char * const *source, int &index ) -{ - if ( source ) { - buf = source[index++]; - return TRUE; - } - - if ( buf.size() < 69 ) //# just an approximation - buf.resize( 123 ); - - buf[0] = '\0'; - int c; - int i; - while ( (c=d->getch()) != EOF && c != '"' ) { } - if ( c == EOF ) { - return FALSE; - } - i = 0; - while ( (c=d->getch()) != EOF && c != '"' ) { - if ( i == (int)buf.size() ) - buf.resize( i*2+42 ); - buf[i++] = c; - } - if ( c == EOF ) { - return FALSE; - } - - if ( i == (int)buf.size() ) // always use a 0 terminator - buf.resize( i+1 ); - buf[i] = '\0'; - return TRUE; -} - - - -static int nextColorSpec(const TQCString & buf) -{ - int i = buf.find(" c "); - if (i < 0) - i = buf.find(" g "); - if (i < 0) - i = buf.find(" g4 "); - if (i < 0) - i = buf.find(" m "); - if (i < 0) - i = buf.find(" s "); - return i; -} - -// -// INTERNAL -// -// Reads an .xpm from either the TQImageIO or from the TQString *. -// One of the two HAS to be 0, the other one is used. -// - -static void read_xpm_image_or_array( TQImageIO * iio, const char * const * source, - TQImage & image) -{ - TQCString buf; - TQIODevice *d = 0; - buf.resize( 200 ); - - int i, cpp, ncols, w, h, index = 0; - - if ( iio ) { - iio->setqStatus( 1 ); - d = iio ? iio->ioDevice() : 0; - d->readLine( buf.data(), buf.size() ); // "/* XPM */" - TQRegExp r( TQString::tqfromLatin1("/\\*.XPM.\\*/") ); - if ( buf.find(r) == -1 ) - return; // bad magic - } else if ( !source ) { - return; - } - - if ( !read_xpm_string( buf, d, source, index ) ) - return; - - if ( sscanf( buf, "%d %d %d %d", &w, &h, &ncols, &cpp ) < 4 ) - return; // < 4 numbers parsed - - if ( cpp > 15 ) - return; - - if ( ncols > 256 ) { - image.create( w, h, 32 ); - } else { - image.create( w, h, 8, ncols ); - } - - if (image.isNull()) - return; - - TQMap colorMap; - int currentColor; - - for( currentColor=0; currentColor < ncols; ++currentColor ) { - if ( !read_xpm_string( buf, d, source, index ) ) { -#if defined(TQT_CHECK_RANGE) - qWarning( "TQImage: XPM color specification missing"); -#endif - return; - } - TQString index; - index = buf.left( cpp ); - buf = buf.mid( cpp ).simplifyWhiteSpace().lower(); - buf.prepend( " " ); - i = nextColorSpec(buf); - if ( i < 0 ) { -#if defined(TQT_CHECK_RANGE) - qWarning( "TQImage: XPM color specification is missing: %s", buf.data()); -#endif - return; // no c/g/g4/m/s specification at all - } - buf = buf.mid( i+3 ); - // Strip any other colorspec - int end = nextColorSpec(buf); - if (end != -1) - buf.truncate(end); - buf = buf.stripWhiteSpace(); - if ( buf == "none" ) { - image.setAlphaBuffer( TRUE ); - int transparentColor = currentColor; - if ( image.depth() == 8 ) { - image.setColor( transparentColor, - TQRGB_MASK & tqRgb(198,198,198) ); - colorMap.insert( index, transparentColor ); - } else { - TQRgb rgb = TQRGB_MASK & tqRgb(198,198,198); - colorMap.insert( index, rgb ); - } - } else { - if ( ((buf.length()-1) % 3) && (buf[0] == '#') ) { - buf.truncate (((buf.length()-1) / 4 * 3) + 1); // remove alpha channel left by imagemagick - } - TQColor c( buf.data() ); - if ( image.depth() == 8 ) { - image.setColor( currentColor, 0xff000000 | c.rgb() ); - colorMap.insert( index, currentColor ); - } else { - TQRgb rgb = 0xff000000 | c.rgb(); - colorMap.insert( index, rgb ); - } - } - } - - // Read pixels - for( int y=0; ysetImage( image ); - iio->setqStatus( 0 ); // image ok - } -} - - -static void read_xpm_image( TQImageIO * iio ) -{ - TQImage i; - (void)read_xpm_image_or_array( iio, 0, i ); - return; -} - - -static const char* xpm_color_name( int cpp, int index ) -{ - static char returnable[5]; - static const char code[] = ".#abcdefghijklmnopqrstuvwxyzABCD" - "EFGHIJKLMNOPQRSTUVWXYZ0123456789"; - // cpp is limited to 4 and index is limited to 64^cpp - if ( cpp > 1 ) { - if ( cpp > 2 ) { - if ( cpp > 3 ) { - returnable[3] = code[index % 64]; - index /= 64; - } else - returnable[3] = '\0'; - returnable[2] = code[index % 64]; - index /= 64; - } else - returnable[2] = '\0'; - // the following 4 lines are a joke! - if ( index == 0 ) - index = 64*44+21; - else if ( index == 64*44+21 ) - index = 0; - returnable[1] = code[index % 64]; - index /= 64; - } else - returnable[1] = '\0'; - returnable[0] = code[index]; - - return returnable; -} - - -// write XPM image data -static void write_xpm_image( TQImageIO * iio ) -{ - if ( iio ) - iio->setqStatus( 1 ); - else - return; - - // ### 8-bit case could be made faster - TQImage image; - if ( iio->image().depth() != 32 ) - image = iio->image().convertDepth( 32 ); - else - image = iio->image(); - - TQMap colorMap; - - int w = image.width(), h = image.height(), ncolors = 0; - int x, y; - - // build color table - for( y=0; y k; k *= 64 ) { - ++cpp; - // limit to 4 characters per pixel - // 64^4 colors is enough for a 4096x4096 image - if ( cpp > 4) - break; - } - - TQString line; - - // write header - TQTextStream s( iio->ioDevice() ); - s << "/* XPM */" << endl - << "static char *" << fbname(iio->fileName()) << "[]={" << endl - << "\"" << w << " " << h << " " << ncolors << " " << cpp << "\""; - - // write palette - TQMap::Iterator c = colorMap.begin(); - while ( c != colorMap.end() ) { - TQRgb color = c.key(); - if ( image.hasAlphaBuffer() && color == (color & TQRGB_MASK) ) - line.sprintf( "\"%s c None\"", - xpm_color_name(cpp, *c) ); - else - line.sprintf( "\"%s c #%02x%02x%02x\"", - xpm_color_name(cpp, *c), - tqRed(color), - tqGreen(color), - tqBlue(color) ); - ++c; - s << "," << endl << line; - } - - // write pixels, limit to 4 characters per pixel - line.truncate( cpp*w ); - for( y=0; y 1 ) { - line[cc++] = chars[1]; - if ( cpp > 2 ) { - line[cc++] = chars[2]; - if ( cpp > 3 ) { - line[cc++] = chars[3]; - } - } - } - } - s << "," << endl << "\"" << line << "\""; - } - s << "};" << endl; - - iio->setqStatus( 0 ); -} - -#endif // TQT_NO_IMAGEIO_XPM -#endif //TQT_NO_IMAGEIO -#endif - -// table to flip bits -static const uchar bitflip[256] = { - /* - open OUT, "| fmt"; - for $i (0..255) { - print OUT (($i >> 7) & 0x01) | (($i >> 5) & 0x02) | - (($i >> 3) & 0x04) | (($i >> 1) & 0x08) | - (($i << 7) & 0x80) | (($i << 5) & 0x40) | - (($i << 3) & 0x20) | (($i << 1) & 0x10), ", "; - } - close OUT; - */ - 0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240, - 8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248, - 4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244, - 12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252, - 2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242, - 10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250, - 6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246, - 14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254, - 1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241, - 9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249, - 5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245, - 13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253, - 3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243, - 11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251, - 7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247, - 15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255 -}; - -/*! - Converts the bit order of the image to the given \a bitOrder and - returns the converted image. The original image is not changed. - Returns this image if the given \a bitOrder is equal to the image - current bit order, or a null image if this image cannot be - converted. - - Use convertToFormat() instead. -*/ - -TQImage TQImage::convertBitOrder(Endian bitOrder) const -{ - if (isNull() || depth() != 1 || !(bitOrder == BigEndian || bitOrder == LittleEndian)) - return QImage(); - - if ((format() == Format_Mono && bitOrder == BigEndian) - || (format() == Format_MonoLSB && bitOrder == LittleEndian)) - return *this; - - TQImage image(width(), height(), format() == Format_Mono ? Format_MonoLSB : Format_Mono); - - const uchar *data = bits(); - const uchar *end = data + byteCount(); - uchar *ndata = image.bits(); - while (data < end) - *ndata++ = bitflip[*data++]; - - image.setDotsPerMeterX(dotsPerMeterX()); - image.setDotsPerMeterY(dotsPerMeterY()); - - image.setColorTable(colorTable()); - return image; -} - -TQImage::Endian TQImage::systemBitOrder() { -#if defined(Q_WS_X11) - return BitmapBitOrder(QX11Info::display()) == MSBFirst ? BigEndian : LittleEndian; -#else - return BigEndian; -#endif -} - -/*! - \fn TQImage TQImage::convertDepthWithPalette(int depth, QRgb* palette, int palette_count, Qt::ImageConversionFlags flags) const - - Returns an image with the given \a depth, using the \a - palette_count colors pointed to by \a palette. If \a depth is 1 or - 8, the returned image will have its color table ordered in the - same way as \a palette. - - If the image needs to be modified to fit in a lower-resolution - result (e.g. converting from 32-bit to 8-bit), use the \a flags to - specify how you'd prefer this to happen. - - Note: currently no closest-color search is made. If colors are - found that are not in the palette, the palette may not be used at - all. This result should not be considered valid because it may - change in future implementations. - - Currently inefficient for non-32-bit images. - - Use the convertToFormat() function in combination with the - setColorTable() function instead. -*/ -TQImage TQImage::convertDepthWithPalette(int d, QRgb* palette, int palette_count, Qt::ImageConversionFlags flags) const -{ - Format f = const_cast(this)->formatFor(d, TQImage::LittleEndian); - QVector colortable; - for (int i = 0; i < palette_count; ++i) - colortable.append(palette[i]); - return convertToFormat(f, colortable, flags); -} - -#ifndef TQT_NO_IMAGE_HEURISTIC_MASK -TQImage TQImage::createHeuristicMask( bool clipTight ) const { - return TQImage(QImage::createHeuristicMask(clipTight)); -} -#endif - -#else // USE_QT4 - -// 16bpp images on supported on TQt/Embedded -#if !defined( TQ_WS_TQWS ) && !defined(TQT_NO_IMAGE_16_BIT) -#define TQT_NO_IMAGE_16_BIT -#endif - - -/*! - \class TQImage - \brief The TQImage class provides a hardware-independent pixmap - representation with direct access to the pixel data. - - \ingroup images - \ingroup graphics - \ingroup shared - \mainclass - - It is one of the two classes TQt provides for dealing with images, - the other being TQPixmap. TQImage is designed and optimized for I/O - and for direct pixel access/manipulation. TQPixmap is designed and - optimized for drawing. There are (slow) functions to convert - between TQImage and TQPixmap: TQPixmap::convertToImage() and - TQPixmap::convertFromImage(). - - An image has the parameters \link width() width\endlink, \link - height() height\endlink and \link depth() depth\endlink (bits per - pixel, bpp), a color table and the actual \link bits() - pixels\endlink. TQImage supports 1-bpp, 8-bpp and 32-bpp image - data. 1-bpp and 8-bpp images use a color lookup table; the pixel - value is a color table index. - - 32-bpp images encode an RGB value in 24 bits and ignore the color - table. The most significant byte is used for the \link - setAlphaBuffer() alpha buffer\endlink. - - An entry in the color table is an RGB triplet encoded as a \c - uint. Use the \link ::tqRed() tqRed()\endlink, \link ::tqGreen() - tqGreen()\endlink and \link ::tqBlue() tqBlue()\endlink functions (\c - tqcolor.h) to access the components, and \link ::tqRgb() - tqRgb\endlink to make an RGB triplet (see the TQColor class - documentation). - - 1-bpp (monochrome) images have a color table with a most two - colors. There are two different formats: big endian (MSB first) or - little endian (LSB first) bit order. To access a single bit you - will must do some bit shifts: - - \code - TQImage image; - // sets bit at (x,y) to 1 - if ( image.bitOrder() == TQImage::LittleEndian ) - *(image.scanLine(y) + (x >> 3)) |= 1 << (x & 7); - else - *(image.scanLine(y) + (x >> 3)) |= 1 << (7 - (x & 7)); - \endcode - - If this looks complicated, it might be a good idea to convert the - 1-bpp image to an 8-bpp image using convertDepth(). - - 8-bpp images are much easier to work with than 1-bpp images - because they have a single byte per pixel: - - \code - TQImage image; - // set entry 19 in the color table to yellow - image.setColor( 19, tqRgb(255,255,0) ); - // set 8 bit pixel at (x,y) to value yellow (in color table) - *(image.scanLine(y) + x) = 19; - \endcode - - 32-bpp images ignore the color table; instead, each pixel contains - the RGB triplet. 24 bits contain the RGB value; the most - significant byte is reserved for the alpha buffer. - - \code - TQImage image; - // sets 32 bit pixel at (x,y) to yellow. - uint *p = (uint *)image.scanLine(y) + x; - *p = tqRgb(255,255,0); - \endcode - - On TQt/Embedded, scanlines are aligned to the pixel depth and may - be padded to any degree, while on all other platforms, the - scanlines are 32-bit aligned for all depths. The constructor - taking a \c{uchar*} argument always expects 32-bit aligned data. - On TQt/Embedded, an additional constructor allows the number of - bytes-per-line to be specified. - - TQImage supports a variety of methods for getting information about - the image, for example, colorTable(), allGray(), isGrayscale(), - bitOrder(), bytesPerLine(), depth(), dotsPerMeterX() and - dotsPerMeterY(), hasAlphaBuffer(), numBytes(), numColors(), and - width() and height(). - - Pixel colors are retrieved with pixel() and set with setPixel(). - - TQImage also supports a number of functions for creating a new - image that is a transformed version of the original. For example, - copy(), convertBitOrder(), convertDepth(), createAlphaMask(), - createHeuristicMask(), mirror(), scale(), smoothScale(), swapRGB() - and xForm(). There are also functions for changing attributes of - an image in-place, for example, setAlphaBuffer(), setColor(), - setDotsPerMeterX() and setDotsPerMeterY() and setNumColors(). - - Images can be loaded and saved in the supported formats. Images - are saved to a file with save(). Images are loaded from a file - with load() (or in the constructor) or from an array of data with - loadFromData(). The lists of supported formats are available from - inputFormatList() and outputFormatList(). - - Strings of text may be added to images using setText(). - - The TQImage class uses explicit \link shclass.html sharing\endlink, - similar to that used by TQMemArray. - - New image formats can be added as \link plugins-howto.html - plugins\endlink. - - \sa TQImageIO TQPixmap \link shclass.html Shared Classes\endlink -*/ - - -/*! - \enum TQImage::Endian - - This enum type is used to describe the endianness of the CPU and - graphics hardware. - - \value IgnoreEndian Endianness does not matter. Useful for some - operations that are independent of endianness. - \value BigEndian Network byte order, as on SPARC and Motorola CPUs. - \value LittleEndian PC/Alpha byte order. -*/ - -/*! - \enum TQt::ImageConversionFlags - - The conversion flag is a bitwise-OR of the following values. The - options marked "(default)" are set if no other values from the - list are included (since the defaults are zero): - - Color/Mono preference (ignored for TQBitmap) - \value AutoColor (default) - If the image has \link - TQImage::depth() depth\endlink 1 and contains only - black and white pixels, the pixmap becomes monochrome. - \value ColorOnly The pixmap is dithered/converted to the - \link TQPixmap::defaultDepth() native display depth\endlink. - \value MonoOnly The pixmap becomes monochrome. If necessary, - it is dithered using the chosen dithering algorithm. - - Dithering mode preference for RGB channels - \value DiffuseDither (default) - A high-quality dither. - \value OrderedDither A faster, more ordered dither. - \value ThresholdDither No dithering; closest color is used. - - Dithering mode preference for alpha channel - \value ThresholdAlphaDither (default) - No dithering. - \value OrderedAlphaDither A faster, more ordered dither. - \value DiffuseAlphaDither A high-quality dither. - \value NoAlpha Not supported. - - Color matching versus dithering preference - \value PreferDither (default when converting to a pixmap) - Always dither - 32-bit images when the image is converted to 8 bits. - \value AvoidDither (default when converting for the purpose of saving to - file) - Dither 32-bit images only if the image has more than 256 - colors and it is being converted to 8 bits. - \value AutoDither Not supported. - - The following are not values that are used directly, but masks for - the above classes: - \value ColorMode_Mask Mask for the color mode. - \value Dither_Mask Mask for the dithering mode for RGB channels. - \value AlphaDither_Mask Mask for the dithering mode for the alpha channel. - \value DitherMode_Mask Mask for the mode that determines the preference of - color matching versus dithering. - - Using 0 as the conversion flag sets all the default options. -*/ - -#if defined(TQ_CC_DEC) && defined(__alpha) && (__DECCXX_VER-0 >= 50190001) -#pragma message disable narrowptr -#endif - -#ifndef TQT_NO_IMAGE_TEXT -class TQImageDataMisc { -public: - TQImageDataMisc() { } - TQImageDataMisc( const TQImageDataMisc& o ) : - text_lang(o.text_lang) { } - - TQImageDataMisc& operator=(const TQImageDataMisc& o) - { - text_lang = o.text_lang; - return *this; - } - TQValueList list() - { - return text_lang.keys(); - } - - TQStringList languages() - { - TQStringList r; - TQMap::Iterator it = text_lang.begin(); - for ( ; it != text_lang.end(); ++it ) { - r.remove( it.key().lang ); - r.append( it.key().lang ); - } - return r; - } - TQStringList keys() - { - TQStringList r; - TQMap::Iterator it = text_lang.begin(); - for ( ; it != text_lang.end(); ++it ) { - r.remove( it.key().key ); - r.append( it.key().key ); - } - return r; - } - - TQMap text_lang; -}; -#endif // TQT_NO_IMAGE_TEXT - - - -/***************************************************************************** - TQImage member functions - *****************************************************************************/ - -// table to flip bits -static const uchar bitflip[256] = { - /* - open OUT, "| fmt"; - for $i (0..255) { - print OUT (($i >> 7) & 0x01) | (($i >> 5) & 0x02) | - (($i >> 3) & 0x04) | (($i >> 1) & 0x08) | - (($i << 7) & 0x80) | (($i << 5) & 0x40) | - (($i << 3) & 0x20) | (($i << 1) & 0x10), ", "; - } - close OUT; - */ - 0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240, - 8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248, - 4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244, - 12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252, - 2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242, - 10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250, - 6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246, - 14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254, - 1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241, - 9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249, - 5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245, - 13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253, - 3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243, - 11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251, - 7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247, - 15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255 -}; - -const uchar *qt_get_bitflip_array() // called from TQPixmap code -{ - return bitflip; -} - - -/*! - Constructs a null image. - - \sa isNull() -*/ - -TQImage::TQImage() -{ - init(); -} - -/*! - Constructs an image with \a w width, \a h height, \a depth bits - per pixel, \a numColors colors and bit order \a bitOrder. - - Using this constructor is the same as first constructing a null - image and then calling the create() function. - - \sa create() -*/ - -TQImage::TQImage( int w, int h, int depth, int numColors, Endian bitOrder ) -{ - init(); - create( w, h, depth, numColors, bitOrder ); -} - -/*! - Constructs an image with size \a size pixels, depth \a depth bits, - \a numColors and \a bitOrder endianness. - - Using this constructor is the same as first constructing a null - image and then calling the create() function. - - \sa create() -*/ -TQImage::TQImage( const TQSize& size, int depth, int numColors, Endian bitOrder ) -{ - init(); - create( size, depth, numColors, bitOrder ); -} - -#ifndef TQT_NO_IMAGEIO -/*! - Constructs an image and tries to load the image from the file \a - fileName. - - If \a format is specified, the loader attempts to read the image - using the specified format. If \a format is not specified (which - is the default), the loader reads a few bytes from the header to - guess the file format. - - If the loading of the image failed, this object is a \link - isNull() null\endlink image. - - The TQImageIO documentation lists the supported image formats and - explains how to add extra formats. - - \sa load() isNull() TQImageIO -*/ - -TQImage::TQImage( const TQString &fileName, const char* format ) -{ - init(); - load( fileName, format ); -} - -#ifndef TQT_NO_IMAGEIO_XPM -// helper -static void read_xpm_image_or_array( TQImageIO *, const char * const *, TQImage & ); -#endif -/*! - Constructs an image from \a xpm, which must be a valid XPM image. - - Errors are silently ignored. - - Note that it's possible to squeeze the XPM variable a little bit - by using an unusual declaration: - - \code - static const char * const start_xpm[]={ - "16 15 8 1", - "a c #cec6bd", - .... - \endcode - - The extra \c const makes the entire definition read-only, which is - slightly more efficient (e.g. when the code is in a shared - library) and ROMable when the application is to be stored in ROM. -*/ - -TQImage::TQImage( const char * const xpm[] ) -{ - init(); -#ifndef TQT_NO_IMAGEIO_XPM - read_xpm_image_or_array( 0, xpm, *this ); -#else - // We use a qFatal rather than disabling the whole function, as this - // constructor may be ambiguous. - qFatal("XPM not supported"); -#endif -} - -/*! - Constructs an image from the binary data \a array. It tries to - guess the file format. - - If the loading of the image failed, this object is a \link - isNull() null\endlink image. - - \sa loadFromData() isNull() imageFormat() -*/ -TQImage::TQImage( const TQByteArray &array ) -{ - init(); - loadFromData(array); -} -#endif //TQT_NO_IMAGEIO - - -/*! - Constructs a \link shclass.html shallow copy\endlink of \a image. -*/ - -TQImage::TQImage( const TQImage &image ) -{ - data = image.data; - data->ref(); -} - -/*! - Constructs an image \a w pixels wide, \a h pixels high with a - color depth of \a depth, that uses an existing memory buffer, \a - yourdata. The buffer must remain valid throughout the life of the - TQImage. The image does not delete the buffer at destruction. - - If \a colortable is 0, a color table sufficient for \a numColors - will be allocated (and destructed later). - - Note that \a yourdata must be 32-bit aligned. - - The endianness is given in \a bitOrder. -*/ -TQImage::TQImage( uchar* yourdata, int w, int h, int depth, - TQRgb* colortable, int numColors, - Endian bitOrder ) -{ - init(); - int bpl = ((w*depth+31)/32)*4; // bytes per scanline - if ( w <= 0 || h <= 0 || depth <= 0 || numColors < 0 - || INT_MAX / sizeof(uchar *) < uint(h) - || INT_MAX / uint(depth) < uint(w) - || bpl <= 0 - || INT_MAX / uint(bpl) < uint(h) ) - return; // invalid parameter(s) - data->w = w; - data->h = h; - data->d = depth; - data->ncols = depth != 32 ? numColors : 0; - if ( !yourdata ) - return; // Image header info can be saved without needing to allocate memory. - data->nbytes = bpl*h; - if ( colortable || !data->ncols ) { - data->ctbl = colortable; - data->ctbl_mine = FALSE; - } else { - // calloc since we realloc, etc. later (ick) - data->ctbl = (TQRgb*)calloc( data->ncols*sizeof(TQRgb), data->ncols ); - TQ_CHECK_PTR(data->ctbl); - data->ctbl_mine = TRUE; - } - uchar** jt = (uchar**)malloc(h*sizeof(uchar*)); - TQ_CHECK_PTR(jt); - for (int j=0; jbits = jt; - data->bitordr = bitOrder; -} - -#ifdef TQ_WS_TQWS - -/*! - Constructs an image that uses an existing memory buffer. The - buffer must remain valid for the life of the TQImage. The image - does not delete the buffer at destruction. The buffer is passed as - \a yourdata. The image's width is \a w and its height is \a h. The - color depth is \a depth. \a bpl specifies the number of bytes per - line. - - If \a colortable is 0, a color table sufficient for \a numColors - will be allocated (and destructed later). - - The endianness is specified by \a bitOrder. - - \warning This constructor is only available on TQt/Embedded. -*/ -TQImage::TQImage( uchar* yourdata, int w, int h, int depth, - int bpl, TQRgb* colortable, int numColors, - Endian bitOrder ) -{ - init(); - if ( !yourdata || w <= 0 || h <= 0 || depth <= 0 || numColors < 0 - || INT_MAX / sizeof(uchar *) < uint(h) - || INT_MAX / uint(bpl) < uint(h) - ) - return; // invalid parameter(s) - data->w = w; - data->h = h; - data->d = depth; - data->ncols = numColors; - data->nbytes = bpl * h; - if ( colortable || !numColors ) { - data->ctbl = colortable; - data->ctbl_mine = FALSE; - } else { - // calloc since we realloc, etc. later (ick) - data->ctbl = (TQRgb*)calloc( numColors*sizeof(TQRgb), numColors ); - TQ_CHECK_PTR(data->ctbl); - data->ctbl_mine = TRUE; - } - uchar** jt = (uchar**)malloc(h*sizeof(uchar*)); - TQ_CHECK_PTR(jt); - for (int j=0; jbits = jt; - data->bitordr = bitOrder; -} -#endif // TQ_WS_TQWS - -/*! - Destroys the image and cleans up. -*/ - -TQImage::~TQImage() -{ - if ( data && data->deref() ) { - reset(); - delete data; - } -} - - - - -/*! Convenience function. Gets the data associated with the absolute - name \a abs_name from the default mime source factory and decodes it - to an image. - - \sa TQMimeSourceFactory, TQImage::fromMimeSource(), TQImageDrag::decode() -*/ -#ifndef TQT_NO_MIME -TQImage TQImage::fromMimeSource( const TQString &abs_name ) -{ - const TQMimeSource *m = TQMimeSourceFactory::defaultFactory()->data( abs_name ); - if ( !m ) { -#if defined(TQT_CHECK_STATE) - qWarning("TQImage::fromMimeSource: Cannot find image \"%s\" in the mime source factory", abs_name.latin1() ); -#endif - return TQImage(); - } - TQImage img; - TQImageDrag::decode( m, img ); - return img; -} -#endif - - -/*! - Assigns a \link shclass.html shallow copy\endlink of \a image to - this image and returns a reference to this image. - - \sa copy() -*/ - -TQImage &TQImage::operator=( const TQImage &image ) -{ - image.data->ref(); // avoid 'x = x' - if ( data->deref() ) { - reset(); - delete data; - } - data = image.data; - return *this; -} - -/*! - \overload - - Sets the image bits to the \a pixmap contents and returns a - reference to the image. - - If the image shares data with other images, it will first - dereference the shared data. - - Makes a call to TQPixmap::convertToImage(). -*/ - -TQImage &TQImage::operator=( const TQPixmap &pixmap ) -{ - *this = pixmap.convertToImage(); - return *this; -} - -/*! - Detaches from shared image data and makes sure that this image is - the only one referring to the data. - - If multiple images share common data, this image makes a copy of - the data and detaches itself from the sharing mechanism. - Nothing is done if there is just a single reference. - - \sa copy() -*/ - -void TQImage::detach() -{ - if ( data->count != 1 ) - *this = copy(); -} - -/*! - Returns a \link shclass.html deep copy\endlink of the image. - - \sa detach() -*/ - -TQImage TQImage::copy() const -{ - if ( isNull() ) { - // maintain the fields of invalid TQImages when copied - return TQImage( 0, width(), height(), depth(), colorTable(), numColors(), bitOrder() ); - } else { - TQImage image; - image.create( width(), height(), depth(), numColors(), bitOrder() ); -#ifdef TQ_WS_TQWS - // TQt/Embedded can create images with non-default bpl - // make sure we don't crash. - if ( image.numBytes() != numBytes() ) - for ( int i = 0; i < height(); i++ ) - memcpy( image.scanLine(i), scanLine(i), image.bytesPerLine() ); - else -#endif - memcpy( image.bits(), bits(), numBytes() ); - memcpy( image.colorTable(), colorTable(), numColors() * sizeof(TQRgb) ); - image.setAlphaBuffer( hasAlphaBuffer() ); - image.data->dpmx = dotsPerMeterX(); - image.data->dpmy = dotsPerMeterY(); - image.data->offset = offset(); -#ifndef TQT_NO_IMAGE_TEXT - if ( data->misc ) { - image.data->misc = new TQImageDataMisc; - *image.data->misc = misc(); - } -#endif - return image; - } -} - -/*! - \overload - - Returns a \link shclass.html deep copy\endlink of a sub-area of - the image. - - The returned image is always \a w by \a h pixels in size, and is - copied from position \a x, \a y in this image. In areas beyond - this image pixels are filled with pixel 0. - - If the image needs to be modified to fit in a lower-resolution - result (e.g. converting from 32-bit to 8-bit), use the \a - conversion_flags to specify how you'd prefer this to happen. - - \sa bitBlt() TQt::ImageConversionFlags -*/ - -TQImage TQImage::copy(int x, int y, int w, int h, int conversion_flags) const -{ - int dx = 0; - int dy = 0; - if ( w <= 0 || h <= 0 ) return TQImage(); // Nothing to copy - - TQImage image( w, h, depth(), numColors(), bitOrder() ); - - if ( x < 0 || y < 0 || x + w > width() || y + h > height() ) { - // bitBlt will not cover entire image - clear it. - // ### should deal with each side separately for efficiency - image.fill(0); - if ( x < 0 ) { - dx = -x; - x = 0; - } - if ( y < 0 ) { - dy = -y; - y = 0; - } - } - - bool has_alpha = hasAlphaBuffer(); - if ( has_alpha ) { - // alpha channel should be only copied, not used by bitBlt(), and - // this is mutable, we will restore the image state before returning - TQImage *that = (TQImage *) this; - that->setAlphaBuffer( FALSE ); - } - memcpy( image.colorTable(), colorTable(), numColors()*sizeof(TQRgb) ); - bitBlt( &image, dx, dy, this, x, y, -1, -1, conversion_flags ); - if ( has_alpha ) { - // restore image state - TQImage *that = (TQImage *) this; - that->setAlphaBuffer( TRUE ); - } - image.setAlphaBuffer(hasAlphaBuffer()); - image.data->dpmx = dotsPerMeterX(); - image.data->dpmy = dotsPerMeterY(); - image.data->offset = offset(); -#ifndef TQT_NO_IMAGE_TEXT - if ( data->misc ) { - image.data->misc = new TQImageDataMisc; - *image.data->misc = misc(); - } -#endif - return image; -} - -/*! - \overload TQImage TQImage::copy(const TQRect& r) const - - Returns a \link shclass.html deep copy\endlink of a sub-area of - the image. - - The returned image always has the size of the rectangle \a r. In - areas beyond this image pixels are filled with pixel 0. -*/ - -/*! - \fn bool TQImage::isNull() const - - Returns TRUE if it is a null image; otherwise returns FALSE. - - A null image has all parameters set to zero and no allocated data. -*/ - - -/*! - \fn int TQImage::width() const - - Returns the width of the image. - - \sa height() size() rect() -*/ - -/*! - \fn int TQImage::height() const - - Returns the height of the image. - - \sa width() size() rect() -*/ - -/*! - \fn TQSize TQImage::size() const - - Returns the size of the image, i.e. its width and height. - - \sa width() height() rect() -*/ - -/*! - \fn TQRect TQImage::rect() const - - Returns the enclosing rectangle (0, 0, width(), height()) of the - image. - - \sa width() height() size() -*/ - -/*! - \fn int TQImage::depth() const - - Returns the depth of the image. - - The image depth is the number of bits used to encode a single - pixel, also called bits per pixel (bpp) or bit planes of an image. - - The supported depths are 1, 8, 16 (TQt/Embedded only) and 32. - - \sa convertDepth() -*/ - -/*! - \fn int TQImage::numColors() const - - Returns the size of the color table for the image. - - Notice that numColors() returns 0 for 16-bpp (TQt/Embedded only) - and 32-bpp images because these images do not use color tables, - but instead encode pixel values as RGB triplets. - - \sa setNumColors() colorTable() -*/ - -/*! - \fn TQImage::Endian TQImage::bitOrder() const - - Returns the bit order for the image. - - If it is a 1-bpp image, this function returns either - TQImage::BigEndian or TQImage::LittleEndian. - - If it is not a 1-bpp image, this function returns - TQImage::IgnoreEndian. - - \sa depth() -*/ - -/*! - \fn uchar **TQImage::jumpTable() const - - Returns a pointer to the scanline pointer table. - - This is the beginning of the data block for the image. - - \sa bits() scanLine() -*/ - -/*! - \fn TQRgb *TQImage::colorTable() const - - Returns a pointer to the color table. - - \sa numColors() -*/ - -/*! - \fn int TQImage::numBytes() const - - Returns the number of bytes occupied by the image data. - - \sa bytesPerLine() bits() -*/ - -/*! - \fn int TQImage::bytesPerLine() const - - Returns the number of bytes per image scanline. This is equivalent - to numBytes()/height(). - - \sa numBytes() scanLine() -*/ - -/*! - \fn TQRgb TQImage::color( int i ) const - - Returns the color in the color table at index \a i. The first - color is at index 0. - - A color value is an RGB triplet. Use the \link ::tqRed() - tqRed()\endlink, \link ::tqGreen() tqGreen()\endlink and \link - ::tqBlue() tqBlue()\endlink functions (defined in \c tqcolor.h) to - get the color value components. - - \sa setColor() numColors() TQColor -*/ - -/*! - \fn void TQImage::setColor( int i, TQRgb c ) - - Sets a color in the color table at index \a i to \a c. - - A color value is an RGB triplet. Use the \link ::tqRgb() - tqRgb()\endlink function (defined in \c tqcolor.h) to make RGB - triplets. - - \sa color() setNumColors() numColors() -*/ - -/*! - \fn uchar *TQImage::scanLine( int i ) const - - Returns a pointer to the pixel data at the scanline with index \a - i. The first scanline is at index 0. - - The scanline data is aligned on a 32-bit boundary. - - \warning If you are accessing 32-bpp image data, cast the returned - pointer to \c{TQRgb*} (TQRgb has a 32-bit size) and use it to - read/write the pixel value. You cannot use the \c{uchar*} pointer - directly, because the pixel format depends on the byte order on - the underlying platform. Hint: use \link ::tqRed() tqRed()\endlink, - \link ::tqGreen() tqGreen()\endlink and \link ::tqBlue() - tqBlue()\endlink, etc. (tqcolor.h) to access the pixels. - - \warning If you are accessing 16-bpp image data, you must handle - endianness yourself. (TQt/Embedded only) - - \sa bytesPerLine() bits() jumpTable() -*/ - -/*! - \fn uchar *TQImage::bits() const - - Returns a pointer to the first pixel data. This is equivalent to - scanLine(0). - - \sa numBytes() scanLine() jumpTable() -*/ - - - -void TQImage::warningIndexRange( const char *func, int i ) -{ -#if defined(TQT_CHECK_RANGE) - qWarning( "TQImage::%s: Index %d out of range", func, i ); -#else - TQ_UNUSED( func ) - TQ_UNUSED( i ) -#endif -} - - -/*! - Resets all image parameters and deallocates the image data. -*/ - -void TQImage::reset() -{ - freeBits(); - setNumColors( 0 ); -#ifndef TQT_NO_IMAGE_TEXT - delete data->misc; -#endif - reinit(); -} - - -/*! - Fills the entire image with the pixel value \a pixel. - - If the \link depth() depth\endlink of this image is 1, only the - lowest bit is used. If you say fill(0), fill(2), etc., the image - is filled with 0s. If you say fill(1), fill(3), etc., the image is - filled with 1s. If the depth is 8, the lowest 8 bits are used. - - If the depth is 32 and the image has no alpha buffer, the \a pixel - value is written to each pixel in the image. If the image has an - alpha buffer, only the 24 RGB bits are set and the upper 8 bits - (alpha value) are left unchanged. - - Note: TQImage::pixel() returns the color of the pixel at the given - coordinates; TQColor::pixel() returns the pixel value of the - underlying window system (essentially an index value), so normally - you will want to use TQImage::pixel() to use a color from an - existing image or TQColor::rgb() to use a specific color. - - \sa invertPixels() depth() hasAlphaBuffer() create() -*/ - -void TQImage::fill( uint pixel ) -{ - if ( depth() == 1 || depth() == 8 ) { - if ( depth() == 1 ) { - if ( pixel & 1 ) - pixel = 0xffffffff; - else - pixel = 0; - } else { - uint c = pixel & 0xff; - pixel = c | ((c << 8) & 0xff00) | ((c << 16) & 0xff0000) | - ((c << 24) & 0xff000000); - } - int bpl = bytesPerLine(); - for ( int i=0; i // needed for systemBitOrder -#include -#include -#if defined(TQ_OS_WIN32) -#undef open -#undef close -#undef read -#undef write -#endif -#endif - -// POSIX Large File Support redefines open -> open64 -#if defined(open) -# undef open -#endif - -// POSIX Large File Support redefines truncate -> truncate64 -#if defined(truncate) -# undef truncate -#endif - -/*! - Determines the bit order of the display hardware. Returns - TQImage::LittleEndian (LSB first) or TQImage::BigEndian (MSB first). - - \sa systemByteOrder() -*/ - -TQImage::Endian TQImage::systemBitOrder() -{ -#if defined(TQ_WS_X11) - return BitmapBitOrder(qt_xdisplay()) == MSBFirst ? BigEndian :LittleEndian; -#else - return BigEndian; -#endif -} - - -/*! - Resizes the color table to \a numColors colors. - - If the color table is expanded all the extra colors will be set to - black (RGB 0,0,0). - - \sa numColors() color() setColor() colorTable() -*/ - -void TQImage::setNumColors( int numColors ) -{ - if ( numColors == data->ncols ) - return; - if ( numColors == 0 ) { // use no color table - if ( data->ctbl ) { - if ( data->ctbl_mine ) - free( data->ctbl ); - else - data->ctbl_mine = TRUE; - data->ctbl = 0; - } - data->ncols = 0; - return; - } - if ( data->ctbl && data->ctbl_mine ) { // already has color table - data->ctbl = (TQRgb*)realloc( data->ctbl, numColors*sizeof(TQRgb) ); - if ( data->ctbl && numColors > data->ncols ) - memset( (char *)&data->ctbl[data->ncols], 0, - (numColors-data->ncols)*sizeof(TQRgb) ); - } else { // create new color table - data->ctbl = (TQRgb*)calloc( numColors*sizeof(TQRgb), 1 ); - TQ_CHECK_PTR(data->ctbl); - data->ctbl_mine = TRUE; - } - data->ncols = data->ctbl == 0 ? 0 : numColors; -} - - -/*! - \fn bool TQImage::hasAlphaBuffer() const - - Returns TRUE if alpha buffer mode is enabled; otherwise returns - FALSE. - - \sa setAlphaBuffer() -*/ - -/*! - Enables alpha buffer mode if \a enable is TRUE, otherwise disables - it. The default setting is disabled. - - An 8-bpp image has 8-bit pixels. A pixel is an index into the - \link color() color table\endlink, which contains 32-bit color - values. In a 32-bpp image, the 32-bit pixels are the color values. - - This 32-bit value is encoded as follows: The lower 24 bits are - used for the red, green, and blue components. The upper 8 bits - contain the alpha component. - - The alpha component specifies the transparency of a pixel. 0 means - completely transparent and 255 means opaque. The alpha component - is ignored if you do not enable alpha buffer mode. - - The alpha buffer is used to set a mask when a TQImage is translated - to a TQPixmap. - - \sa hasAlphaBuffer() createAlphaMask() -*/ - -void TQImage::setAlphaBuffer( bool enable ) -{ - data->alpha = enable; -} - - -/*! - Sets the image \a width, \a height, \a depth, its number of colors - (in \a numColors), and bit order. Returns TRUE if successful, or - FALSE if the parameters are incorrect or if memory cannot be - allocated. - - The \a width and \a height is limited to 32767. \a depth must be - 1, 8, or 32. If \a depth is 1, \a bitOrder must be set to - either TQImage::LittleEndian or TQImage::BigEndian. For other depths - \a bitOrder must be TQImage::IgnoreEndian. - - This function allocates a color table and a buffer for the image - data. The image data is not initialized. - - The image buffer is allocated as a single block that consists of a - table of \link scanLine() scanline\endlink pointers (jumpTable()) - and the image data (bits()). - - \sa fill() width() height() depth() numColors() bitOrder() - jumpTable() scanLine() bits() bytesPerLine() numBytes() -*/ - -bool TQImage::create( int width, int height, int depth, int numColors, - Endian bitOrder ) -{ - reset(); // reset old data - if ( width <= 0 || height <= 0 || depth <= 0 || numColors < 0 ) - return FALSE; // invalid parameter(s) - if ( depth == 1 && bitOrder == IgnoreEndian ) { -#if defined(TQT_CHECK_RANGE) - qWarning( "TQImage::create: Bit order is required for 1 bpp images" ); -#endif - return FALSE; - } - if ( depth != 1 ) - bitOrder = IgnoreEndian; - -#if defined(TQT_CHECK_RANGE) - if ( depth == 24 ) - qWarning( "TQImage::create: 24-bpp images no longer supported, " - "use 32-bpp instead" ); -#endif - switch ( depth ) { - case 1: - case 8: -#ifndef TQT_NO_IMAGE_16_BIT - case 16: -#endif -#ifndef TQT_NO_IMAGE_TRUECOLOR - case 32: -#endif - break; - default: // invalid depth - return FALSE; - } - - if ( depth == 32 ) - numColors = 0; - setNumColors( numColors ); - if ( data->ncols != numColors ) // could not alloc color table - return FALSE; - - if ( INT_MAX / uint(depth) < uint(width) ) { // sanity check for potential overflow - setNumColors( 0 ); - return FALSE; - } -// TQt/Embedded doesn't waste memory on unnecessary padding. -#ifdef TQ_WS_TQWS - const int bpl = (width*depth+7)/8; // bytes per scanline - const int pad = 0; -#else - const int bpl = ((width*depth+31)/32)*4; // bytes per scanline - // #### WWA: shouldn't this be (width*depth+7)/8: - const int pad = bpl - (width*depth)/8; // pad with zeros -#endif - if ( INT_MAX / uint(bpl) < uint(height) - || bpl < 0 - || INT_MAX / sizeof(uchar *) < uint(height) ) { // sanity check for potential overflow - setNumColors( 0 ); - return FALSE; - } - int nbytes = bpl*height; // image size - int ptbl = height*sizeof(uchar*); // pointer table size - int size = nbytes + ptbl; // total size of data block - uchar **p = (uchar **)malloc( size ); // alloc image bits - TQ_CHECK_PTR(p); - if ( !p ) { // no memory - setNumColors( 0 ); - return FALSE; - } - data->w = width; - data->h = height; - data->d = depth; - data->nbytes = nbytes; - data->bitordr = bitOrder; - data->bits = p; // set image pointer - //uchar *d = (uchar*)p + ptbl; // setup scanline pointers - uchar *d = (uchar*)(p + height); // setup scanline pointers - while ( height-- ) { - *p++ = d; - if ( pad ) - memset( d+bpl-pad, 0, pad ); - d += bpl; - } - return TRUE; -} - -/*! - \overload bool TQImage::create( const TQSize&, int depth, int numColors, Endian bitOrder ) -*/ -bool TQImage::create( const TQSize& size, int depth, int numColors, - TQImage::Endian bitOrder ) -{ - return create(size.width(), size.height(), depth, numColors, bitOrder); -} - -/*! - \internal - Initializes the image data structure. -*/ - -void TQImage::init() -{ - data = new TQImageData; - TQ_CHECK_PTR( data ); - reinit(); -} - -void TQImage::reinit() -{ - data->w = data->h = data->d = data->ncols = 0; - data->nbytes = 0; - data->ctbl = 0; - data->bits = 0; - data->bitordr = TQImage::IgnoreEndian; - data->alpha = FALSE; -#ifndef TQT_NO_IMAGE_TEXT - data->misc = 0; -#endif - data->dpmx = 0; - data->dpmy = 0; - data->offset = TQPoint(0,0); -} - -/*! - \internal - Deallocates the image data and sets the bits pointer to 0. -*/ - -void TQImage::freeBits() -{ - if ( data->bits ) { // dealloc image bits - free( data->bits ); - data->bits = 0; - } -} - - -/***************************************************************************** - Internal routines for converting image depth. - *****************************************************************************/ - -// -// convert_32_to_8: Converts a 32 bits depth (true color) to an 8 bit -// image with a colormap. If the 32 bit image has more than 256 colors, -// we convert the red,green and blue bytes into a single byte encoded -// as 6 shades of each of red, green and blue. -// -// if dithering is needed, only 1 color at most is available for alpha. -// -#ifndef TQT_NO_IMAGE_TRUECOLOR -struct TQRgbMap { - TQRgbMap() : rgb(0xffffffff) { } - bool used() const { return rgb!=0xffffffff; } - uchar pix; - TQRgb rgb; -}; - -static bool convert_32_to_8( const TQImage *src, TQImage *dst, int conversion_flags, TQRgb* palette=0, int palette_count=0 ) -{ - register TQRgb *p; - uchar *b; - bool do_quant = FALSE; - int y, x; - - if ( !dst->create(src->width(), src->height(), 8, 256) ) - return FALSE; - - const int tablesize = 997; // prime - TQRgbMap table[tablesize]; - int pix=0; - TQRgb amask = src->hasAlphaBuffer() ? 0xffffffff : 0x00ffffff; - if ( src->hasAlphaBuffer() ) - dst->setAlphaBuffer(TRUE); - - if ( palette ) { - // Preload palette into table. - - p = palette; - // Almost same code as pixel insertion below - while ( palette_count-- > 0 ) { - // Find in table... - int hash = (*p & amask) % tablesize; - for (;;) { - if ( table[hash].used() ) { - if ( table[hash].rgb == (*p & amask) ) { - // Found previous insertion - use it - break; - } else { - // Keep searching... - if (++hash == tablesize) hash = 0; - } - } else { - // Cannot be in table - TQ_ASSERT ( pix != 256 ); // too many colors - // Insert into table at this unused position - dst->setColor( pix, (*p & amask) ); - table[hash].pix = pix++; - table[hash].rgb = *p & amask; - break; - } - } - p++; - } - } - - if ( (conversion_flags & TQt::DitherMode_Mask) == TQt::PreferDither ) { - do_quant = TRUE; - } else { - for ( y=0; yheight(); y++ ) { // check if <= 256 colors - p = (TQRgb *)src->scanLine(y); - b = dst->scanLine(y); - x = src->width(); - while ( x-- ) { - // Find in table... - int hash = (*p & amask) % tablesize; - for (;;) { - if ( table[hash].used() ) { - if ( table[hash].rgb == (*p & amask) ) { - // Found previous insertion - use it - break; - } else { - // Keep searching... - if (++hash == tablesize) hash = 0; - } - } else { - // Cannot be in table - if ( pix == 256 ) { // too many colors - do_quant = TRUE; - // Break right out - x = 0; - y = src->height(); - } else { - // Insert into table at this unused position - dst->setColor( pix, (*p & amask) ); - table[hash].pix = pix++; - table[hash].rgb = (*p & amask); - } - break; - } - } - *b++ = table[hash].pix; // May occur once incorrectly - p++; - } - } - } - int ncols = do_quant ? 256 : pix; - - static uint bm[16][16]; - static int init=0; - if (!init) { - // Build a Bayer Matrix for dithering - - init = 1; - int n, i, j; - - bm[0][0]=0; - - for (n=1; n<16; n*=2) { - for (i=0; isetNumColors( ncols ); - - if ( do_quant ) { // quantization needed - -#define MAX_R 5 -#define MAX_G 5 -#define MAX_B 5 -#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 6x6x6 color cube - for ( gc=0; gc<=MAX_G; gc++ ) - for ( bc=0; bc<=MAX_B; bc++ ) { - dst->setColor( INDEXOF(rc,gc,bc), - (amask&0xff000000) - | 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]; - if ( ( conversion_flags & TQt::Dither_Mask ) == TQt::DiffuseDither ) { - 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 = (TQRgb *)src->scanLine(y); - b = dst->scanLine(y); - TQRgb *end = p + sw; - - // perform quantization - if ( ( conversion_flags & TQt::Dither_Mask ) == TQt::ThresholdDither ) { -#define DITHER(p,m) ((uchar) ((p * (m) + 127) / 255)) - while ( p < end ) { - rc = tqRed( *p ); - gc = tqGreen( *p ); - bc = tqBlue( *p ); - - *b++ = - INDEXOF( - DITHER(rc, MAX_R), - DITHER(gc, MAX_G), - DITHER(bc, MAX_B) - ); - - p++; - } -#undef DITHER - } else if ( ( conversion_flags & TQt::Dither_Mask ) == TQt::OrderedDither ) { -#define DITHER(p,d,m) ((uchar) ((((256 * (m) + (m) + 1)) * (p) + (d)) / 65536 )) - - int x = 0; - while ( p < end ) { - uint d = bm[y&15][x&15]; - - rc = tqRed( *p ); - gc = tqGreen( *p ); - bc = tqBlue( *p ); - - *b++ = - INDEXOF( - DITHER(rc, d, MAX_R), - DITHER(gc, d, MAX_G), - DITHER(bc, d, MAX_B) - ); - - p++; - x++; - } -#undef DITHER - } else { // Diffuse - int endian = (TQImage::systemByteOrder() == TQImage::BigEndian); - int x; - uchar* q = src->scanLine(y); - uchar* q2 = 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(5, (l1[x] * 5 + 128)/ 255), 0); - int err = l1[x] - pix * 255 / 5; - 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; xhasAlphaBuffer() ) { - const int trans = 216; - dst->setColor(trans, 0x00000000); // transparent - TQImage mask = src->createAlphaMask(conversion_flags); - uchar* m; - for ( y=0; y < src->height(); y++ ) { - uchar bit = 0x80; - m = mask.scanLine(y); - b = dst->scanLine(y); - int w = src->width(); - for ( x = 0; x>= 1)) { - bit = 0x80; - while ( xcreate(src->width(), src->height(), 32) ) - return FALSE; // create failed - dst->setAlphaBuffer( src->hasAlphaBuffer() ); - for ( int y=0; yheight(); y++ ) { // for each scan line... - register uint *p = (uint *)dst->scanLine(y); - uchar *b = src->scanLine(y); - uint *end = p + dst->width(); - while ( p < end ) - *p++ = src->color(*b++); - } - return TRUE; -} - - -static bool convert_1_to_32( const TQImage *src, TQImage *dst ) -{ - if ( !dst->create(src->width(), src->height(), 32) ) - return FALSE; // could not create - dst->setAlphaBuffer( src->hasAlphaBuffer() ); - for ( int y=0; yheight(); y++ ) { // for each scan line... - register uint *p = (uint *)dst->scanLine(y); - uchar *b = src->scanLine(y); - int x; - if ( src->bitOrder() == TQImage::BigEndian ) { - for ( x=0; xwidth(); x++ ) { - *p++ = src->color( (*b >> (7 - (x & 7))) & 1 ); - if ( (x & 7) == 7 ) - b++; - } - } else { - for ( x=0; xwidth(); x++ ) { - *p++ = src->color( (*b >> (x & 7)) & 1 ); - if ( (x & 7) == 7 ) - b++; - } - } - } - return TRUE; -} -#endif // TQT_NO_IMAGE_TRUECOLOR - -static bool convert_1_to_8( const TQImage *src, TQImage *dst ) -{ - if ( !dst->create(src->width(), src->height(), 8, 2) ) - return FALSE; // something failed - dst->setAlphaBuffer( src->hasAlphaBuffer() ); - if (src->numColors() >= 2) { - dst->setColor( 0, src->color(0) ); // copy color table - dst->setColor( 1, src->color(1) ); - } else { - // Unlikely, but they do exist - if (src->numColors() >= 1) - dst->setColor( 0, src->color(0) ); - else - dst->setColor( 0, 0xffffffff ); - dst->setColor( 1, 0xff000000 ); - } - for ( int y=0; yheight(); y++ ) { // for each scan line... - register uchar *p = dst->scanLine(y); - uchar *b = src->scanLine(y); - int x; - if ( src->bitOrder() == TQImage::BigEndian ) { - for ( x=0; xwidth(); x++ ) { - *p++ = (*b >> (7 - (x & 7))) & 1; - if ( (x & 7) == 7 ) - b++; - } - } else { - for ( x=0; xwidth(); x++ ) { - *p++ = (*b >> (x & 7)) & 1; - if ( (x & 7) == 7 ) - b++; - } - } - } - return TRUE; -} - -#ifndef TQT_NO_IMAGE_DITHER_TO_1 -// -// dither_to_1: Uses selected dithering algorithm. -// - -static bool dither_to_1( const TQImage *src, TQImage *dst, - int conversion_flags, bool fromalpha ) -{ - if ( !dst->create(src->width(), src->height(), 1, 2, TQImage::BigEndian) ) - return FALSE; // something failed - - enum { Threshold, Ordered, Diffuse } dithermode; - - if ( fromalpha ) { - if ( ( conversion_flags & TQt::AlphaDither_Mask ) == TQt::DiffuseAlphaDither ) - dithermode = Diffuse; - else if ( ( conversion_flags & TQt::AlphaDither_Mask ) == TQt::OrderedAlphaDither ) - dithermode = Ordered; - else - dithermode = Threshold; - } else { - if ( ( conversion_flags & TQt::Dither_Mask ) == TQt::ThresholdDither ) - dithermode = Threshold; - else if ( ( conversion_flags & TQt::Dither_Mask ) == TQt::OrderedDither ) - dithermode = Ordered; - else - dithermode = Diffuse; - } - - dst->setColor( 0, tqRgb(255, 255, 255) ); - dst->setColor( 1, tqRgb( 0, 0, 0) ); - int w = src->width(); - int h = src->height(); - int d = src->depth(); - uchar gray[256]; // gray map for 8 bit images - bool use_gray = d == 8; - if ( use_gray ) { // make gray map - if ( fromalpha ) { - // Alpha 0x00 -> 0 pixels (white) - // Alpha 0xFF -> 1 pixels (black) - for ( int i=0; inumColors(); i++ ) - gray[i] = (255 - (src->color(i) >> 24)); - } else { - // Pixel 0x00 -> 1 pixels (black) - // Pixel 0xFF -> 0 pixels (white) - for ( int i=0; inumColors(); i++ ) - gray[i] = tqGray( src->color(i) & 0x00ffffff ); - } - } - - switch ( dithermode ) { - case Diffuse: { - int *line1 = new int[w]; - int *line2 = new int[w]; - int bmwidth = (w+7)/8; - if ( !(line1 && line2) ) - return FALSE; - register uchar *p; - uchar *end; - int *b1, *b2; - int wbytes = w * (d/8); - p = src->bits(); - end = p + wbytes; - b2 = line2; - if ( use_gray ) { // 8 bit image - while ( p < end ) - *b2++ = gray[*p++]; -#ifndef TQT_NO_IMAGE_TRUECOLOR - } else { // 32 bit image - if ( fromalpha ) { - while ( p < end ) { - *b2++ = 255 - (*(uint*)p >> 24); - p += 4; - } - } else { - while ( p < end ) { - *b2++ = tqGray(*(uint*)p); - p += 4; - } - } -#endif - } - int x, y; - for ( y=0; yscanLine(y+1); - end = p + wbytes; - b2 = line2; - if ( use_gray ) { // 8 bit image - while ( p < end ) - *b2++ = gray[*p++]; -#ifndef TQT_NO_IMAGE_TRUECOLOR - } else { // 24 bit image - if ( fromalpha ) { - while ( p < end ) { - *b2++ = 255 - (*(uint*)p >> 24); - p += 4; - } - } else { - while ( p < end ) { - *b2++ = tqGray(*(uint*)p); - p += 4; - } - } -#endif - } - } - - int err; - p = dst->scanLine( y ); - memset( p, 0, bmwidth ); - b1 = line1; - b2 = line2; - int bit = 7; - for ( x=1; x<=w; x++ ) { - if ( *b1 < 128 ) { // black pixel - err = *b1++; - *p |= 1 << bit; - } else { // white pixel - err = *b1++ - 255; - } - if ( bit == 0 ) { - p++; - bit = 7; - } else { - bit--; - } - if ( x < w ) - *b1 += (err*7)>>4; // spread error to right pixel - if ( not_last_line ) { - b2[0] += (err*5)>>4; // pixel below - if ( x > 1 ) - b2[-1] += (err*3)>>4; // pixel below left - if ( x < w ) - b2[1] += err>>4; // pixel below right - } - b2++; - } - } - delete [] line1; - delete [] line2; - } break; - case Ordered: { - static uint bm[16][16]; - static int init=0; - if (!init) { - // Build a Bayer Matrix for dithering - - init = 1; - int n, i, j; - - bm[0][0]=0; - - for (n=1; n<16; n*=2) { - for (i=0; ifill( 0 ); - uchar** mline = dst->jumpTable(); -#ifndef TQT_NO_IMAGE_TRUECOLOR - if ( d == 32 ) { - uint** line = (uint**)src->jumpTable(); - for ( int i=0; i> 24) >= bm[j++&15][i&15] ) - *m |= 1 << bit; - if ( bit == 0 ) { - m++; - bit = 7; - } else { - bit--; - } - } - } else { - while ( p < end ) { - if ( (uint)tqGray(*p++) < bm[j++&15][i&15] ) - *m |= 1 << bit; - if ( bit == 0 ) { - m++; - bit = 7; - } else { - bit--; - } - } - } - } - } else -#endif // TQT_NO_IMAGE_TRUECOLOR - /* ( d == 8 ) */ { - uchar** line = src->jumpTable(); - for ( int i=0; ifill( 0 ); - uchar** mline = dst->jumpTable(); -#ifndef TQT_NO_IMAGE_TRUECOLOR - if ( d == 32 ) { - uint** line = (uint**)src->jumpTable(); - for ( int i=0; i> 24) >= 128 ) - *m |= 1 << bit; // Set mask "on" - if ( bit == 0 ) { - m++; - bit = 7; - } else { - bit--; - } - } - } else { - while ( p < end ) { - if ( tqGray(*p++) < 128 ) - *m |= 1 << bit; // Set pixel "black" - if ( bit == 0 ) { - m++; - bit = 7; - } else { - bit--; - } - } - } - } - } else -#endif //TQT_NO_IMAGE_TRUECOLOR - if ( d == 8 ) { - uchar** line = src->jumpTable(); - for ( int i=0; i> 11; - int g=(c & 0x07e0) >> 6; //green/2 - int b=(c & 0x001f); - return r == g && g == b; -} - - -static bool convert_16_to_32( const TQImage *src, TQImage *dst ) -{ - if ( !dst->create(src->width(), src->height(), 32) ) - return FALSE; // create failed - dst->setAlphaBuffer( src->hasAlphaBuffer() ); - for ( int y=0; yheight(); y++ ) { // for each scan line... - register uint *p = (uint *)dst->scanLine(y); - ushort *s = (ushort*)src->scanLine(y); - uint *end = p + dst->width(); - while ( p < end ) - *p++ = qt_conv16ToRgb( *s++ ); - } - return TRUE; -} - - -static bool convert_32_to_16( const TQImage *src, TQImage *dst ) -{ - if ( !dst->create(src->width(), src->height(), 16) ) - return FALSE; // create failed - dst->setAlphaBuffer( src->hasAlphaBuffer() ); - for ( int y=0; yheight(); y++ ) { // for each scan line... - register ushort *p = (ushort *)dst->scanLine(y); - uint *s = (uint*)src->scanLine(y); - ushort *end = p + dst->width(); - while ( p < end ) - *p++ = qt_convRgbTo16( *s++ ); - } - return TRUE; -} - - -#endif - -/*! - Converts the depth (bpp) of the image to \a depth and returns the - converted image. The original image is not changed. - - The \a depth argument must be 1, 8, 16 (TQt/Embedded only) or 32. - - Returns \c *this if \a depth is equal to the image depth, or a - \link isNull() null\endlink image if this image cannot be - converted. - - If the image needs to be modified to fit in a lower-resolution - result (e.g. converting from 32-bit to 8-bit), use the \a - conversion_flags to specify how you'd prefer this to happen. - - \sa TQt::ImageConversionFlags depth() isNull() -*/ - -TQImage TQImage::convertDepth( int depth, int conversion_flags ) const -{ - TQImage image; - if ( data->d == depth ) - image = *this; // no conversion -#ifndef TQT_NO_IMAGE_DITHER_TO_1 - else if ( (data->d == 8 || data->d == 32) && depth == 1 ) // dither - dither_to_1( this, &image, conversion_flags, FALSE ); -#endif -#ifndef TQT_NO_IMAGE_TRUECOLOR - else if ( data->d == 32 && depth == 8 ) // 32 -> 8 - convert_32_to_8( this, &image, conversion_flags ); - else if ( data->d == 8 && depth == 32 ) // 8 -> 32 - convert_8_to_32( this, &image ); -#endif - else if ( data->d == 1 && depth == 8 ) // 1 -> 8 - convert_1_to_8( this, &image ); -#ifndef TQT_NO_IMAGE_TRUECOLOR - else if ( data->d == 1 && depth == 32 ) // 1 -> 32 - convert_1_to_32( this, &image ); -#endif -#ifndef TQT_NO_IMAGE_16_BIT - else if ( data->d == 16 && depth != 16 ) { - TQImage tmp; - convert_16_to_32( this, &tmp ); - image = tmp.convertDepth( depth, conversion_flags ); - } else if ( data->d != 16 && depth == 16 ) { - TQImage tmp = convertDepth( 32, conversion_flags ); - convert_32_to_16( &tmp, &image ); - } -#endif - else { -#if defined(TQT_CHECK_RANGE) - if ( isNull() ) - qWarning( "TQImage::convertDepth: Image is a null image" ); - else - qWarning( "TQImage::convertDepth: Depth %d not supported", depth ); -#endif - } - return image; -} - -/*! - \overload -*/ - -TQImage TQImage::convertDepth( int depth ) const -{ - return convertDepth( depth, 0 ); -} - -/*! - Returns TRUE if ( \a x, \a y ) is a valid coordinate in the image; - otherwise returns FALSE. - - \sa width() height() pixelIndex() -*/ - -bool TQImage::valid( int x, int y ) const -{ - return x >= 0 && x < width() - && y >= 0 && y < height(); -} - -/*! - Returns the pixel index at the given coordinates. - - If (\a x, \a y) is not \link valid() valid\endlink, or if the - image is not a paletted image (depth() \> 8), the results are - undefined. - - \sa valid() depth() -*/ - -int TQImage::pixelIndex( int x, int y ) const -{ -#if defined(TQT_CHECK_RANGE) - if ( x < 0 || x >= width() ) { - qWarning( "TQImage::pixel: x=%d out of range", x ); - return -12345; - } -#endif - uchar * s = scanLine( y ); - switch( depth() ) { - case 1: - if ( bitOrder() == TQImage::LittleEndian ) - return (*(s + (x >> 3)) >> (x & 7)) & 1; - else - return (*(s + (x >> 3)) >> (7- (x & 7))) & 1; - case 8: - return (int)s[x]; -#ifndef TQT_NO_IMAGE_TRUECOLOR -#ifndef TQT_NO_IMAGE_16_BIT - case 16: -#endif - case 32: -#if defined(TQT_CHECK_RANGE) - qWarning( "TQImage::pixelIndex: Not applicable for %d-bpp images " - "(no palette)", depth() ); -#endif - return 0; -#endif //TQT_NO_IMAGE_TRUECOLOR - } - return 0; -} - - -/*! - Returns the color of the pixel at the coordinates (\a x, \a y). - - If (\a x, \a y) is not \link valid() on the image\endlink, the - results are undefined. - - \sa setPixel() tqRed() tqGreen() tqBlue() valid() -*/ - -TQRgb TQImage::pixel( int x, int y ) const -{ -#if defined(TQT_CHECK_RANGE) - if ( x < 0 || x >= width() ) { - qWarning( "TQImage::pixel: x=%d out of range", x ); - return 12345; - } -#endif - uchar * s = scanLine( y ); - switch( depth() ) { - case 1: - if ( bitOrder() == TQImage::LittleEndian ) - return color( (*(s + (x >> 3)) >> (x & 7)) & 1 ); - else - return color( (*(s + (x >> 3)) >> (7- (x & 7))) & 1 ); - case 8: - return color( (int)s[x] ); -#ifndef TQT_NO_IMAGE_16_BIT - case 16: - return qt_conv16ToRgb(((ushort*)s)[x]); -#endif -#ifndef TQT_NO_IMAGE_TRUECOLOR - case 32: - return ((TQRgb*)s)[x]; -#endif - default: - return 100367; - } -} - - -/*! - Sets the pixel index or color at the coordinates (\a x, \a y) to - \a index_or_rgb. - - If (\a x, \a y) is not \link valid() valid\endlink, the result is - undefined. - - If the image is a paletted image (depth() \<= 8) and \a - index_or_rgb \>= numColors(), the result is undefined. - - \sa pixelIndex() pixel() tqRgb() tqRgba() valid() -*/ - -void TQImage::setPixel( int x, int y, uint index_or_rgb ) -{ - if ( x < 0 || x >= width() ) { -#if defined(TQT_CHECK_RANGE) - qWarning( "TQImage::setPixel: x=%d out of range", x ); -#endif - return; - } - if ( depth() == 1 ) { - uchar * s = scanLine( y ); - if ( index_or_rgb > 1) { -#if defined(TQT_CHECK_RANGE) - qWarning( "TQImage::setPixel: index=%d out of range", - index_or_rgb ); -#endif - } else if ( bitOrder() == TQImage::LittleEndian ) { - if (index_or_rgb==0) - *(s + (x >> 3)) &= ~(1 << (x & 7)); - else - *(s + (x >> 3)) |= (1 << (x & 7)); - } else { - if (index_or_rgb==0) - *(s + (x >> 3)) &= ~(1 << (7-(x & 7))); - else - *(s + (x >> 3)) |= (1 << (7-(x & 7))); - } - } else if ( depth() == 8 ) { - if (index_or_rgb > (uint)numColors()) { -#if defined(TQT_CHECK_RANGE) - qWarning( "TQImage::setPixel: index=%d out of range", - index_or_rgb ); -#endif - return; - } - uchar * s = scanLine( y ); - s[x] = index_or_rgb; -#ifndef TQT_NO_IMAGE_16_BIT - } else if ( depth() == 16 ) { - ushort * s = (ushort*)scanLine( y ); - s[x] = qt_convRgbTo16(index_or_rgb); -#endif -#ifndef TQT_NO_IMAGE_TRUECOLOR - } else if ( depth() == 32 ) { - TQRgb * s = (TQRgb*)scanLine( y ); - s[x] = index_or_rgb; -#endif - } -} - - -/*! - Converts the bit order of the image to \a bitOrder and returns the - converted image. The original image is not changed. - - Returns \c *this if the \a bitOrder is equal to the image bit - order, or a \link isNull() null\endlink image if this image cannot - be converted. - - \sa bitOrder() systemBitOrder() isNull() -*/ - -TQImage TQImage::convertBitOrder( Endian bitOrder ) const -{ - if ( isNull() || data->d != 1 || // invalid argument(s) - !(bitOrder == BigEndian || bitOrder == LittleEndian) ) { - TQImage nullImage; - return nullImage; - } - if ( data->bitordr == bitOrder ) // nothing to do - return copy(); - - TQImage image( data->w, data->h, 1, data->ncols, bitOrder ); - - int bpl = (width() + 7) / 8; - for ( int y = 0; y < data->h; y++ ) { - register uchar *p = jumpTable()[y]; - uchar *end = p + bpl; - uchar *b = image.jumpTable()[y]; - while ( p < end ) - *b++ = bitflip[*p++]; - } - memcpy( image.colorTable(), colorTable(), numColors()*sizeof(TQRgb) ); - return image; -} - -// ### Candidate (renamed) for tqcolor.h -static -bool isGray(TQRgb c) -{ - return tqRed(c) == tqGreen(c) - && tqRed(c) == tqBlue(c); -} - -/*! - Returns TRUE if all the colors in the image are shades of gray - (i.e. their red, green and blue components are equal); otherwise - returns FALSE. - - This function is slow for large 16-bit (TQt/Embedded only) and 32-bit images. - - \sa isGrayscale() -*/ -bool TQImage::allGray() const -{ -#ifndef TQT_NO_IMAGE_TRUECOLOR - if (depth()==32) { - int p = width()*height(); - TQRgb* b = (TQRgb*)bits(); - while (p--) - if (!isGray(*b++)) - return FALSE; -#ifndef TQT_NO_IMAGE_16_BIT - } else if (depth()==16) { - int p = width()*height(); - ushort* b = (ushort*)bits(); - while (p--) - if (!is16BitGray(*b++)) - return FALSE; -#endif - } else -#endif //TQT_NO_IMAGE_TRUECOLOR - { - if (!data->ctbl) return TRUE; - for (int i=0; ictbl[i])) - return FALSE; - } - return TRUE; -} - -/*! - For 16-bit (TQt/Embedded only) and 32-bit images, this function is - equivalent to allGray(). - - For 8-bpp images, this function returns TRUE if color(i) is - TQRgb(i,i,i) for all indices of the color table; otherwise returns - FALSE. - - \sa allGray() depth() -*/ -bool TQImage::isGrayscale() const -{ - switch (depth()) { -#ifndef TQT_NO_IMAGE_TRUECOLOR - case 32: -#ifndef TQT_NO_IMAGE_16_BIT - case 16: -#endif - return allGray(); -#endif //TQT_NO_IMAGE_TRUECOLOR - case 8: { - for (int i=0; ictbl[i] != tqRgb(i,i,i)) - return FALSE; - return TRUE; - } - } - return FALSE; -} - -#ifndef TQT_NO_IMAGE_SMOOTHSCALE -static -void pnmscale(const TQImage& src, TQImage& dst) -{ - TQRgb* xelrow = 0; - TQRgb* tempxelrow = 0; - register TQRgb* xP; - register TQRgb* nxP; - int rows, cols, rowsread, newrows, newcols; - register int row, col, needtoreadrow; - const uchar maxval = 255; - double xscale, yscale; - long sxscale, syscale; - register long fracrowtofill, fracrowleft; - long* as; - long* rs; - long* gs; - long* bs; - int rowswritten = 0; - - cols = src.width(); - rows = src.height(); - newcols = dst.width(); - newrows = dst.height(); - - long SCALE; - long HALFSCALE; - - if (cols > 4096) - { - SCALE = 4096; - HALFSCALE = 2048; - } - else - { - int fac = 4096; - - while (cols * fac > 4096) - { - fac /= 2; - } - - SCALE = fac * cols; - HALFSCALE = fac * cols / 2; - } - - xscale = (double) newcols / (double) cols; - yscale = (double) newrows / (double) rows; - - sxscale = (long)(xscale * SCALE); - syscale = (long)(yscale * SCALE); - - if ( newrows != rows ) /* shortcut Y scaling if possible */ - tempxelrow = new TQRgb[cols]; - - if ( src.hasAlphaBuffer() ) { - dst.setAlphaBuffer(TRUE); - as = new long[cols]; - for ( col = 0; col < cols; ++col ) - as[col] = HALFSCALE; - } else { - as = 0; - } - rs = new long[cols]; - gs = new long[cols]; - bs = new long[cols]; - rowsread = 0; - fracrowleft = syscale; - needtoreadrow = 1; - for ( col = 0; col < cols; ++col ) - rs[col] = gs[col] = bs[col] = HALFSCALE; - fracrowtofill = SCALE; - - for ( row = 0; row < newrows; ++row ) { - /* First scale Y from xelrow into tempxelrow. */ - if ( newrows == rows ) { - /* shortcut Y scaling if possible */ - tempxelrow = xelrow = (TQRgb*)src.scanLine(rowsread++); - } else { - while ( fracrowleft < fracrowtofill ) { - if ( needtoreadrow && rowsread < rows ) - xelrow = (TQRgb*)src.scanLine(rowsread++); - for ( col = 0, xP = xelrow; col < cols; ++col, ++xP ) { - if (as) { - as[col] += fracrowleft * tqAlpha( *xP ); - rs[col] += fracrowleft * tqRed( *xP ) * tqAlpha( *xP ) / 255; - gs[col] += fracrowleft * tqGreen( *xP ) * tqAlpha( *xP ) / 255; - bs[col] += fracrowleft * tqBlue( *xP ) * tqAlpha( *xP ) / 255; - } else { - rs[col] += fracrowleft * tqRed( *xP ); - gs[col] += fracrowleft * tqGreen( *xP ); - bs[col] += fracrowleft * tqBlue( *xP ); - } - } - fracrowtofill -= fracrowleft; - fracrowleft = syscale; - needtoreadrow = 1; - } - /* Now fracrowleft is >= fracrowtofill, so we can produce a row. */ - if ( needtoreadrow && rowsread < rows ) { - xelrow = (TQRgb*)src.scanLine(rowsread++); - needtoreadrow = 0; - } - register long a=0; - for ( col = 0, xP = xelrow, nxP = tempxelrow; - col < cols; ++col, ++xP, ++nxP ) - { - register long r, g, b; - - if ( as ) { - r = rs[col] + fracrowtofill * tqRed( *xP ) * tqAlpha( *xP ) / 255; - g = gs[col] + fracrowtofill * tqGreen( *xP ) * tqAlpha( *xP ) / 255; - b = bs[col] + fracrowtofill * tqBlue( *xP ) * tqAlpha( *xP ) / 255; - a = as[col] + fracrowtofill * tqAlpha( *xP ); - if ( a ) { - r = r * 255 / a * SCALE; - g = g * 255 / a * SCALE; - b = b * 255 / a * SCALE; - } - } else { - r = rs[col] + fracrowtofill * tqRed( *xP ); - g = gs[col] + fracrowtofill * tqGreen( *xP ); - b = bs[col] + fracrowtofill * tqBlue( *xP ); - } - r /= SCALE; - if ( r > maxval ) r = maxval; - g /= SCALE; - if ( g > maxval ) g = maxval; - b /= SCALE; - if ( b > maxval ) b = maxval; - if ( as ) { - a /= SCALE; - if ( a > maxval ) a = maxval; - *nxP = tqRgba( (int)r, (int)g, (int)b, (int)a ); - as[col] = HALFSCALE; - } else { - *nxP = tqRgb( (int)r, (int)g, (int)b ); - } - rs[col] = gs[col] = bs[col] = HALFSCALE; - } - fracrowleft -= fracrowtofill; - if ( fracrowleft == 0 ) { - fracrowleft = syscale; - needtoreadrow = 1; - } - fracrowtofill = SCALE; - } - - /* Now scale X from tempxelrow into dst and write it out. */ - if ( newcols == cols ) { - /* shortcut X scaling if possible */ - memcpy(dst.scanLine(rowswritten++), tempxelrow, newcols*4); - } else { - register long a, r, g, b; - register long fraccoltofill, fraccolleft = 0; - register int needcol; - - nxP = (TQRgb*)dst.scanLine(rowswritten++); - fraccoltofill = SCALE; - a = r = g = b = HALFSCALE; - needcol = 0; - for ( col = 0, xP = tempxelrow; col < cols; ++col, ++xP ) { - fraccolleft = sxscale; - while ( fraccolleft >= fraccoltofill ) { - if ( needcol ) { - ++nxP; - a = r = g = b = HALFSCALE; - } - if ( as ) { - r += fraccoltofill * tqRed( *xP ) * tqAlpha( *xP ) / 255; - g += fraccoltofill * tqGreen( *xP ) * tqAlpha( *xP ) / 255; - b += fraccoltofill * tqBlue( *xP ) * tqAlpha( *xP ) / 255; - a += fraccoltofill * tqAlpha( *xP ); - if ( a ) { - r = r * 255 / a * SCALE; - g = g * 255 / a * SCALE; - b = b * 255 / a * SCALE; - } - } else { - r += fraccoltofill * tqRed( *xP ); - g += fraccoltofill * tqGreen( *xP ); - b += fraccoltofill * tqBlue( *xP ); - } - r /= SCALE; - if ( r > maxval ) r = maxval; - g /= SCALE; - if ( g > maxval ) g = maxval; - b /= SCALE; - if ( b > maxval ) b = maxval; - if (as) { - a /= SCALE; - if ( a > maxval ) a = maxval; - *nxP = tqRgba( (int)r, (int)g, (int)b, (int)a ); - } else { - *nxP = tqRgb( (int)r, (int)g, (int)b ); - } - fraccolleft -= fraccoltofill; - fraccoltofill = SCALE; - needcol = 1; - } - if ( fraccolleft > 0 ) { - if ( needcol ) { - ++nxP; - a = r = g = b = HALFSCALE; - needcol = 0; - } - if (as) { - a += fraccolleft * tqAlpha( *xP ); - r += fraccolleft * tqRed( *xP ) * tqAlpha( *xP ) / 255; - g += fraccolleft * tqGreen( *xP ) * tqAlpha( *xP ) / 255; - b += fraccolleft * tqBlue( *xP ) * tqAlpha( *xP ) / 255; - } else { - r += fraccolleft * tqRed( *xP ); - g += fraccolleft * tqGreen( *xP ); - b += fraccolleft * tqBlue( *xP ); - } - fraccoltofill -= fraccolleft; - } - } - if ( fraccoltofill > 0 ) { - --xP; - if (as) { - a += fraccolleft * tqAlpha( *xP ); - r += fraccoltofill * tqRed( *xP ) * tqAlpha( *xP ) / 255; - g += fraccoltofill * tqGreen( *xP ) * tqAlpha( *xP ) / 255; - b += fraccoltofill * tqBlue( *xP ) * tqAlpha( *xP ) / 255; - if ( a ) { - r = r * 255 / a * SCALE; - g = g * 255 / a * SCALE; - b = b * 255 / a * SCALE; - } - } else { - r += fraccoltofill * tqRed( *xP ); - g += fraccoltofill * tqGreen( *xP ); - b += fraccoltofill * tqBlue( *xP ); - } - } - if ( ! needcol ) { - r /= SCALE; - if ( r > maxval ) r = maxval; - g /= SCALE; - if ( g > maxval ) g = maxval; - b /= SCALE; - if ( b > maxval ) b = maxval; - if (as) { - a /= SCALE; - if ( a > maxval ) a = maxval; - *nxP = tqRgba( (int)r, (int)g, (int)b, (int)a ); - } else { - *nxP = tqRgb( (int)r, (int)g, (int)b ); - } - } - } - } - - if ( newrows != rows && tempxelrow )// Robust, tempxelrow might be 0 1 day - delete [] tempxelrow; - if ( as ) // Avoid purify complaint - delete [] as; - if ( rs ) // Robust, rs might be 0 one day - delete [] rs; - if ( gs ) // Robust, gs might be 0 one day - delete [] gs; - if ( bs ) // Robust, bs might be 0 one day - delete [] bs; -} -#endif - -/*! - \enum TQImage::ScaleMode - - The functions scale() and smoothScale() use different modes for - scaling the image. The purpose of these modes is to retain the - ratio of the image if this is required. - - \img scaling.png - - \value ScaleFree The image is scaled freely: the resulting image - fits exactly into the specified size; the ratio will not - necessarily be preserved. - \value ScaleMin The ratio of the image is preserved and the - resulting image is guaranteed to fit into the specified size - (it is as large as possible within these constraints) - the - image might be smaller than the requested size. - \value ScaleMax The ratio of the image is preserved and the - resulting image fills the whole specified rectangle (it is as - small as possible within these constraints) - the image might - be larger than the requested size. -*/ - -#ifndef TQT_NO_IMAGE_SMOOTHSCALE -/*! - Returns a smoothly scaled copy of the image. The returned image - has a size of width \a w by height \a h pixels if \a mode is \c - ScaleFree. The modes \c ScaleMin and \c ScaleMax may be used to - preserve the ratio of the image: if \a mode is \c ScaleMin, the - returned image is guaranteed to fit into the rectangle specified - by \a w and \a h (it is as large as possible within the - constraints); if \a mode is \c ScaleMax, the returned image fits - at least into the specified rectangle (it is a small as possible - within the constraints). - - For 32-bpp images and 1-bpp/8-bpp color images the result will be - 32-bpp, whereas \link allGray() all-gray \endlink images - (including black-and-white 1-bpp) will produce 8-bit \link - isGrayscale() grayscale \endlink images with the palette spanning - 256 grays from black to white. - - This function uses code based on pnmscale.c by Jef Poskanzer. - - pnmscale.c - read a portable anymap and scale it - - \legalese - - Copyright (C) 1989, 1991 by Jef Poskanzer. - - Permission to use, copy, modify, and distribute this software and - its documentation for any purpose and without fee is hereby - granted, provided that the above copyright notice appear in all - copies and that both that copyright notice and this permission - notice appear in supporting documentation. This software is - provided "as is" without express or implied warranty. - - \sa scale() mirror() -*/ -TQImage TQImage::smoothScale( int w, int h, ScaleMode mode ) const -{ - return smoothScale( TQSize( w, h ), mode ); -} -#endif - -#ifndef TQT_NO_IMAGE_SMOOTHSCALE -/*! - \overload - - The requested size of the image is \a s. -*/ -TQImage TQImage::smoothScale( const TQSize& s, ScaleMode mode ) const -{ - if ( isNull() ) { -#if defined(TQT_CHECK_RANGE) - qWarning( "TQImage::smoothScale: Image is a null image" ); -#endif - return copy(); - } - - TQSize newSize = size(); - newSize.scale( s, (TQSize::ScaleMode)mode ); // ### remove cast in TQt 4.0 - if ( newSize == size() ) - return copy(); - - if ( depth() == 32 ) { - TQImage img( newSize, 32 ); - // 32-bpp to 32-bpp - pnmscale( *this, img ); - return img; - } else if ( depth() != 16 && allGray() && !hasAlphaBuffer() ) { - // Inefficient - return convertDepth(32).smoothScale(newSize, mode).convertDepth(8); - } else { - // Inefficient - return convertDepth(32).smoothScale(newSize, mode); - } -} -#endif - -/*! - Returns a copy of the image scaled to a rectangle of width \a w - and height \a h according to the ScaleMode \a mode. - - \list - \i If \a mode is \c ScaleFree, the image is scaled to (\a w, - \a h). - \i If \a mode is \c ScaleMin, the image is scaled to a rectangle - as large as possible inside (\a w, \a h), preserving the aspect - ratio. - \i If \a mode is \c ScaleMax, the image is scaled to a rectangle - as small as possible outside (\a w, \a h), preserving the aspect - ratio. - \endlist - - If either the width \a w or the height \a h is 0 or negative, this - function returns a \link isNull() null\endlink image. - - This function uses a simple, fast algorithm. If you need better - quality, use smoothScale() instead. - - \sa scaleWidth() scaleHeight() smoothScale() xForm() -*/ -#ifndef TQT_NO_IMAGE_TRANSFORMATION -TQImage TQImage::scale( int w, int h, ScaleMode mode ) const -{ - return scale( TQSize( w, h ), mode ); -} -#endif - -/*! - \overload - - The requested size of the image is \a s. -*/ -#ifndef TQT_NO_IMAGE_TRANSFORMATION -TQImage TQImage::scale( const TQSize& s, ScaleMode mode ) const -{ - if ( isNull() ) { -#if defined(TQT_CHECK_RANGE) - qWarning( "TQImage::scale: Image is a null image" ); -#endif - return copy(); - } - if ( s.isEmpty() ) - return TQImage(); - - TQSize newSize = size(); - newSize.scale( s, (TQSize::ScaleMode)mode ); // ### remove cast in TQt 4.0 - if ( newSize == size() ) - return copy(); - - TQImage img; - TQWMatrix wm; - wm.scale( (double)newSize.width() / width(), (double)newSize.height() / height() ); - img = xForm( wm ); - // ### I should test and resize the image if it has not the right size -// if ( img.width() != newSize.width() || img.height() != newSize.height() ) -// img.resize( newSize.width(), newSize.height() ); - return img; -} -#endif - -/*! - Returns a scaled copy of the image. The returned image has a width - of \a w pixels. This function automatically calculates the height - of the image so that the ratio of the image is preserved. - - If \a w is 0 or negative a \link isNull() null\endlink image is - returned. - - \sa scale() scaleHeight() smoothScale() xForm() -*/ -#ifndef TQT_NO_IMAGE_TRANSFORMATION -TQImage TQImage::scaleWidth( int w ) const -{ - if ( isNull() ) { -#if defined(TQT_CHECK_RANGE) - qWarning( "TQImage::scaleWidth: Image is a null image" ); -#endif - return copy(); - } - if ( w <= 0 ) - return TQImage(); - - TQWMatrix wm; - double factor = (double) w / width(); - wm.scale( factor, factor ); - return xForm( wm ); -} -#endif - -/*! - Returns a scaled copy of the image. The returned image has a - height of \a h pixels. This function automatically calculates the - width of the image so that the ratio of the image is preserved. - - If \a h is 0 or negative a \link isNull() null\endlink image is - returned. - - \sa scale() scaleWidth() smoothScale() xForm() -*/ -#ifndef TQT_NO_IMAGE_TRANSFORMATION -TQImage TQImage::scaleHeight( int h ) const -{ - if ( isNull() ) { -#if defined(TQT_CHECK_RANGE) - qWarning( "TQImage::scaleHeight: Image is a null image" ); -#endif - return copy(); - } - if ( h <= 0 ) - return TQImage(); - - TQWMatrix wm; - double factor = (double) h / height(); - wm.scale( factor, factor ); - return xForm( wm ); -} -#endif - - -/*! - Returns a copy of the image that is transformed using the - transformation matrix, \a matrix. - - The transformation \a matrix is internally adjusted to compensate - for unwanted translation, i.e. xForm() returns the smallest image - that contains all the transformed points of the original image. - - \sa scale() TQPixmap::xForm() TQPixmap::trueMatrix() TQWMatrix -*/ -#ifndef TQT_NO_IMAGE_TRANSFORMATION -TQImage TQImage::xForm( const TQWMatrix &matrix ) const -{ - // This function uses the same algorithm as (and steals quite some - // code from) TQPixmap::xForm(). - - if ( isNull() ) - return copy(); - - if ( depth() == 16 ) { - // inefficient - return convertDepth( 32 ).xForm( matrix ); - } - - // source image data - int ws = width(); - int hs = height(); - int sbpl = bytesPerLine(); - uchar *sptr = bits(); - - // target image data - int wd; - int hd; - - int bpp = depth(); - - // compute size of target image - TQWMatrix mat = TQPixmap::trueMatrix( matrix, ws, hs ); - if ( mat.m12() == 0.0F && mat.m21() == 0.0F ) { - if ( mat.m11() == 1.0F && mat.m22() == 1.0F ) // identity matrix - return copy(); - hd = tqRound( mat.m22() * hs ); - wd = tqRound( mat.m11() * ws ); - hd = TQABS( hd ); - wd = TQABS( wd ); - } else { // rotation or shearing - TQPointArray a( TQRect(0, 0, ws, hs) ); - a = mat.map( a ); - TQRect r = a.boundingRect().normalize(); - wd = r.width(); - hd = r.height(); - } - - bool invertible; - mat = mat.invert( &invertible ); // invert matrix - if ( hd == 0 || wd == 0 || !invertible ) // error, return null image - return TQImage(); - - // create target image (some of the code is from TQImage::copy()) - TQImage dImage( wd, hd, depth(), numColors(), bitOrder() ); - - // If the image allocation failed, we need to gracefully abort. - if (dImage.isNull()) - return dImage; - - memcpy( dImage.colorTable(), colorTable(), numColors()*sizeof(TQRgb) ); - dImage.setAlphaBuffer( hasAlphaBuffer() ); - dImage.data->dpmx = dotsPerMeterX(); - dImage.data->dpmy = dotsPerMeterY(); - - switch ( bpp ) { - // initizialize the data - case 1: - memset( dImage.bits(), 0, dImage.numBytes() ); - break; - case 8: - if ( dImage.data->ncols < 256 ) { - // colors are left in the color table, so pick that one as transparent - dImage.setNumColors( dImage.data->ncols+1 ); - dImage.setColor( dImage.data->ncols-1, 0x00 ); - memset( dImage.bits(), dImage.data->ncols-1, dImage.numBytes() ); - } else { - memset( dImage.bits(), 0, dImage.numBytes() ); - } - break; - case 16: - memset( dImage.bits(), 0xff, dImage.numBytes() ); - break; - case 32: - memset( dImage.bits(), 0x00, dImage.numBytes() ); - break; - } - - int type; - if ( bitOrder() == BigEndian ) - type = TQT_XFORM_TYPE_MSBFIRST; - else - type = TQT_XFORM_TYPE_LSBFIRST; - int dbpl = dImage.bytesPerLine(); - qt_xForm_helper( mat, 0, type, bpp, dImage.bits(), dbpl, 0, hd, sptr, sbpl, - ws, hs ); - return dImage; -} -#endif - -/*! - Builds and returns a 1-bpp mask from the alpha buffer in this - image. Returns a \link isNull() null\endlink image if \link - setAlphaBuffer() alpha buffer mode\endlink is disabled. - - See TQPixmap::convertFromImage() for a description of the \a - conversion_flags argument. - - The returned image has little-endian bit order, which you can - convert to big-endianness using convertBitOrder(). - - \sa createHeuristicMask() hasAlphaBuffer() setAlphaBuffer() -*/ -#ifndef TQT_NO_IMAGE_DITHER_TO_1 -TQImage TQImage::createAlphaMask( int conversion_flags ) const -{ - if ( conversion_flags == 1 ) { - // Old code is passing "TRUE". - conversion_flags = TQt::DiffuseAlphaDither; - } - - if ( isNull() || !hasAlphaBuffer() ) - return TQImage(); - - if ( depth() == 1 ) { - // A monochrome pixmap, with alpha channels on those two colors. - // Pretty unlikely, so use less efficient solution. - return convertDepth(8, conversion_flags) - .createAlphaMask( conversion_flags ); - } - - TQImage mask1; - dither_to_1( this, &mask1, conversion_flags, TRUE ); - return mask1; -} -#endif - -#ifndef TQT_NO_IMAGE_HEURISTIC_MASK -/*! - Creates and returns a 1-bpp heuristic mask for this image. It - works by selecting a color from one of the corners, then chipping - away pixels of that color starting at all the edges. - - The four corners vote for which color is to be masked away. In - case of a draw (this generally means that this function is not - applicable to the image), the result is arbitrary. - - The returned image has little-endian bit order, which you can - convert to big-endianness using convertBitOrder(). - - If \a clipTight is TRUE the mask is just large enough to cover the - pixels; otherwise, the mask is larger than the data pixels. - - This function disregards the \link hasAlphaBuffer() alpha buffer - \endlink. - - \sa createAlphaMask() -*/ - -TQImage TQImage::createHeuristicMask( bool clipTight ) const -{ - if ( isNull() ) { - TQImage nullImage; - return nullImage; - } - if ( depth() != 32 ) { - TQImage img32 = convertDepth(32); - return img32.createHeuristicMask(clipTight); - } - -#define PIX(x,y) (*((TQRgb*)scanLine(y)+x) & 0x00ffffff) - - int w = width(); - int h = height(); - TQImage m(w, h, 1, 2, TQImage::LittleEndian); - m.setColor( 0, 0xffffff ); - m.setColor( 1, 0 ); - m.fill( 0xff ); - - TQRgb background = PIX(0,0); - if ( background != PIX(w-1,0) && - background != PIX(0,h-1) && - background != PIX(w-1,h-1) ) { - background = PIX(w-1,0); - if ( background != PIX(w-1,h-1) && - background != PIX(0,h-1) && - PIX(0,h-1) == PIX(w-1,h-1) ) { - background = PIX(w-1,h-1); - } - } - - int x,y; - bool done = FALSE; - uchar *ypp, *ypc, *ypn; - while( !done ) { - done = TRUE; - ypn = m.scanLine(0); - ypc = 0; - for ( y = 0; y < h; y++ ) { - ypp = ypc; - ypc = ypn; - ypn = (y == h-1) ? 0 : m.scanLine(y+1); - TQRgb *p = (TQRgb *)scanLine(y); - for ( x = 0; x < w; x++ ) { - // slowness here - it's possible to do six of these tests - // together in one go. oh well. - if ( ( x == 0 || y == 0 || x == w-1 || y == h-1 || - !(*(ypc + ((x-1) >> 3)) & (1 << ((x-1) & 7))) || - !(*(ypc + ((x+1) >> 3)) & (1 << ((x+1) & 7))) || - !(*(ypp + (x >> 3)) & (1 << (x & 7))) || - !(*(ypn + (x >> 3)) & (1 << (x & 7))) ) && - ( (*(ypc + (x >> 3)) & (1 << (x & 7))) ) && - ( (*p & 0x00ffffff) == background ) ) { - done = FALSE; - *(ypc + (x >> 3)) &= ~(1 << (x & 7)); - } - p++; - } - } - } - - if ( !clipTight ) { - ypn = m.scanLine(0); - ypc = 0; - for ( y = 0; y < h; y++ ) { - ypp = ypc; - ypc = ypn; - ypn = (y == h-1) ? 0 : m.scanLine(y+1); - TQRgb *p = (TQRgb *)scanLine(y); - for ( x = 0; x < w; x++ ) { - if ( (*p & 0x00ffffff) != background ) { - if ( x > 0 ) - *(ypc + ((x-1) >> 3)) |= (1 << ((x-1) & 7)); - if ( x < w-1 ) - *(ypc + ((x+1) >> 3)) |= (1 << ((x+1) & 7)); - if ( y > 0 ) - *(ypp + (x >> 3)) |= (1 << (x & 7)); - if ( y < h-1 ) - *(ypn + (x >> 3)) |= (1 << (x & 7)); - } - p++; - } - } - } - -#undef PIX - - return m; -} -#endif //TQT_NO_IMAGE_HEURISTIC_MASK - -#ifndef TQT_NO_IMAGE_MIRROR -/* - This code is contributed by Philipp Lang, - GeneriCom Software Germany (www.generi.com) - under the terms of the TQPL, Version 1.0 -*/ - -/*! - \overload - - Returns a mirror of the image, mirrored in the horizontal and/or - the vertical direction depending on whether \a horizontal and \a - vertical are set to TRUE or FALSE. The original image is not - changed. - - \sa smoothScale() -*/ -TQImage TQImage::mirror(bool horizontal, bool vertical) const -{ - int w = width(); - int h = height(); - if ( (w <= 1 && h <= 1) || (!horizontal && !vertical) ) - return copy(); - - // Create result image, copy colormap - TQImage result(w, h, depth(), numColors(), bitOrder()); - memcpy(result.colorTable(), colorTable(), numColors()*sizeof(TQRgb)); - result.setAlphaBuffer(hasAlphaBuffer()); - - if (depth() == 1) - w = (w+7)/8; - int dxi = horizontal ? -1 : 1; - int dxs = horizontal ? w-1 : 0; - int dyi = vertical ? -1 : 1; - int dy = vertical ? h-1: 0; - - // 1 bit, 8 bit - if (depth() == 1 || depth() == 8) { - for (int sy = 0; sy < h; sy++, dy += dyi) { - TQ_UINT8* ssl = (TQ_UINT8*)(data->bits[sy]); - TQ_UINT8* dsl = (TQ_UINT8*)(result.data->bits[dy]); - int dx = dxs; - for (int sx = 0; sx < w; sx++, dx += dxi) - dsl[dx] = ssl[sx]; - } - } -#ifndef TQT_NO_IMAGE_TRUECOLOR -#ifndef TQT_NO_IMAGE_16_BIT - // 16 bit - else if (depth() == 16) { - for (int sy = 0; sy < h; sy++, dy += dyi) { - TQ_UINT16* ssl = (TQ_UINT16*)(data->bits[sy]); - TQ_UINT16* dsl = (TQ_UINT16*)(result.data->bits[dy]); - int dx = dxs; - for (int sx = 0; sx < w; sx++, dx += dxi) - dsl[dx] = ssl[sx]; - } - } -#endif - // 32 bit - else if (depth() == 32) { - for (int sy = 0; sy < h; sy++, dy += dyi) { - TQ_UINT32* ssl = (TQ_UINT32*)(data->bits[sy]); - TQ_UINT32* dsl = (TQ_UINT32*)(result.data->bits[dy]); - int dx = dxs; - for (int sx = 0; sx < w; sx++, dx += dxi) - dsl[dx] = ssl[sx]; - } - } -#endif - - // special handling of 1 bit images for horizontal mirroring - if (horizontal && depth() == 1) { - int shift = width() % 8; - for (int y = h-1; y >= 0; y--) { - TQ_UINT8* a0 = (TQ_UINT8*)(result.data->bits[y]); - // Swap bytes - TQ_UINT8* a = a0+dxs; - while (a >= a0) { - *a = bitflip[*a]; - a--; - } - // Shift bits if unaligned - if (shift != 0) { - a = a0+dxs; - TQ_UINT8 c = 0; - if (bitOrder() == TQImage::LittleEndian) { - while (a >= a0) { - TQ_UINT8 nc = *a << shift; - *a = (*a >> (8-shift)) | c; - --a; - c = nc; - } - } else { - while (a >= a0) { - TQ_UINT8 nc = *a >> shift; - *a = (*a << (8-shift)) | c; - --a; - c = nc; - } - } - } - } - } - - return result; -} - -/*! - Returns a TQImage which is a vertically mirrored copy of this - image. The original TQImage is not changed. -*/ - -TQImage TQImage::mirror() const -{ - return mirror(FALSE,TRUE); -} -#endif //TQT_NO_IMAGE_MIRROR - -/*! - Returns a TQImage in which the values of the red and blue - components of all pixels have been swapped, effectively converting - an RGB image to a BGR image. The original TQImage is not changed. -*/ - -TQImage TQImage::swapRGB() const -{ - TQImage res = copy(); - if ( !isNull() ) { -#ifndef TQT_NO_IMAGE_TRUECOLOR - if ( depth() == 32 ) { - for ( int i=0; i < height(); i++ ) { - uint *p = (uint*)scanLine( i ); - uint *q = (uint*)res.scanLine( i ); - uint *end = p + width(); - while ( p < end ) { - *q = ((*p << 16) & 0xff0000) | ((*p >> 16) & 0xff) | - (*p & 0xff00ff00); - p++; - q++; - } - } -#ifndef TQT_NO_IMAGE_16_BIT - } else if ( depth() == 16 ) { - qWarning( "TQImage::swapRGB not implemented for 16bpp" ); -#endif - } else -#endif //TQT_NO_IMAGE_TRUECOLOR - { - uint* p = (uint*)colorTable(); - uint* q = (uint*)res.colorTable(); - if ( p && q ) { - for ( int i=0; i < numColors(); i++ ) { - *q = ((*p << 16) & 0xff0000) | ((*p >> 16) & 0xff) | - (*p & 0xff00ff00); - p++; - q++; - } - } - } - } - return res; -} - -#ifndef TQT_NO_IMAGEIO -/*! - Returns a string that specifies the image format of the file \a - fileName, or 0 if the file cannot be read or if the format is not - recognized. - - The TQImageIO documentation lists the guaranteed supported image - formats, or use TQImage::inputFormats() and TQImage::outputFormats() - to get lists that include the installed formats. - - \sa load() save() -*/ - -const char* TQImage::imageFormat( const TQString &fileName ) -{ - return TQImageIO::imageFormat( fileName ); -} - -/*! - Returns a list of image formats that are supported for image - input. - - \sa outputFormats() inputFormatList() TQImageIO -*/ -TQStrList TQImage::inputFormats() -{ - return TQImageIO::inputFormats(); -} -#ifndef TQT_NO_STRINGLIST -/*! - Returns a list of image formats that are supported for image - input. - - Note that if you want to iterate over the list, you should iterate - over a copy, e.g. - \code - TQStringList list = myImage.inputFormatList(); - TQStringList::Iterator it = list.begin(); - while( it != list.end() ) { - myProcessing( *it ); - ++it; - } - \endcode - - \sa outputFormatList() inputFormats() TQImageIO -*/ -TQStringList TQImage::inputFormatList() -{ - return TQStringList::fromStrList(TQImageIO::inputFormats()); -} - - -/*! - Returns a list of image formats that are supported for image - output. - - Note that if you want to iterate over the list, you should iterate - over a copy, e.g. - \code - TQStringList list = myImage.outputFormatList(); - TQStringList::Iterator it = list.begin(); - while( it != list.end() ) { - myProcessing( *it ); - ++it; - } - \endcode - - \sa inputFormatList() outputFormats() TQImageIO -*/ -TQStringList TQImage::outputFormatList() -{ - return TQStringList::fromStrList(TQImageIO::outputFormats()); -} -#endif //TQT_NO_STRINGLIST - -/*! - Returns a list of image formats that are supported for image - output. - - \sa inputFormats() outputFormatList() TQImageIO -*/ -TQStrList TQImage::outputFormats() -{ - return TQImageIO::outputFormats(); -} - - -/*! - Loads an image from the file \a fileName. Returns TRUE if the - image was successfully loaded; otherwise returns FALSE. - - If \a format is specified, the loader attempts to read the image - using the specified format. If \a format is not specified (which - is the default), the loader reads a few bytes from the header to - guess the file format. - - The TQImageIO documentation lists the supported image formats and - explains how to add extra formats. - - \sa loadFromData() save() imageFormat() TQPixmap::load() TQImageIO -*/ - -bool TQImage::load( const TQString &fileName, const char* format ) -{ - TQImageIO io( fileName, format ); - bool result = io.read(); - if ( result ) - operator=( io.image() ); - return result; -} - -/*! - Loads an image from the first \a len bytes of binary data in \a - buf. Returns TRUE if the image was successfully loaded; otherwise - returns FALSE. - - If \a format is specified, the loader attempts to read the image - using the specified format. If \a format is not specified (which - is the default), the loader reads a few bytes from the header to - guess the file format. - - The TQImageIO documentation lists the supported image formats and - explains how to add extra formats. - - \sa load() save() imageFormat() TQPixmap::loadFromData() TQImageIO -*/ - -bool TQImage::loadFromData( const uchar *buf, uint len, const char *format ) -{ - TQByteArray a; - a.setRawData( (char *)buf, len ); - TQBuffer b( a ); - b.open( IO_ReadOnly ); - TQImageIO io( &b, format ); - bool result = io.read(); - b.close(); - a.resetRawData( (char *)buf, len ); - if ( result ) - operator=( io.image() ); - return result; -} - -/*! - \overload - - Loads an image from the TQByteArray \a buf. -*/ -bool TQImage::loadFromData( TQByteArray buf, const char *format ) -{ - return loadFromData( (const uchar *)(buf.data()), buf.size(), format ); -} - -/*! - Saves the image to the file \a fileName, using the image file - format \a format and a quality factor of \a quality. \a quality - must be in the range 0..100 or -1. Specify 0 to obtain small - compressed files, 100 for large uncompressed files, and -1 (the - default) to use the default settings. - - Returns TRUE if the image was successfully saved; otherwise - returns FALSE. - - \sa load() loadFromData() imageFormat() TQPixmap::save() TQImageIO -*/ - -bool TQImage::save( const TQString &fileName, const char* format, int quality ) const -{ - if ( isNull() ) - return FALSE; // nothing to save - TQImageIO io( fileName, format ); - return doImageIO( &io, quality ); -} - -/*! - \overload - - This function writes a TQImage to the TQIODevice, \a tqdevice. This - can be used, for example, to save an image directly into a - TQByteArray: - \code - TQImage image; - TQByteArray ba; - TQBuffer buffer( ba ); - buffer.open( IO_WriteOnly ); - image.save( &buffer, "PNG" ); // writes image into ba in PNG format - \endcode -*/ - -bool TQImage::save( TQIODevice* tqdevice, const char* format, int quality ) const -{ - if ( isNull() ) - return FALSE; // nothing to save - TQImageIO io( tqdevice, format ); - return doImageIO( &io, quality ); -} - -/* \internal -*/ - -bool TQImage::doImageIO( TQImageIO* io, int quality ) const -{ - if ( !io ) - return FALSE; - io->setImage( *this ); -#if defined(TQT_CHECK_RANGE) - if ( quality > 100 || quality < -1 ) - qWarning( "TQPixmap::save: quality out of range [-1,100]" ); -#endif - if ( quality >= 0 ) - io->setQuality( TQMIN(quality,100) ); - return io->write(); -} -#endif //TQT_NO_IMAGEIO - -/***************************************************************************** - TQImage stream functions - *****************************************************************************/ -#if !defined(TQT_NO_DATASTREAM) && !defined(TQT_NO_IMAGEIO) -/*! - \relates TQImage - - Writes the image \a image to the stream \a s as a PNG image, or as a - BMP image if the stream's version is 1. - - Note that writing the stream to a file will not produce a valid image file. - - \sa TQImage::save() - \link datastreamformat.html Format of the TQDataStream operators \endlink -*/ - -TQDataStream &operator<<( TQDataStream &s, const TQImage &image ) -{ - if ( s.version() >= 5 ) { - if ( image.isNull() ) { - s << (TQ_INT32) 0; // null image marker - return s; - } else { - s << (TQ_INT32) 1; - // continue ... - } - } - TQImageIO io; - io.setIODevice( s.tqdevice() ); - if ( s.version() == 1 ) - io.setFormat( "BMP" ); - else - io.setFormat( "PNG" ); - - io.setImage( image ); - io.write(); - return s; -} - -/*! - \relates TQImage - - Reads an image from the stream \a s and stores it in \a image. - - \sa TQImage::load() - \link datastreamformat.html Format of the TQDataStream operators \endlink -*/ - -TQDataStream &operator>>( TQDataStream &s, TQImage &image ) -{ - if ( s.version() >= 5 ) { - TQ_INT32 nullMarker; - s >> nullMarker; - if ( !nullMarker ) { - image = TQImage(); // null image - return s; - } - } - TQImageIO io( s.tqdevice(), 0 ); - if ( io.read() ) - image = io.image(); - return s; -} -#endif - -/***************************************************************************** - Standard image io handlers (defined below) - *****************************************************************************/ - -// standard image io handlers (defined below) -#ifndef TQT_NO_IMAGEIO_BMP -static void read_bmp_image( TQImageIO * ); -static void write_bmp_image( TQImageIO * ); -#endif -#ifndef TQT_NO_IMAGEIO_PPM -static void read_pbm_image( TQImageIO * ); -static void write_pbm_image( TQImageIO * ); -#endif -#ifndef TQT_NO_IMAGEIO_XBM -static void read_xbm_image( TQImageIO * ); -static void write_xbm_image( TQImageIO * ); -#endif -#ifndef TQT_NO_IMAGEIO_XPM -static void read_xpm_image( TQImageIO * ); -static void write_xpm_image( TQImageIO * ); -#endif - -#ifndef TQT_NO_ASYNC_IMAGE_IO -static void read_async_image( TQImageIO * ); // Not in table of handlers -#endif - -/***************************************************************************** - Misc. utility functions - *****************************************************************************/ -#if !defined(TQT_NO_IMAGEIO_XPM) || !defined(TQT_NO_IMAGEIO_XBM) -static TQString fbname( const TQString &fileName ) // get file basename (sort of) -{ - TQString s = fileName; - if ( !s.isEmpty() ) { - int i; - if ( (i = s.findRev('/')) >= 0 ) - s = s.mid( i ); - if ( (i = s.findRev('\\')) >= 0 ) - s = s.mid( i ); - TQRegExp r( TQString::tqfromLatin1("[a-zA-Z][a-zA-Z0-9_]*") ); - int p = r.search( s ); - if ( p == -1 ) - s.truncate( 0 ); - else - s = s.mid( p, r.matchedLength() ); - } - if ( s.isEmpty() ) - s = TQString::tqfromLatin1( "dummy" ); - return s; -} -#endif - -#ifndef TQT_NO_IMAGEIO_BMP -static void swapPixel01( TQImage *image ) // 1-bpp: swap 0 and 1 pixels -{ - int i; - if ( image->depth() == 1 && image->numColors() == 2 ) { - register uint *p = (uint *)image->bits(); - int nbytes = image->numBytes(); - for ( i=0; icolor(0); // swap color 0 and 1 - image->setColor( 0, image->color(1) ); - image->setColor( 1, t ); - } -} -#endif - - -/***************************************************************************** - TQImageIO member functions - *****************************************************************************/ - -/*! - \class TQImageIO tqimage.h - - \brief The TQImageIO class contains parameters for loading and - saving images. - - \ingroup images - \ingroup graphics - \ingroup io - - TQImageIO contains a TQIODevice object that is used for image data - I/O. The programmer can install new image file formats in addition - to those that TQt provides. - - TQt currently supports the following image file formats: PNG, BMP, - XBM, XPM and PNM. It may also support JPEG, MNG and GIF, if - specially configured during compilation. The different PNM formats - are: PBM (P1 or P4), PGM (P2 or P5), and PPM (P3 or P6). - - You don't normally need to use this class; TQPixmap::load(), - TQPixmap::save(), and TQImage contain sufficient functionality. - - For image files that contain sequences of images, only the first - is read. See TQMovie for loading multiple images. - - PBM, PGM, and PPM format \e output is always in the more condensed - raw format. PPM and PGM files with more than 256 levels of - intensity are scaled down when reading. - - \warning If you are in a country which recognizes software patents - and in which Unisys holds a patent on LZW compression and/or - decompression and you want to use GIF, Unisys may require you to - license the technology. Such countries include Canada, Japan, the - USA, France, Germany, Italy and the UK. - - GIF support may be removed completely in a future version of TQt. - We recommend using the PNG format. - - \sa TQImage TQPixmap TQFile TQMovie -*/ - -#ifndef TQT_NO_IMAGEIO -struct TQImageIOData -{ - const char *parameters; - int quality; - float gamma; -}; - -/*! - Constructs a TQImageIO object with all parameters set to zero. -*/ - -TQImageIO::TQImageIO() -{ - init(); -} - -/*! - Constructs a TQImageIO object with the I/O tqdevice \a ioDevice and a - \a format tag. -*/ - -TQImageIO::TQImageIO( TQIODevice *ioDevice, const char *format ) - : frmt(format) -{ - init(); - iodev = ioDevice; -} - -/*! - Constructs a TQImageIO object with the file name \a fileName and a - \a format tag. -*/ - -TQImageIO::TQImageIO( const TQString &fileName, const char* format ) - : frmt(format), fname(fileName) -{ - init(); -} - -/*! - Contains initialization common to all TQImageIO constructors. -*/ - -void TQImageIO::init() -{ - d = new TQImageIOData(); - d->parameters = 0; - d->quality = -1; // default quality of the current format - d->gamma=0.0f; - iostat = 0; - iodev = 0; -} - -/*! - Destroys the object and all related data. -*/ - -TQImageIO::~TQImageIO() -{ - if ( d->parameters ) - delete [] (char*)d->parameters; - delete d; -} - - -/***************************************************************************** - TQImageIO image handler functions - *****************************************************************************/ - -class TQImageHandler -{ -public: - TQImageHandler( const char *f, const char *h, const TQCString& fl, - image_io_handler r, image_io_handler w ); - TQCString format; // image format - TQRegExp header; // image header pattern - enum TMode { Untranslated=0, TranslateIn, TranslateInOut } text_mode; - image_io_handler read_image; // image read function - image_io_handler write_image; // image write function - bool obsolete; // support not "published" -}; - -TQImageHandler::TQImageHandler( const char *f, const char *h, const TQCString& fl, - image_io_handler r, image_io_handler w ) - : format(f), header(TQString::tqfromLatin1(h)) -{ - text_mode = Untranslated; - if ( fl.contains('t') ) - text_mode = TranslateIn; - else if ( fl.contains('T') ) - text_mode = TranslateInOut; - obsolete = fl.contains('O'); - read_image = r; - write_image = w; -} - -typedef TQPtrList TQIHList;// list of image handlers -static TQIHList *imageHandlers = 0; -#ifndef TQT_NO_COMPONENT -static TQPluginManager *plugin_manager = 0; -#else -static void *plugin_manager = 0; -#endif - -void qt_init_image_plugins() -{ -#ifndef TQT_NO_COMPONENT - if ( plugin_manager ) - return; - - plugin_manager = new TQPluginManager( IID_TQImageFormat, TQApplication::libraryPaths(), "/imageformats" ); - - TQStringList features = plugin_manager->featureList(); - TQStringList::Iterator it = features.begin(); - while ( it != features.end() ) { - TQString str = *it; - ++it; - TQInterfacePtr iface; - plugin_manager->queryInterface( str, &iface ); - if ( iface ) - iface->installIOHandler( str ); - } -#endif -} - -static void cleanup() -{ - // make sure that image handlers are delete before plugin manager - delete imageHandlers; - imageHandlers = 0; -#ifndef TQT_NO_COMPONENT - delete plugin_manager; - plugin_manager = 0; -#endif -} - -void qt_init_image_handlers() // initialize image handlers -{ - if ( !imageHandlers ) { - imageHandlers = new TQIHList; - TQ_CHECK_PTR( imageHandlers ); - imageHandlers->setAutoDelete( TRUE ); - qAddPostRoutine( cleanup ); -#ifndef TQT_NO_IMAGEIO_BMP - TQImageIO::defineIOHandler( "BMP", "^BM", 0, - read_bmp_image, write_bmp_image ); -#endif -#ifndef TQT_NO_IMAGEIO_PPM - TQImageIO::defineIOHandler( "PBM", "^P1", "t", - read_pbm_image, write_pbm_image ); - TQImageIO::defineIOHandler( "PBMRAW", "^P4", "O", - read_pbm_image, write_pbm_image ); - TQImageIO::defineIOHandler( "PGM", "^P2", "t", - read_pbm_image, write_pbm_image ); - TQImageIO::defineIOHandler( "PGMRAW", "^P5", "O", - read_pbm_image, write_pbm_image ); - TQImageIO::defineIOHandler( "PPM", "^P3", "t", - read_pbm_image, write_pbm_image ); - TQImageIO::defineIOHandler( "PPMRAW", "^P6", "O", - read_pbm_image, write_pbm_image ); -#endif -#ifndef TQT_NO_IMAGEIO_XBM - TQImageIO::defineIOHandler( "XBM", "^((/\\*(?!.XPM.\\*/))|#define)", "T", - read_xbm_image, write_xbm_image ); -#endif -#ifndef TQT_NO_IMAGEIO_XPM - TQImageIO::defineIOHandler( "XPM", "/\\*.XPM.\\*/", "T", - read_xpm_image, write_xpm_image ); -#endif -#ifndef TQT_NO_IMAGEIO_MNG - qInitMngIO(); -#endif -#ifndef TQT_NO_IMAGEIO_PNG - qInitPngIO(); -#endif -#ifndef TQT_NO_IMAGEIO_JPEG - qInitJpegIO(); -#endif - } -} - -static TQImageHandler *get_image_handler( const char *format ) -{ // get pointer to handler - qt_init_image_handlers(); - qt_init_image_plugins(); - register TQImageHandler *p = imageHandlers->first(); - while ( p ) { // traverse list - if ( p->format == format ) - return p; - p = imageHandlers->next(); - } - return 0; // no such handler -} - - -/*! - Defines an image I/O handler for the image format called \a - format, which is recognized using the \link tqregexp.html#details - regular expression\endlink \a header, read using \a readImage and - written using \a writeImage. - - \a flags is a string of single-character flags for this format. - The only flag defined currently is T (upper case), so the only - legal value for \a flags are "T" and the empty string. The "T" - flag means that the image file is a text file, and TQt should treat - all newline conventions as equivalent. (XPM files and some PPM - files are text files for example.) - - \a format is used to select a handler to write a TQImage; \a header - is used to select a handler to read an image file. - - If \a readImage is a null pointer, the TQImageIO will not be able - to read images in \a format. If \a writeImage is a null pointer, - the TQImageIO will not be able to write images in \a format. If - both are null, the TQImageIO object is valid but useless. - - Example: - \code - void readGIF( TQImageIO *image ) - { - // read the image using the image->ioDevice() - } - - void writeGIF( TQImageIO *image ) - { - // write the image using the image->ioDevice() - } - - // add the GIF image handler - - TQImageIO::defineIOHandler( "GIF", - "^GIF[0-9][0-9][a-z]", - 0, - readGIF, - writeGIF ); - \endcode - - Before the regex test, all the 0 bytes in the file header are - converted to 1 bytes. This is done because when TQt was - ASCII-based, TQRegExp could not handle 0 bytes in strings. - - The regexp is only applied on the first 14 bytes of the file. - - Note that TQt assumes that there is only one handler per format; if - two handlers support the same format, TQt will choose one - arbitrarily. It is not possible to have one handler support - reading, and another support writing. -*/ - -void TQImageIO::defineIOHandler( const char *format, - const char *header, - const char *flags, - image_io_handler readImage, - image_io_handler writeImage ) -{ - qt_init_image_handlers(); - TQImageHandler *p; - p = new TQImageHandler( format, header, flags, - readImage, writeImage ); - TQ_CHECK_PTR( p ); - imageHandlers->insert( 0, p ); -} - - -/***************************************************************************** - TQImageIO normal member functions - *****************************************************************************/ - -/*! - \fn const TQImage &TQImageIO::image() const - - Returns the image currently set. - - \sa setImage() -*/ - -/*! - \fn int TQImageIO::status() const - - Returns the image's IO status. A non-zero value indicates an - error, whereas 0 means that the IO operation was successful. - - \sa setqStatus() -*/ - -/*! - \fn const char *TQImageIO::format() const - - Returns the image format string or 0 if no format has been - explicitly set. -*/ - -/*! - \fn TQIODevice *TQImageIO::ioDevice() const - - Returns the IO tqdevice currently set. - - \sa setIODevice() -*/ - -/*! - \fn TQString TQImageIO::fileName() const - - Returns the file name currently set. - - \sa setFileName() -*/ - -/*! - \fn TQString TQImageIO::description() const - - Returns the image description string. - - \sa setDescription() -*/ - - -/*! - Sets the image to \a image. - - \sa image() -*/ - -void TQImageIO::setImage( const TQImage &image ) -{ - im = image; -} - -/*! - Sets the image IO status to \a status. A non-zero value indicates - an error, whereas 0 means that the IO operation was successful. - - \sa status() -*/ - -void TQImageIO::setqStatus( int status ) -{ - iostat = status; -} - -/*! - Sets the image format to \a format for the image to be read or - written. - - It is necessary to specify a format before writing an image, but - it is not necessary to specify a format before reading an image. - - If no format has been set, TQt guesses the image format before - reading it. If a format is set the image will only be read if it - has that format. - - \sa read() write() format() -*/ - -void TQImageIO::setFormat( const char *format ) -{ - frmt = format; -} - -/*! - Sets the IO tqdevice to be used for reading or writing an image. - - Setting the IO tqdevice allows images to be read/written to any - block-oriented TQIODevice. - - If \a ioDevice is not null, this IO tqdevice will override file name - settings. - - \sa setFileName() -*/ - -void TQImageIO::setIODevice( TQIODevice *ioDevice ) -{ - iodev = ioDevice; -} - -/*! - Sets the name of the file to read or write an image from to \a - fileName. - - \sa setIODevice() -*/ - -void TQImageIO::setFileName( const TQString &fileName ) -{ - fname = fileName; -} - -/*! - Returns the quality of the written image, related to the - compression ratio. - - \sa setQuality() TQImage::save() -*/ - -int TQImageIO::quality() const -{ - return d->quality; -} - -/*! - Sets the quality of the written image to \a q, related to the - compression ratio. - - \a q must be in the range -1..100. Specify 0 to obtain small - compressed files, 100 for large uncompressed files. (-1 signifies - the default compression.) - - \sa quality() TQImage::save() -*/ - -void TQImageIO::setQuality( int q ) -{ - d->quality = q; -} - -/*! - Returns the image's parameters string. - - \sa setParameters() -*/ - -const char *TQImageIO::parameters() const -{ - return d->parameters; -} - -/*! - Sets the image's parameter string to \a parameters. This is for - image handlers that require special parameters. - - Although the current image formats supported by TQt ignore the - parameters string, it may be used in future extensions or by - contributions (for example, JPEG). - - \sa parameters() -*/ - -void TQImageIO::setParameters( const char *parameters ) -{ - if ( d && d->parameters ) - delete [] (char*)d->parameters; - d->parameters = qstrdup( parameters ); -} - -/*! - Sets the gamma value at which the image will be viewed to \a - gamma. If the image format stores a gamma value for which the - image is intended to be used, then this setting will be used to - modify the image. Setting to 0.0 will disable gamma correction - (i.e. any specification in the file will be ignored). - - The default value is 0.0. - - \sa gamma() -*/ -void TQImageIO::setGamma( float gamma ) -{ - d->gamma=gamma; -} - -/*! - Returns the gamma value at which the image will be viewed. - - \sa setGamma() -*/ -float TQImageIO::gamma() const -{ - return d->gamma; -} - -/*! - Sets the image description string for image handlers that support - image descriptions to \a description. - - Currently, no image format supported by TQt uses the description - string. -*/ - -void TQImageIO::setDescription( const TQString &description ) -{ - descr = description; -} - - -/*! - Returns a string that specifies the image format of the file \a - fileName, or null if the file cannot be read or if the format is - not recognized. -*/ - -const char* TQImageIO::imageFormat( const TQString &fileName ) -{ - TQFile file( fileName ); - if ( !file.open(IO_ReadOnly) ) - return 0; - const char* format = imageFormat( &file ); - file.close(); - return format; -} - -/*! - \overload - - Returns a string that specifies the image format of the image read - from IO tqdevice \a d, or 0 if the tqdevice cannot be read or if the - format is not recognized. - - Make sure that \a d is at the right position in the tqdevice (for - example, at the beginning of the file). - - \sa TQIODevice::at() -*/ - -const char *TQImageIO::imageFormat( TQIODevice *d ) -{ - // if you change this change the documentation for defineIOHandler() - const int buflen = 14; - - char buf[buflen]; - char buf2[buflen]; - qt_init_image_handlers(); - qt_init_image_plugins(); - int pos = d->at(); // save position - int rdlen = d->readBlock( buf, buflen ); // read a few bytes - - if ( rdlen != buflen ) - return 0; - - memcpy( buf2, buf, buflen ); - - const char* format = 0; - for ( int n = 0; n < rdlen; n++ ) - if ( buf[n] == '\0' ) - buf[n] = '\001'; - if ( d->status() == IO_Ok && rdlen > 0 ) { - buf[rdlen - 1] = '\0'; - TQString bufStr = TQString::tqfromLatin1(buf); - TQImageHandler *p = imageHandlers->first(); - int bestMatch = -1; - while ( p ) { - if ( p->read_image && p->header.search(bufStr) != -1 ) { - // try match with header if a read function is available - if (p->header.matchedLength() > bestMatch) { - // keep looking for best match - format = p->format; - bestMatch = p->header.matchedLength(); - } - } - p = imageHandlers->next(); - } - } - d->at( pos ); // restore position -#ifndef TQT_NO_ASYNC_IMAGE_IO - if ( !format ) - format = TQImageDecoder::formatName( (uchar*)buf2, rdlen ); -#endif - - return format; -} - -/*! - Returns a sorted list of image formats that are supported for - image input. -*/ -TQStrList TQImageIO::inputFormats() -{ - TQStrList result; - - qt_init_image_handlers(); - qt_init_image_plugins(); - -#ifndef TQT_NO_ASYNC_IMAGE_IO - // Include asynchronous loaders first. - result = TQImageDecoder::inputFormats(); -#endif - - TQImageHandler *p = imageHandlers->first(); - while ( p ) { - if ( p->read_image - && !p->obsolete - && !result.contains(p->format) ) - { - result.inSort(p->format); - } - p = imageHandlers->next(); - } - - return result; -} - -/*! - Returns a sorted list of image formats that are supported for - image output. -*/ -TQStrList TQImageIO::outputFormats() -{ - TQStrList result; - - qt_init_image_handlers(); - qt_init_image_plugins(); - - // Include asynchronous writers (!) first. - // (None) - - TQImageHandler *p = imageHandlers->first(); - while ( p ) { - if ( p->write_image - && !p->obsolete - && !result.contains(p->format) ) - { - result.inSort(p->format); - } - p = imageHandlers->next(); - } - - return result; -} - - - -/*! - Reads an image into memory and returns TRUE if the image was - successfully read; otherwise returns FALSE. - - Before reading an image you must set an IO tqdevice or a file name. - If both an IO tqdevice and a file name have been set, the IO tqdevice - will be used. - - Setting the image file format string is optional. - - Note that this function does \e not set the \link format() - format\endlink used to read the image. If you need that - information, use the imageFormat() static functions. - - Example: - - \code - TQImageIO iio; - TQPixmap pixmap; - iio.setFileName( "vegeburger.bmp" ); - if ( image.read() ) // ok - pixmap = iio.image(); // convert to pixmap - \endcode - - \sa setIODevice() setFileName() setFormat() write() TQPixmap::load() -*/ - -bool TQImageIO::read() -{ - TQFile file; - const char *image_format; - TQImageHandler *h; - - if ( iodev ) { // read from io tqdevice - // ok, already open - } else if ( !fname.isEmpty() ) { // read from file - file.setName( fname ); - if ( !file.open(IO_ReadOnly) ) - return FALSE; // cannot open file - iodev = &file; - } else { // no file name or io tqdevice - return FALSE; - } - if (frmt.isEmpty()) { - // Try to guess format - image_format = imageFormat( iodev ); // get image format - if ( !image_format ) { - if ( file.isOpen() ) { // unknown format - file.close(); - iodev = 0; - } - return FALSE; - } - } else { - image_format = frmt; - } - - h = get_image_handler( image_format ); - if ( file.isOpen() ) { -#if !defined(TQ_OS_UNIX) - if ( h && h->text_mode ) { // reopen in translated mode - file.close(); - file.open( IO_ReadOnly | IO_Translate ); - } - else -#endif - file.at( 0 ); // position to start - } - iostat = 1; // assume error - - if ( h && h->read_image ) { - (*h->read_image)( this ); - } -#ifndef TQT_NO_ASYNC_IMAGE_IO - else { - // Format name, but no handler - must be an asychronous reader - read_async_image( this ); - } -#endif - - if ( file.isOpen() ) { // image was read using file - file.close(); - iodev = 0; - } - return iostat == 0; // image successfully read? -} - - -/*! - Writes an image to an IO tqdevice and returns TRUE if the image was - successfully written; otherwise returns FALSE. - - Before writing an image you must set an IO tqdevice or a file name. - If both an IO tqdevice and a file name have been set, the IO tqdevice - will be used. - - The image will be written using the specified image format. - - Example: - \code - TQImageIO iio; - TQImage im; - im = pixmap; // convert to image - iio.setImage( im ); - iio.setFileName( "vegeburger.bmp" ); - iio.setFormat( "BMP" ); - if ( iio.write() ) - // returned TRUE if written successfully - \endcode - - \sa setIODevice() setFileName() setFormat() read() TQPixmap::save() -*/ - -bool TQImageIO::write() -{ - if ( frmt.isEmpty() ) - return FALSE; - TQImageHandler *h = get_image_handler( frmt ); - if ( !h && !plugin_manager) { - qt_init_image_plugins(); - h = get_image_handler( frmt ); - } - if ( !h || !h->write_image ) { -#if defined(TQT_CHECK_RANGE) - qWarning( "TQImageIO::write: No such image format handler: %s", - format() ); -#endif - return FALSE; - } - TQFile file; - if ( !iodev && !fname.isEmpty() ) { - file.setName( fname ); - bool translate = h->text_mode==TQImageHandler::TranslateInOut; - int fmode = translate ? IO_WriteOnly|IO_Translate : IO_WriteOnly; - if ( !file.open(fmode) ) // couldn't create file - return FALSE; - iodev = &file; - } - iostat = 1; - (*h->write_image)( this ); - if ( file.isOpen() ) { // image was written using file - file.close(); - iodev = 0; - } - return iostat == 0; // image successfully written? -} -#endif //TQT_NO_IMAGEIO - -#ifndef TQT_NO_IMAGEIO_BMP - -/***************************************************************************** - BMP (DIB) image read/write functions - *****************************************************************************/ - -const int BMP_FILEHDR_SIZE = 14; // size of BMP_FILEHDR data - -struct BMP_FILEHDR { // BMP file header - char bfType[2]; // "BM" - TQ_INT32 bfSize; // size of file - TQ_INT16 bfReserved1; - TQ_INT16 bfReserved2; - TQ_INT32 bfOffBits; // pointer to the pixmap bits -}; - -TQDataStream &operator>>( TQDataStream &s, BMP_FILEHDR &bf ) -{ // read file header - s.readRawBytes( bf.bfType, 2 ); - s >> bf.bfSize >> bf.bfReserved1 >> bf.bfReserved2 >> bf.bfOffBits; - return s; -} - -TQDataStream &operator<<( TQDataStream &s, const BMP_FILEHDR &bf ) -{ // write file header - s.writeRawBytes( bf.bfType, 2 ); - s << bf.bfSize << bf.bfReserved1 << bf.bfReserved2 << bf.bfOffBits; - return s; -} - - -const int BMP_OLD = 12; // old Windows/OS2 BMP size -const int BMP_WIN = 40; // new Windows BMP size -const int BMP_OS2 = 64; // new OS/2 BMP size - -const int BMP_RGB = 0; // no compression -const int BMP_RLE8 = 1; // run-length encoded, 8 bits -const int BMP_RLE4 = 2; // run-length encoded, 4 bits -const int BMP_BITFIELDS = 3; // RGB values encoded in data as bit-fields - -struct BMP_INFOHDR { // BMP information header - TQ_INT32 biSize; // size of this struct - TQ_INT32 biWidth; // pixmap width - TQ_INT32 biHeight; // pixmap height - TQ_INT16 biPlanes; // should be 1 - TQ_INT16 biBitCount; // number of bits per pixel - TQ_INT32 biCompression; // compression method - TQ_INT32 biSizeImage; // size of image - TQ_INT32 biXPelsPerMeter; // horizontal resolution - TQ_INT32 biYPelsPerMeter; // vertical resolution - TQ_INT32 biClrUsed; // number of colors used - TQ_INT32 biClrImportant; // number of important colors -}; - - -TQDataStream &operator>>( TQDataStream &s, BMP_INFOHDR &bi ) -{ - s >> bi.biSize; - if ( bi.biSize == BMP_WIN || bi.biSize == BMP_OS2 ) { - s >> bi.biWidth >> bi.biHeight >> bi.biPlanes >> bi.biBitCount; - s >> bi.biCompression >> bi.biSizeImage; - s >> bi.biXPelsPerMeter >> bi.biYPelsPerMeter; - s >> bi.biClrUsed >> bi.biClrImportant; - } - else { // probably old Windows format - TQ_INT16 w, h; - s >> w >> h >> bi.biPlanes >> bi.biBitCount; - bi.biWidth = w; - bi.biHeight = h; - bi.biCompression = BMP_RGB; // no compression - bi.biSizeImage = 0; - bi.biXPelsPerMeter = bi.biYPelsPerMeter = 0; - bi.biClrUsed = bi.biClrImportant = 0; - } - return s; -} - -TQDataStream &operator<<( TQDataStream &s, const BMP_INFOHDR &bi ) -{ - s << bi.biSize; - s << bi.biWidth << bi.biHeight; - s << bi.biPlanes; - s << bi.biBitCount; - s << bi.biCompression; - s << bi.biSizeImage; - s << bi.biXPelsPerMeter << bi.biYPelsPerMeter; - s << bi.biClrUsed << bi.biClrImportant; - return s; -} - -static -int calc_shift(int mask) -{ - int result = 0; - while (!(mask & 1)) { - result++; - mask >>= 1; - } - return result; -} - -static -bool read_dib( TQDataStream& s, int offset, int startpos, TQImage& image ) -{ - BMP_INFOHDR bi; - TQIODevice* d = s.tqdevice(); - - s >> bi; // read BMP info header - if ( d->atEnd() ) // end of stream/file - return FALSE; -#if 0 - qDebug( "offset...........%d", offset ); - qDebug( "startpos.........%d", startpos ); - qDebug( "biSize...........%d", bi.biSize ); - qDebug( "biWidth..........%d", bi.biWidth ); - qDebug( "biHeight.........%d", bi.biHeight ); - qDebug( "biPlanes.........%d", bi.biPlanes ); - qDebug( "biBitCount.......%d", bi.biBitCount ); - qDebug( "biCompression....%d", bi.biCompression ); - qDebug( "biSizeImage......%d", bi.biSizeImage ); - qDebug( "biXPelsPerMeter..%d", bi.biXPelsPerMeter ); - qDebug( "biYPelsPerMeter..%d", bi.biYPelsPerMeter ); - qDebug( "biClrUsed........%d", bi.biClrUsed ); - qDebug( "biClrImportant...%d", bi.biClrImportant ); -#endif - int w = bi.biWidth, h = bi.biHeight, nbits = bi.biBitCount; - int t = bi.biSize, comp = bi.biCompression; - int red_mask, green_mask, blue_mask; - int red_shift = 0; - int green_shift = 0; - int blue_shift = 0; - int red_scale = 0; - int green_scale = 0; - int blue_scale = 0; - - if ( !(nbits == 1 || nbits == 4 || nbits == 8 || nbits == 16 || nbits == 24 || nbits == 32) || - bi.biPlanes != 1 || comp > BMP_BITFIELDS ) - return FALSE; // weird BMP image - if ( !(comp == BMP_RGB || (nbits == 4 && comp == BMP_RLE4) || - (nbits == 8 && comp == BMP_RLE8) || ((nbits == 16 || nbits == 32) && comp == BMP_BITFIELDS)) ) - return FALSE; // weird compression type - - int ncols; - int depth; - switch ( nbits ) { - case 32: - case 24: - case 16: - depth = 32; - break; - case 8: - case 4: - depth = 8; - break; - default: - depth = 1; - } - if ( depth == 32 ) // there's no colormap - ncols = 0; - else // # colors used - ncols = bi.biClrUsed ? bi.biClrUsed : 1 << nbits; - - image.create( w, h, depth, ncols, nbits == 1 ? - TQImage::BigEndian : TQImage::IgnoreEndian ); - if ( image.isNull() ) // could not create image - return FALSE; - - image.setDotsPerMeterX( bi.biXPelsPerMeter ); - image.setDotsPerMeterY( bi.biYPelsPerMeter ); - - d->at( startpos + BMP_FILEHDR_SIZE + bi.biSize ); // goto start of colormap - - if ( ncols > 0 ) { // read color table - uchar rgb[4]; - int rgb_len = t == BMP_OLD ? 3 : 4; - for ( int i=0; ireadBlock( (char *)rgb, rgb_len ) != rgb_len ) - return FALSE; - image.setColor( i, tqRgb(rgb[2],rgb[1],rgb[0]) ); - if ( d->atEnd() ) // truncated file - return FALSE; - } - } else if (comp == BMP_BITFIELDS && (nbits == 16 || nbits == 32)) { - if ( (TQ_ULONG)d->readBlock( (char *)&red_mask, sizeof(red_mask) ) != sizeof(red_mask) ) - return FALSE; - if ( (TQ_ULONG)d->readBlock( (char *)&green_mask, sizeof(green_mask) ) != sizeof(green_mask) ) - return FALSE; - if ( (TQ_ULONG)d->readBlock( (char *)&blue_mask, sizeof(blue_mask) ) != sizeof(blue_mask) ) - return FALSE; - red_shift = calc_shift(red_mask); - red_scale = 256 / ((red_mask >> red_shift) + 1); - green_shift = calc_shift(green_mask); - green_scale = 256 / ((green_mask >> green_shift) + 1); - blue_shift = calc_shift(blue_mask); - blue_scale = 256 / ((blue_mask >> blue_shift) + 1); - } else if (comp == BMP_RGB && (nbits == 24 || nbits == 32)) { - blue_mask = 0x000000ff; - green_mask = 0x0000ff00; - red_mask = 0x00ff0000; - blue_shift = 0; - green_shift = 8; - red_shift = 16; - blue_scale = green_scale = red_scale = 1; - } else if (comp == BMP_RGB && nbits == 16) // don't support RGB values for 15/16 bpp - return FALSE; - - // offset can be bogus, be careful - if (offset>=0 && startpos + offset > (TQ_LONG)d->at() ) - d->at( startpos + offset ); // start of image data - - int bpl = image.bytesPerLine(); -#ifdef TQ_WS_TQWS - // - // Guess the number of bytes-per-line if we don't know how much - // image data is in the file (bogus image ?). - // - int bmpbpl = bi.biSizeImage > 0 ? - bi.biSizeImage / bi.biHeight : - (d->size() - offset) / bi.biHeight; - int pad = bmpbpl-bpl; -#endif - uchar **line = image.jumpTable(); - - if ( nbits == 1 ) { // 1 bit BMP image - while ( --h >= 0 ) { - if ( d->readBlock((char*)line[h],bpl) != bpl ) - break; -#ifdef TQ_WS_TQWS - if ( pad > 0 ) - d->at(d->at()+pad); -#endif - } - if ( ncols == 2 && tqGray(image.color(0)) < tqGray(image.color(1)) ) - swapPixel01( &image ); // pixel 0 is white! - } - - else if ( nbits == 4 ) { // 4 bit BMP image - int buflen = ((w+7)/8)*4; - uchar *buf = new uchar[buflen]; - TQ_CHECK_PTR( buf ); - if ( comp == BMP_RLE4 ) { // run length compression - int x=0, y=0, b, c, i; - register uchar *p = line[h-1]; - uchar *endp = line[h-1]+w; - while ( y < h ) { - if ( (b=d->getch()) == EOF ) - break; - if ( b == 0 ) { // escape code - switch ( (b=d->getch()) ) { - case 0: // end of line - x = 0; - y++; - p = line[h-y-1]; - break; - case 1: // end of image - case EOF: // end of file - y = h; // exit loop - break; - case 2: // delta (jump) - x += d->getch(); - y += d->getch(); - - // Protection - if ( (uint)x >= (uint)w ) - x = w-1; - if ( (uint)y >= (uint)h ) - y = h-1; - - p = line[h-y-1] + x; - break; - default: // absolute mode - // Protection - if ( p + b > endp ) - b = endp-p; - - i = (c = b)/2; - while ( i-- ) { - b = d->getch(); - *p++ = b >> 4; - *p++ = b & 0x0f; - } - if ( c & 1 ) - *p++ = d->getch() >> 4; - if ( (((c & 3) + 1) & 2) == 2 ) - d->getch(); // align on word boundary - x += c; - } - } else { // encoded mode - // Protection - if ( p + b > endp ) - b = endp-p; - - i = (c = b)/2; - b = d->getch(); // 2 pixels to be repeated - while ( i-- ) { - *p++ = b >> 4; - *p++ = b & 0x0f; - } - if ( c & 1 ) - *p++ = b >> 4; - x += c; - } - } - } else if ( comp == BMP_RGB ) { // no compression - while ( --h >= 0 ) { - if ( d->readBlock((char*)buf,buflen) != buflen ) - break; - register uchar *p = line[h]; - uchar *b = buf; - for ( int i=0; i> 4; - *p++ = *b++ & 0x0f; - } - if ( w & 1 ) // the last nibble - *p = *b >> 4; - } - } - delete [] buf; - } - - else if ( nbits == 8 ) { // 8 bit BMP image - if ( comp == BMP_RLE8 ) { // run length compression - int x=0, y=0, b; - register uchar *p = line[h-1]; - const uchar *endp = line[h-1]+w; - while ( y < h ) { - if ( (b=d->getch()) == EOF ) - break; - if ( b == 0 ) { // escape code - switch ( (b=d->getch()) ) { - case 0: // end of line - x = 0; - y++; - p = line[h-y-1]; - break; - case 1: // end of image - case EOF: // end of file - y = h; // exit loop - break; - case 2: // delta (jump) - x += d->getch(); - y += d->getch(); - - // Protection - if ( (uint)x >= (uint)w ) - x = w-1; - if ( (uint)y >= (uint)h ) - y = h-1; - - p = line[h-y-1] + x; - break; - default: // absolute mode - // Protection - if ( p + b > endp ) - b = endp-p; - - if ( d->readBlock( (char *)p, b ) != b ) - return FALSE; - if ( (b & 1) == 1 ) - d->getch(); // align on word boundary - x += b; - p += b; - } - } else { // encoded mode - // Protection - if ( p + b > endp ) - b = endp-p; - - memset( p, d->getch(), b ); // repeat pixel - x += b; - p += b; - } - } - } else if ( comp == BMP_RGB ) { // uncompressed - while ( --h >= 0 ) { - if ( d->readBlock((char *)line[h],bpl) != bpl ) - break; -#ifdef TQ_WS_TQWS - if ( pad > 0 ) - d->at(d->at()+pad); -#endif - } - } - } - - else if ( nbits == 16 || nbits == 24 || nbits == 32 ) { // 16,24,32 bit BMP image - register TQRgb *p; - TQRgb *end; - uchar *buf24 = new uchar[bpl]; - int bpl24 = ((w*nbits+31)/32)*4; - uchar *b; - int c; - - while ( --h >= 0 ) { - p = (TQRgb *)line[h]; - end = p + w; - if ( d->readBlock( (char *)buf24,bpl24) != bpl24 ) - break; - b = buf24; - while ( p < end ) { - c = *(uchar*)b | (*(uchar*)(b+1)<<8); - if (nbits != 16) - c |= *(uchar*)(b+2)<<16; - *p++ = tqRgb(((c & red_mask) >> red_shift) * red_scale, - ((c & green_mask) >> green_shift) * green_scale, - ((c & blue_mask) >> blue_shift) * blue_scale); - b += nbits/8; - } - } - delete[] buf24; - } - - return TRUE; -} - -bool qt_read_dib( TQDataStream& s, TQImage& image ) -{ - return read_dib(s,-1,-BMP_FILEHDR_SIZE,image); -} - - -static void read_bmp_image( TQImageIO *iio ) -{ - TQIODevice *d = iio->ioDevice(); - TQDataStream s( d ); - BMP_FILEHDR bf; - int startpos = d->at(); - - s.setByteOrder( TQDataStream::LittleEndian );// Intel byte order - s >> bf; // read BMP file header - - if ( tqstrncmp(bf.bfType,"BM",2) != 0 ) // not a BMP image - return; - - TQImage image; - if (read_dib( s, bf.bfOffBits, startpos, image )) { - iio->setImage( image ); - iio->setqStatus( 0 ); // image ok - } -} - -bool qt_write_dib( TQDataStream& s, TQImage image ) -{ - int nbits; - int bpl_bmp; - int bpl = image.bytesPerLine(); - - TQIODevice* d = s.tqdevice(); - - if ( image.depth() == 8 && image.numColors() <= 16 ) { - bpl_bmp = (((bpl+1)/2+3)/4)*4; - nbits = 4; - } else if ( image.depth() == 32 ) { - bpl_bmp = ((image.width()*24+31)/32)*4; - nbits = 24; -#ifdef TQ_WS_TQWS - } else if ( image.depth() == 1 || image.depth() == 8 ) { - // TQt/E doesn't word align. - bpl_bmp = ((image.width()*image.depth()+31)/32)*4; - nbits = image.depth(); -#endif - } else { - bpl_bmp = bpl; - nbits = image.depth(); - } - - BMP_INFOHDR bi; - bi.biSize = BMP_WIN; // build info header - bi.biWidth = image.width(); - bi.biHeight = image.height(); - bi.biPlanes = 1; - bi.biBitCount = nbits; - bi.biCompression = BMP_RGB; - bi.biSizeImage = bpl_bmp*image.height(); - bi.biXPelsPerMeter = image.dotsPerMeterX() ? image.dotsPerMeterX() - : 2834; // 72 dpi default - bi.biYPelsPerMeter = image.dotsPerMeterY() ? image.dotsPerMeterY() : 2834; - bi.biClrUsed = image.numColors(); - bi.biClrImportant = image.numColors(); - s << bi; // write info header - - if ( image.depth() != 32 ) { // write color table - uchar *color_table = new uchar[4*image.numColors()]; - uchar *rgb = color_table; - TQRgb *c = image.colorTable(); - for ( int i=0; iwriteBlock( (char *)color_table, 4*image.numColors() ); - delete [] color_table; - } - - if ( image.depth() == 1 && image.bitOrder() != TQImage::BigEndian ) - image = image.convertBitOrder( TQImage::BigEndian ); - - int y; - - if ( nbits == 1 || nbits == 8 ) { // direct output -#ifdef TQ_WS_TQWS - // TQt/E doesn't word align. - int pad = bpl_bmp - bpl; - char padding[4]; -#endif - for ( y=image.height()-1; y>=0; y-- ) { - d->writeBlock( (char*)image.scanLine(y), bpl ); -#ifdef TQ_WS_TQWS - d->writeBlock( padding, pad ); -#endif - } - return TRUE; - } - - uchar *buf = new uchar[bpl_bmp]; - uchar *b, *end; - register uchar *p; - - memset( buf, 0, bpl_bmp ); - for ( y=image.height()-1; y>=0; y-- ) { // write the image bits - if ( nbits == 4 ) { // convert 8 -> 4 bits - p = image.scanLine(y); - b = buf; - end = b + image.width()/2; - while ( b < end ) { - *b++ = (*p << 4) | (*(p+1) & 0x0f); - p += 2; - } - if ( image.width() & 1 ) - *b = *p << 4; - } else { // 32 bits - TQRgb *p = (TQRgb *)image.scanLine( y ); - TQRgb *end = p + image.width(); - b = buf; - while ( p < end ) { - *b++ = tqBlue(*p); - *b++ = tqGreen(*p); - *b++ = tqRed(*p); - p++; - } - } - if ( bpl_bmp != d->writeBlock( (char*)buf, bpl_bmp ) ) { - delete[] buf; - return FALSE; - } - } - delete[] buf; - return TRUE; -} - - -static void write_bmp_image( TQImageIO *iio ) -{ - TQIODevice *d = iio->ioDevice(); - TQImage image = iio->image(); - TQDataStream s( d ); - BMP_FILEHDR bf; - int bpl_bmp; - int bpl = image.bytesPerLine(); - - // Code partially repeated in qt_write_dib - if ( image.depth() == 8 && image.numColors() <= 16 ) { - bpl_bmp = (((bpl+1)/2+3)/4)*4; - } else if ( image.depth() == 32 ) { - bpl_bmp = ((image.width()*24+31)/32)*4; - } else { - bpl_bmp = bpl; - } - - iio->setqStatus( 0 ); - s.setByteOrder( TQDataStream::LittleEndian );// Intel byte order - strncpy( bf.bfType, "BM", 2 ); // build file header - bf.bfReserved1 = bf.bfReserved2 = 0; // reserved, should be zero - bf.bfOffBits = BMP_FILEHDR_SIZE + BMP_WIN + image.numColors()*4; - bf.bfSize = bf.bfOffBits + bpl_bmp*image.height(); - s << bf; // write file header - - if ( !qt_write_dib( s, image ) ) - iio->setqStatus( 1 ); - -} - -#endif // TQT_NO_IMAGEIO_BMP - -#ifndef TQT_NO_IMAGEIO_PPM - -/***************************************************************************** - PBM/PGM/PPM (ASCII and RAW) image read/write functions - *****************************************************************************/ - -static int read_pbm_int( TQIODevice *d ) -{ - int c; - int val = -1; - bool digit; - const int buflen = 100; - char buf[buflen]; - for ( ;; ) { - if ( (c=d->getch()) == EOF ) // end of file - break; - digit = isdigit( (uchar) c ); - if ( val != -1 ) { - if ( digit ) { - val = 10*val + c - '0'; - continue; - } else { - if ( c == '#' ) // comment - d->readLine( buf, buflen ); - break; - } - } - if ( digit ) // first digit - val = c - '0'; - else if ( isspace((uchar) c) ) - continue; - else if ( c == '#' ) - d->readLine( buf, buflen ); - else - break; - } - return val; -} - -static void read_pbm_image( TQImageIO *iio ) // read PBM image data -{ - const int buflen = 300; - char buf[buflen]; - TQIODevice *d = iio->ioDevice(); - int w, h, nbits, mcc, y; - int pbm_bpl; - char type; - bool raw; - TQImage image; - - if ( d->readBlock( buf, 3 ) != 3 ) // read P[1-6] - return; - if ( !(buf[0] == 'P' && isdigit((uchar) buf[1]) && isspace((uchar) buf[2])) ) - return; - switch ( (type=buf[1]) ) { - case '1': // ascii PBM - case '4': // raw PBM - nbits = 1; - break; - case '2': // ascii PGM - case '5': // raw PGM - nbits = 8; - break; - case '3': // ascii PPM - case '6': // raw PPM - nbits = 32; - break; - default: - return; - } - raw = type >= '4'; - w = read_pbm_int( d ); // get image width - h = read_pbm_int( d ); // get image height - if ( nbits == 1 ) - mcc = 1; // ignore max color component - else - mcc = read_pbm_int( d ); // get max color component - if ( w <= 0 || w > 32767 || h <= 0 || h > 32767 || mcc <= 0 ) - return; // weird P.M image - - int maxc = mcc; - if ( maxc > 255 ) - maxc = 255; - image.create( w, h, nbits, 0, - nbits == 1 ? TQImage::BigEndian : TQImage::IgnoreEndian ); - if ( image.isNull() ) - return; - - pbm_bpl = (nbits*w+7)/8; // bytes per scanline in PBM - - if ( raw ) { // read raw data - if ( nbits == 32 ) { // type 6 - pbm_bpl = 3*w; - uchar *buf24 = new uchar[pbm_bpl], *b; - TQRgb *p; - TQRgb *end; - for ( y=0; yreadBlock( (char *)buf24, pbm_bpl ) != pbm_bpl ) { - delete[] buf24; - return; - } - p = (TQRgb *)image.scanLine( y ); - end = p + w; - b = buf24; - while ( p < end ) { - *p++ = tqRgb(b[0],b[1],b[2]); - b += 3; - } - } - delete[] buf24; - } else { // type 4,5 - for ( y=0; yreadBlock( (char *)image.scanLine(y), pbm_bpl ) - != pbm_bpl ) - return; - } - } - } else { // read ascii data - register uchar *p; - int n; - for ( y=0; ysetImage( image ); - iio->setqStatus( 0 ); // image ok -} - - -static void write_pbm_image( TQImageIO *iio ) -{ - TQIODevice* out = iio->ioDevice(); - TQCString str; - - TQImage image = iio->image(); - TQCString format = iio->format(); - format = format.left(3); // ignore RAW part - bool gray = format == "PGM"; - - if ( format == "PBM" ) { - image = image.convertDepth(1); - } else if ( image.depth() == 1 ) { - image = image.convertDepth(8); - } - - if ( image.depth() == 1 && image.numColors() == 2 ) { - if ( tqGray(image.color(0)) < tqGray(image.color(1)) ) { - // 0=dark/black, 1=light/white - invert - image.detach(); - for ( int y=0; ywriteBlock(str, str.length()) != str.length()) { - iio->setqStatus(1); - return; - } - w = (w+7)/8; - for (uint y=0; ywriteBlock((char*)line, w) ) { - iio->setqStatus(1); - return; - } - } - } - break; - - case 8: { - str.insert(1, gray ? '5' : '6'); - str.append("255\n"); - if ((uint)out->writeBlock(str, str.length()) != str.length()) { - iio->setqStatus(1); - return; - } - TQRgb *color = image.colorTable(); - uint bpl = w*(gray ? 1 : 3); - uchar *buf = new uchar[bpl]; - for (uint y=0; ywriteBlock((char*)buf, bpl) ) { - iio->setqStatus(1); - return; - } - } - delete [] buf; - } - break; - - case 32: { - str.insert(1, gray ? '5' : '6'); - str.append("255\n"); - if ((uint)out->writeBlock(str, str.length()) != str.length()) { - iio->setqStatus(1); - return; - } - uint bpl = w*(gray ? 1 : 3); - uchar *buf = new uchar[bpl]; - for (uint y=0; ywriteBlock((char*)buf, bpl) ) { - iio->setqStatus(1); - return; - } - } - delete [] buf; - } - } - - iio->setqStatus(0); -} - -#endif // TQT_NO_IMAGEIO_PPM - -#ifndef TQT_NO_ASYNC_IMAGE_IO - -class TQImageIOFrameGrabber : public TQImageConsumer { -public: - TQImageIOFrameGrabber() : framecount(0) { } - - TQImageDecoder *decoder; - int framecount; - - void changed(const TQRect&) { } - void end() { } - void frameDone(const TQPoint&, const TQRect&) { framecount++; } - void frameDone() { framecount++; } - void setLooping(int) { } - void setFramePeriod(int) { } - void setSize(int, int) { } -}; - -static void read_async_image( TQImageIO *iio ) -{ - const int buf_len = 2048; - uchar buffer[buf_len]; - TQIODevice *d = iio->ioDevice(); - TQImageIOFrameGrabber* consumer = new TQImageIOFrameGrabber(); - TQImageDecoder *decoder = new TQImageDecoder(consumer); - consumer->decoder = decoder; - int startAt = d->at(); - int totLen = 0; - - for (;;) { - int length = d->readBlock((char*)buffer, buf_len); - if ( length <= 0 ) { - iio->setqStatus(length); - break; - } - uchar* b = buffer; - int r = -1; - while (length > 0 && consumer->framecount==0) { - r = decoder->decode(b, length); - if ( r <= 0 ) break; - b += r; - totLen += r; - length -= r; - } - if ( consumer->framecount ) { - // Stopped after first frame - if ( d->isDirectAccess() ) - d->at( startAt + totLen ); - else { - // ### We have (probably) read too much from the stream into - // the buffer, and there is no way to put it back! - } - iio->setImage(decoder->image()); - iio->setqStatus(0); - break; - } - if ( r <= 0 ) { - iio->setqStatus(r); - break; - } - } - - consumer->decoder = 0; - delete decoder; - delete consumer; -} - -#endif // TQT_NO_ASYNC_IMAGE_IO - -#ifndef TQT_NO_IMAGEIO_XBM - -/***************************************************************************** - X bitmap image read/write functions - *****************************************************************************/ - -static inline int hex2byte( register char *p ) -{ - return ( (isdigit((uchar) *p) ? *p - '0' : toupper((uchar) *p) - 'A' + 10) << 4 ) | - ( isdigit((uchar) *(p+1)) ? *(p+1) - '0' : toupper((uchar) *(p+1)) - 'A' + 10 ); -} - -static void read_xbm_image( TQImageIO *iio ) -{ - const int buflen = 300; - char buf[buflen]; - TQRegExp r1, r2; - TQIODevice *d = iio->ioDevice(); - int w=-1, h=-1; - TQImage image; - - r1 = TQString::tqfromLatin1("^#define[ \t]+[a-zA-Z0-9._]+[ \t]+"); - r2 = TQString::tqfromLatin1("[0-9]+"); - d->readLine( buf, buflen ); // "#define .._width " - - while (!d->atEnd() && buf[0] != '#') //skip leading comment, if any - d->readLine( buf, buflen ); - - TQString sbuf; - sbuf = TQString::tqfromLatin1(buf); - - if ( r1.search(sbuf) == 0 && - r2.search(sbuf, r1.matchedLength()) == r1.matchedLength() ) - w = atoi( &buf[r1.matchedLength()] ); - - d->readLine( buf, buflen ); // "#define .._height " - sbuf = TQString::tqfromLatin1(buf); - - if ( r1.search(sbuf) == 0 && - r2.search(sbuf, r1.matchedLength()) == r1.matchedLength() ) - h = atoi( &buf[r1.matchedLength()] ); - - if ( w <= 0 || w > 32767 || h <= 0 || h > 32767 ) - return; // format error - - for ( ;; ) { // scan for data - if ( d->readLine(buf, buflen) <= 0 ) // end of file - return; - if ( strstr(buf,"0x") != 0 ) // does line contain data? - break; - } - - image.create( w, h, 1, 2, TQImage::LittleEndian ); - if ( image.isNull() ) - return; - - image.setColor( 0, tqRgb(255,255,255) ); // white - image.setColor( 1, tqRgb(0,0,0) ); // black - - int x = 0, y = 0; - uchar *b = image.scanLine(0); - char *p = strstr( buf, "0x" ); - w = (w+7)/8; // byte width - - while ( y < h ) { // for all encoded bytes... - if ( p ) { // p = "0x.." - *b++ = hex2byte(p+2); - p += 2; - if ( ++x == w && ++y < h ) { - b = image.scanLine(y); - x = 0; - } - p = strstr( p, "0x" ); - } else { // read another line - if ( d->readLine(buf,buflen) <= 0 ) // EOF ==> truncated image - break; - p = strstr( buf, "0x" ); - } - } - - iio->setImage( image ); - iio->setqStatus( 0 ); // image ok -} - - -static void write_xbm_image( TQImageIO *iio ) -{ - TQIODevice *d = iio->ioDevice(); - TQImage image = iio->image(); - int w = image.width(); - int h = image.height(); - int i; - TQString s = fbname(iio->fileName()); // get file base name - char *buf = new char[s.length() + 100]; - - sprintf( buf, "#define %s_width %d\n", s.ascii(), w ); - d->writeBlock( buf, tqstrlen(buf) ); - sprintf( buf, "#define %s_height %d\n", s.ascii(), h ); - d->writeBlock( buf, tqstrlen(buf) ); - sprintf( buf, "static char %s_bits[] = {\n ", s.ascii() ); - d->writeBlock( buf, tqstrlen(buf) ); - - iio->setqStatus( 0 ); - - if ( image.depth() != 1 ) - image = image.convertDepth( 1 ); // dither - if ( image.bitOrder() != TQImage::LittleEndian ) - image = image.convertBitOrder( TQImage::LittleEndian ); - - bool invert = tqGray(image.color(0)) < tqGray(image.color(1)); - char hexrep[16]; - for ( i=0; i<10; i++ ) - hexrep[i] = '0' + i; - for ( i=10; i<16; i++ ) - hexrep[i] = 'a' -10 + i; - if ( invert ) { - char t; - for ( i=0; i<8; i++ ) { - t = hexrep[15-i]; - hexrep[15-i] = hexrep[i]; - hexrep[i] = t; - } - } - int bcnt = 0; - register char *p = buf; - int bpl = (w+7)/8; - for (int y = 0; y < h; ++y) { - uchar *b = image.scanLine(y); - for (i = 0; i < bpl; ++i) { - *p++ = '0'; *p++ = 'x'; - *p++ = hexrep[*b >> 4]; - *p++ = hexrep[*b++ & 0xf]; - - if ( i < bpl - 1 || y < h - 1 ) { - *p++ = ','; - if ( ++bcnt > 14 ) { - *p++ = '\n'; - *p++ = ' '; - *p = '\0'; - if ( (int)tqstrlen(buf) != d->writeBlock( buf, tqstrlen(buf) ) ) { - iio->setqStatus( 1 ); - delete [] buf; - return; - } - p = buf; - bcnt = 0; - } - } - } - } - strcpy( p, " };\n" ); - if ( (int)tqstrlen(buf) != d->writeBlock( buf, tqstrlen(buf) ) ) - iio->setqStatus( 1 ); - delete [] buf; -} - -#endif // TQT_NO_IMAGEIO_XBM - - -#ifndef TQT_NO_IMAGEIO_XPM - -/***************************************************************************** - XPM image read/write functions - *****************************************************************************/ - - -// Skip until ", read until the next ", return the rest in *buf -// Returns FALSE on error, TRUE on success - -static bool read_xpm_string( TQCString &buf, TQIODevice *d, - const char * const *source, int &index ) -{ - if ( source ) { - buf = source[index++]; - return TRUE; - } - - if ( buf.size() < 69 ) //# just an approximation - buf.resize( 123 ); - - buf[0] = '\0'; - int c; - int i; - while ( (c=d->getch()) != EOF && c != '"' ) { } - if ( c == EOF ) { - return FALSE; - } - i = 0; - while ( (c=d->getch()) != EOF && c != '"' ) { - if ( i == (int)buf.size() ) - buf.resize( i*2+42 ); - buf[i++] = c; - } - if ( c == EOF ) { - return FALSE; - } - - if ( i == (int)buf.size() ) // always use a 0 terminator - buf.resize( i+1 ); - buf[i] = '\0'; - return TRUE; -} - - - -static int nextColorSpec(const TQCString & buf) -{ - int i = buf.find(" c "); - if (i < 0) - i = buf.find(" g "); - if (i < 0) - i = buf.find(" g4 "); - if (i < 0) - i = buf.find(" m "); - if (i < 0) - i = buf.find(" s "); - return i; -} - -// -// INTERNAL -// -// Reads an .xpm from either the TQImageIO or from the TQString *. -// One of the two HAS to be 0, the other one is used. -// - -static void read_xpm_image_or_array( TQImageIO * iio, const char * const * source, - TQImage & image) -{ - TQCString buf; - TQIODevice *d = 0; - buf.resize( 200 ); - - int i, cpp, ncols, w, h, index = 0; - - if ( iio ) { - iio->setqStatus( 1 ); - d = iio ? iio->ioDevice() : 0; - d->readLine( buf.data(), buf.size() ); // "/* XPM */" - TQRegExp r( TQString::tqfromLatin1("/\\*.XPM.\\*/") ); - if ( buf.find(r) == -1 ) - return; // bad magic - } else if ( !source ) { - return; - } - - if ( !read_xpm_string( buf, d, source, index ) ) - return; - - if ( sscanf( buf, "%d %d %d %d", &w, &h, &ncols, &cpp ) < 4 ) - return; // < 4 numbers parsed - - if ( cpp > 15 ) - return; - - if ( ncols > 256 ) { - image.create( w, h, 32 ); - } else { - image.create( w, h, 8, ncols ); - } - - if (image.isNull()) - return; - - TQMap colorMap; - int currentColor; - - for( currentColor=0; currentColor < ncols; ++currentColor ) { - if ( !read_xpm_string( buf, d, source, index ) ) { -#if defined(TQT_CHECK_RANGE) - qWarning( "TQImage: XPM color specification missing"); -#endif - return; - } - TQString index; - index = buf.left( cpp ); - buf = buf.mid( cpp ).simplifyWhiteSpace().lower(); - buf.prepend( " " ); - i = nextColorSpec(buf); - if ( i < 0 ) { -#if defined(TQT_CHECK_RANGE) - qWarning( "TQImage: XPM color specification is missing: %s", buf.data()); -#endif - return; // no c/g/g4/m/s specification at all - } - buf = buf.mid( i+3 ); - // Strip any other colorspec - int end = nextColorSpec(buf); - if (end != -1) - buf.truncate(end); - buf = buf.stripWhiteSpace(); - if ( buf == "none" ) { - image.setAlphaBuffer( TRUE ); - int transparentColor = currentColor; - if ( image.depth() == 8 ) { - image.setColor( transparentColor, - TQRGB_MASK & tqRgb(198,198,198) ); - colorMap.insert( index, transparentColor ); - } else { - TQRgb rgb = TQRGB_MASK & tqRgb(198,198,198); - colorMap.insert( index, rgb ); - } - } else { - if ( ((buf.length()-1) % 3) && (buf[0] == '#') ) { - buf.truncate (((buf.length()-1) / 4 * 3) + 1); // remove alpha channel left by imagemagick - } - TQColor c( buf.data() ); - if ( image.depth() == 8 ) { - image.setColor( currentColor, 0xff000000 | c.rgb() ); - colorMap.insert( index, currentColor ); - } else { - TQRgb rgb = 0xff000000 | c.rgb(); - colorMap.insert( index, rgb ); - } - } - } - - // Read pixels - for( int y=0; ysetImage( image ); - iio->setqStatus( 0 ); // image ok - } -} - - -static void read_xpm_image( TQImageIO * iio ) -{ - TQImage i; - (void)read_xpm_image_or_array( iio, 0, i ); - return; -} - - -static const char* xpm_color_name( int cpp, int index ) -{ - static char returnable[5]; - static const char code[] = ".#abcdefghijklmnopqrstuvwxyzABCD" - "EFGHIJKLMNOPQRSTUVWXYZ0123456789"; - // cpp is limited to 4 and index is limited to 64^cpp - if ( cpp > 1 ) { - if ( cpp > 2 ) { - if ( cpp > 3 ) { - returnable[3] = code[index % 64]; - index /= 64; - } else - returnable[3] = '\0'; - returnable[2] = code[index % 64]; - index /= 64; - } else - returnable[2] = '\0'; - // the following 4 lines are a joke! - if ( index == 0 ) - index = 64*44+21; - else if ( index == 64*44+21 ) - index = 0; - returnable[1] = code[index % 64]; - index /= 64; - } else - returnable[1] = '\0'; - returnable[0] = code[index]; - - return returnable; -} - - -// write XPM image data -static void write_xpm_image( TQImageIO * iio ) -{ - if ( iio ) - iio->setqStatus( 1 ); - else - return; - - // ### 8-bit case could be made faster - TQImage image; - if ( iio->image().depth() != 32 ) - image = iio->image().convertDepth( 32 ); - else - image = iio->image(); - - TQMap colorMap; - - int w = image.width(), h = image.height(), ncolors = 0; - int x, y; - - // build color table - for( y=0; y k; k *= 64 ) { - ++cpp; - // limit to 4 characters per pixel - // 64^4 colors is enough for a 4096x4096 image - if ( cpp > 4) - break; - } - - TQString line; - - // write header - TQTextStream s( iio->ioDevice() ); - s << "/* XPM */" << endl - << "static char *" << fbname(iio->fileName()) << "[]={" << endl - << "\"" << w << " " << h << " " << ncolors << " " << cpp << "\""; - - // write palette - TQMap::Iterator c = colorMap.begin(); - while ( c != colorMap.end() ) { - TQRgb color = c.key(); - if ( image.hasAlphaBuffer() && color == (color & TQRGB_MASK) ) - line.sprintf( "\"%s c None\"", - xpm_color_name(cpp, *c) ); - else - line.sprintf( "\"%s c #%02x%02x%02x\"", - xpm_color_name(cpp, *c), - tqRed(color), - tqGreen(color), - tqBlue(color) ); - ++c; - s << "," << endl << line; - } - - // write pixels, limit to 4 characters per pixel - line.truncate( cpp*w ); - for( y=0; y 1 ) { - line[cc++] = chars[1]; - if ( cpp > 2 ) { - line[cc++] = chars[2]; - if ( cpp > 3 ) { - line[cc++] = chars[3]; - } - } - } - } - s << "," << endl << "\"" << line << "\""; - } - s << "};" << endl; - - iio->setqStatus( 0 ); -} - -#endif // TQT_NO_IMAGEIO_XPM - -/*! - Returns an image with depth \a d, using the \a palette_count - colors pointed to by \a palette. If \a d is 1 or 8, the returned - image will have its color table ordered the same as \a palette. - - If the image needs to be modified to fit in a lower-resolution - result (e.g. converting from 32-bit to 8-bit), use the \a - conversion_flags to specify how you'd prefer this to happen. - - Note: currently no closest-color search is made. If colors are - found that are not in the palette, the palette may not be used at - all. This result should not be considered valid because it may - change in future implementations. - - Currently inefficient for non-32-bit images. - - \sa TQt::ImageConversionFlags -*/ -#ifndef TQT_NO_IMAGE_TRUECOLOR -TQImage TQImage::convertDepthWithPalette( int d, TQRgb* palette, int palette_count, int conversion_flags ) const -{ - if ( depth() == 1 ) { - return convertDepth( 8, conversion_flags ) - .convertDepthWithPalette( d, palette, palette_count, conversion_flags ); - } else if ( depth() == 8 ) { - // ### this could be easily made more efficient - return convertDepth( 32, conversion_flags ) - .convertDepthWithPalette( d, palette, palette_count, conversion_flags ); - } else { - TQImage result; - convert_32_to_8( this, &result, - (conversion_flags&~TQt::DitherMode_Mask) | TQt::AvoidDither, - palette, palette_count ); - return result.convertDepth( d ); - } -} -#endif -static -bool -haveSamePalette(const TQImage& a, const TQImage& b) -{ - if (a.depth() != b.depth()) return FALSE; - if (a.numColors() != b.numColors()) return FALSE; - TQRgb* ca = a.colorTable(); - TQRgb* cb = b.colorTable(); - for (int i=a.numColors(); i--; ) { - if (*ca++ != *cb++) return FALSE; - } - return TRUE; -} - -/*! - \relates TQImage - - Copies a block of pixels from \a src to \a dst. The pixels - copied from source (src) are converted according to - \a conversion_flags if it is incompatible with the destination - (\a dst). - - \a sx, \a sy is the top-left pixel in \a src, \a dx, \a dy - is the top-left position in \a dst and \a sw, \a sh is the - size of the copied block. - - The copying is clipped if areas outside \a src or \a dst are - specified. - - If \a sw is -1, it is adjusted to src->width(). Similarly, if \a - sh is -1, it is adjusted to src->height(). - - Currently inefficient for non 32-bit images. -*/ -void bitBlt( TQImage* dst, int dx, int dy, const TQImage* src, - int sx, int sy, int sw, int sh, int conversion_flags ) -{ - // Parameter correction - if ( sw < 0 ) sw = src->width(); - if ( sh < 0 ) sh = src->height(); - if ( sx < 0 ) { dx -= sx; sw += sx; sx = 0; } - if ( sy < 0 ) { dy -= sy; sh += sy; sy = 0; } - if ( dx < 0 ) { sx -= dx; sw += dx; dx = 0; } - if ( dy < 0 ) { sy -= dy; sh += dy; dy = 0; } - if ( sx + sw > src->width() ) sw = src->width() - sx; - if ( sy + sh > src->height() ) sh = src->height() - sy; - if ( dx + sw > dst->width() ) sw = dst->width() - dx; - if ( dy + sh > dst->height() ) sh = dst->height() - dy; - if ( sw <= 0 || sh <= 0 ) return; // Nothing left to copy - if ( (dst->data == src->data) && dx==sx && dy==sy ) return; // Same pixels - - // "Easy" to copy if both same depth and one of: - // - 32 bit - // - 8 bit, identical palette - // - 1 bit, identical palette and byte-aligned area - // - if ( haveSamePalette(*dst,*src) - && ( dst->depth() != 1 || - !( (dx&7) || (sx&7) || - ((sw&7) && (sx+sw < src->width()) || - (dx+sw < dst->width()) ) ) ) ) - { - // easy to copy - } else if ( dst->depth() != 32 ) { -#ifndef TQT_NO_IMAGE_TRUECOLOR - - TQImage dstconv = dst->convertDepth( 32 ); - bitBlt( &dstconv, dx, dy, src, sx, sy, sw, sh, - (conversion_flags&~TQt::DitherMode_Mask) | TQt::AvoidDither ); - *dst = dstconv.convertDepthWithPalette( dst->depth(), - dst->colorTable(), dst->numColors() ); -#endif - return; - } - - // Now assume palette can be ignored - - if ( dst->depth() != src->depth() ) { - if ( sw == src->width() && sh == src->height() || dst->depth()==32 ) { - TQImage srcconv = src->convertDepth( dst->depth(), conversion_flags ); - bitBlt( dst, dx, dy, &srcconv, sx, sy, sw, sh, conversion_flags ); - } else { - TQImage srcconv = src->copy( sx, sy, sw, sh ); // ie. bitBlt - bitBlt( dst, dx, dy, &srcconv, 0, 0, sw, sh, conversion_flags ); - } - return; - } - - // Now assume both are the same depth. - - // Now assume both are 32-bit or 8-bit with compatible palettes. - - // "Easy" - - switch ( dst->depth() ) { - case 1: - { - uchar* d = dst->scanLine(dy) + dx/8; - uchar* s = src->scanLine(sy) + sx/8; - const int bw = (sw+7)/8; - if ( bw < 64 ) { - // Trust ourselves - const int dd = dst->bytesPerLine() - bw; - const int ds = src->bytesPerLine() - bw; - while ( sh-- ) { - for ( int t=bw; t--; ) - *d++ = *s++; - d += dd; - s += ds; - } - } else { - // Trust libc - const int dd = dst->bytesPerLine(); - const int ds = src->bytesPerLine(); - while ( sh-- ) { - memcpy( d, s, bw ); - d += dd; - s += ds; - } - } - } - break; - case 8: - { - uchar* d = dst->scanLine(dy) + dx; - uchar* s = src->scanLine(sy) + sx; - if ( sw < 64 ) { - // Trust ourselves - const int dd = dst->bytesPerLine() - sw; - const int ds = src->bytesPerLine() - sw; - while ( sh-- ) { - for ( int t=sw; t--; ) - *d++ = *s++; - d += dd; - s += ds; - } - } else { - // Trust libc - const int dd = dst->bytesPerLine(); - const int ds = src->bytesPerLine(); - while ( sh-- ) { - memcpy( d, s, sw ); - d += dd; - s += ds; - } - } - } - break; -#ifndef TQT_NO_IMAGE_TRUECOLOR - case 32: - if ( src->hasAlphaBuffer() ) { - TQRgb* d = (TQRgb*)dst->scanLine(dy) + dx; - TQRgb* s = (TQRgb*)src->scanLine(sy) + sx; - const int dd = dst->width() - sw; - const int ds = src->width() - sw; - while ( sh-- ) { - for ( int t=sw; t--; ) { - unsigned char a = tqAlpha(*s); - if ( a == 255 ) - *d++ = *s++; - else if ( a == 0 ) - ++d,++s; // nothing - else { - unsigned char r = ((tqRed(*s)-tqRed(*d)) * a) / 256 + tqRed(*d); - unsigned char g = ((tqGreen(*s)-tqGreen(*d)) * a) / 256 + tqGreen(*d); - unsigned char b = ((tqBlue(*s)-tqBlue(*d)) * a) / 256 + tqBlue(*d); - a = TQMAX(tqAlpha(*d),a); // alternatives... - *d++ = tqRgba(r,g,b,a); - ++s; - } - } - d += dd; - s += ds; - } - } else { - TQRgb* d = (TQRgb*)dst->scanLine(dy) + dx; - TQRgb* s = (TQRgb*)src->scanLine(sy) + sx; - if ( sw < 64 ) { - // Trust ourselves - const int dd = dst->width() - sw; - const int ds = src->width() - sw; - while ( sh-- ) { - for ( int t=sw; t--; ) - *d++ = *s++; - d += dd; - s += ds; - } - } else { - // Trust libc - const int dd = dst->width(); - const int ds = src->width(); - const int b = sw*sizeof(TQRgb); - while ( sh-- ) { - memcpy( d, s, b ); - d += dd; - s += ds; - } - } - } - break; -#endif // TQT_NO_IMAGE_TRUECOLOR - } -} - - -/*! - Returns TRUE if this image and image \a i have the same contents; - otherwise returns FALSE. The comparison can be slow, unless there - is some obvious difference, such as different widths, in which - case the function will return quickly. - - \sa operator=() -*/ - -bool TQImage::operator==( const TQImage & i ) const -{ - // same object, or shared? - if ( i.data == data ) - return TRUE; - // obviously different stuff? - if ( i.data->h != data->h || - i.data->w != data->w ) - return FALSE; - // not equal if one has alphabuffer and the other does not - if ( i.hasAlphaBuffer() != hasAlphaBuffer() ) - return FALSE; - // that was the fast bit... - TQImage i1 = convertDepth( 32 ); - TQImage i2 = i.convertDepth( 32 ); - int l; - // if no alpha buffer used, there might still be junk in the - // alpha bits; thus, we can't do memcmp-style comparison of scanlines - if ( !hasAlphaBuffer() ) { - int m; - TQRgb *i1line; - TQRgb *i2line; - for( l=0; l < data->h; l++ ) { - i1line = (uint *)i1.scanLine( l ); - i2line = (uint *)i2.scanLine( l ); - // compare pixels of scanline individually - for ( m=0; m < data->w; m++ ) - if ( (i1line[m] ^ i2line[m]) & 0x00FFFFFF ) - return FALSE; - } - } else { - // yay, we can do fast binary comparison on entire scanlines - for( l=0; l < data->h; l++ ) - if ( memcmp( i1.scanLine( l ), i2.scanLine( l ), 4*data->w ) ) - return FALSE; - } - return TRUE; -} - - -/*! - Returns TRUE if this image and image \a i have different contents; - otherwise returns FALSE. The comparison can be slow, unless there - is some obvious difference, such as different widths, in which - case the function will return quickly. - - \sa operator=() -*/ - -bool TQImage::operator!=( const TQImage & i ) const -{ - return !(*this == i); -} - - - - -/*! - \fn int TQImage::dotsPerMeterX() const - - Returns the number of pixels that fit horizontally in a physical - meter. This and dotsPerMeterY() define the intended scale and - aspect ratio of the image. - - \sa setDotsPerMeterX() -*/ - -/*! - \fn int TQImage::dotsPerMeterY() const - - Returns the number of pixels that fit vertically in a physical - meter. This and dotsPerMeterX() define the intended scale and - aspect ratio of the image. - - \sa setDotsPerMeterY() -*/ - -/*! - Sets the value returned by dotsPerMeterX() to \a x. -*/ -void TQImage::setDotsPerMeterX(int x) -{ - data->dpmx = x; -} - -/*! - Sets the value returned by dotsPerMeterY() to \a y. -*/ -void TQImage::setDotsPerMeterY(int y) -{ - data->dpmy = y; -} - -/*! - \fn TQPoint TQImage::offset() const - - Returns the number of pixels by which the image is intended to be - offset by when positioning relative to other images. -*/ - -/*! - Sets the value returned by offset() to \a p. -*/ -void TQImage::setOffset(const TQPoint& p) -{ - data->offset = p; -} -#ifndef TQT_NO_IMAGE_TEXT -/*! - \internal - - Returns the internal TQImageDataMisc object. This object will be - created if it doesn't already exist. -*/ -TQImageDataMisc& TQImage::misc() const -{ - if ( !data->misc ) - data->misc = new TQImageDataMisc; - return *data->misc; -} - -/*! - Returns the string recorded for the keyword \a key in language \a - lang, or in a default language if \a lang is 0. -*/ -TQString TQImage::text(const char* key, const char* lang) const -{ - TQImageTextKeyLang x(key,lang); - return misc().text_lang[x]; -} - -/*! - \overload - - Returns the string recorded for the keyword and language \a kl. -*/ -TQString TQImage::text(const TQImageTextKeyLang& kl) const -{ - return misc().text_lang[kl]; -} - -/*! - Returns the language identifiers for which some texts are - recorded. - - Note that if you want to iterate over the list, you should iterate - over a copy, e.g. - \code - TQStringList list = myImage.textLanguages(); - TQStringList::Iterator it = list.begin(); - while( it != list.end() ) { - myProcessing( *it ); - ++it; - } - \endcode - - \sa textList() text() setText() textKeys() -*/ -TQStringList TQImage::textLanguages() const -{ - if ( !data->misc ) - return TQStringList(); - return misc().languages(); -} - -/*! - Returns the keywords for which some texts are recorded. - - Note that if you want to iterate over the list, you should iterate - over a copy, e.g. - \code - TQStringList list = myImage.textKeys(); - TQStringList::Iterator it = list.begin(); - while( it != list.end() ) { - myProcessing( *it ); - ++it; - } - \endcode - - \sa textList() text() setText() textLanguages() -*/ -TQStringList TQImage::textKeys() const -{ - if ( !data->misc ) - return TQStringList(); - return misc().keys(); -} - -/*! - Returns a list of TQImageTextKeyLang objects that enumerate all the - texts key/language pairs set by setText() for this image. - - Note that if you want to iterate over the list, you should iterate - over a copy, e.g. - \code - TQValueList list = myImage.textList(); - TQValueList::Iterator it = list.begin(); - while( it != list.end() ) { - myProcessing( *it ); - ++it; - } - \endcode -*/ -TQValueList TQImage::textList() const -{ - if ( !data->misc ) - return TQValueList(); - return misc().list(); -} - -/*! - Records string \a s for the keyword \a key. The \a key should be a - portable keyword recognizable by other software - some suggested - values can be found in \link - http://www.libpng.org/pub/png/spec/1.2/png-1.2-pdg.html#C.Anc-text - the PNG specification \endlink. \a s can be any text. \a lang - should specify the language code (see - \link http://www.rfc-editor.org/rfc/rfc1766.txt RFC 1766 \endlink) or 0. -*/ -void TQImage::setText(const char* key, const char* lang, const TQString& s) -{ - TQImageTextKeyLang x(key,lang); - misc().text_lang.replace(x,s); -} - -#endif // TQT_NO_IMAGE_TEXT - -#ifdef TQ_WS_TQWS -/*! - \internal -*/ -TQGfx * TQImage::graphicsContext() -{ - TQGfx * ret=0; - if(depth()) { - int w = qt_screen->mapToDevice( TQSize(width(),height()) ).width(); - int h = qt_screen->mapToDevice( TQSize(width(),height()) ).height(); - ret=TQGfx::createGfx(depth(),bits(),w,h,bytesPerLine()); - } else { - qDebug("Trying to create image for null depth"); - return 0; - } - if(depth()<=8) { - TQRgb * tmp=colorTable(); - int nc=numColors(); - if(tmp==0) { - static TQRgb table[2] = { tqRgb(255,255,255), tqRgb(0,0,0) }; - tmp=table; - nc=2; - } - ret->setClut(tmp,nc); - } - return ret; -} - -#endif - -#endif // USE_QT4 -- cgit v1.2.1