diff options
Diffstat (limited to 'experimental/tqtinterface/qt4/src/kernel/tqjpegio.cpp')
-rw-r--r-- | experimental/tqtinterface/qt4/src/kernel/tqjpegio.cpp | 599 |
1 files changed, 0 insertions, 599 deletions
diff --git a/experimental/tqtinterface/qt4/src/kernel/tqjpegio.cpp b/experimental/tqtinterface/qt4/src/kernel/tqjpegio.cpp deleted file mode 100644 index 1f3ffd88b..000000000 --- a/experimental/tqtinterface/qt4/src/kernel/tqjpegio.cpp +++ /dev/null @@ -1,599 +0,0 @@ -/**************************************************************************** -** -** Implementation of JPEG TQImage IOHandler -** -** Created : 990521 -** -** 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. -** -**********************************************************************/ - -#ifndef TQT_CLEAN_NAMESPACE -#define TQT_CLEAN_NAMESPACE -#endif - -#include "tqimage.h" - -#ifndef TQT_NO_IMAGEIO_JPEG - -#include "tqiodevice.h" -#include "tqjpegio.h" - -#include <stdio.h> // jpeglib needs this to be pre-included -#include <setjmp.h> - - -// including jpeglib.h seems to be a little messy -extern "C" { -#define XMD_H // shut JPEGlib up -#if defined(TQ_OS_UNIXWARE) -# define HAVE_BOOLEAN // libjpeg under Unixware seems to need this -#endif -#include <jpeglib.h> -#ifdef const -# undef const // remove crazy C hackery in jconfig.h -#endif -} - - -struct my_error_mgr : public jpeg_error_mgr { - jmp_buf setjmp_buffer; -}; - -#if defined(TQ_C_CALLBACKS) -extern "C" { -#endif - -static -void my_error_exit (j_common_ptr cinfo) -{ - my_error_mgr* myerr = (my_error_mgr*) cinfo->err; - char buffer[JMSG_LENGTH_MAX]; - (*cinfo->err->format_message)(cinfo, buffer); - qWarning(buffer); - longjmp(myerr->setjmp_buffer, 1); -} - -#if defined(TQ_C_CALLBACKS) -} -#endif - - -static const int max_buf = 4096; - -struct my_jpeg_source_mgr : public jpeg_source_mgr { - // Nothing dynamic - cannot rely on destruction over longjump - TQImageIO* iio; - JOCTET buffer[max_buf]; - -public: - my_jpeg_source_mgr(TQImageIO* iio); -}; - -#if defined(TQ_C_CALLBACKS) -extern "C" { -#endif - -static -void qt_init_source(j_decompress_ptr) -{ -} - -static -boolean qt_fill_input_buffer(j_decompress_ptr cinfo) -{ - int num_read; - my_jpeg_source_mgr* src = (my_jpeg_source_mgr*)cinfo->src; - TQIODevice* dev = src->iio->ioDevice(); - src->next_input_byte = src->buffer; - num_read = dev->readBlock((char*)src->buffer, max_buf); - if ( num_read <= 0 ) { - // Insert a fake EOI marker - as per jpeglib recommendation - src->buffer[0] = (JOCTET) 0xFF; - src->buffer[1] = (JOCTET) JPEG_EOI; - src->bytes_in_buffer = 2; - } else { - src->bytes_in_buffer = num_read; - } -#if defined(TQ_OS_UNIXWARE) - return B_TRUE; -#else - return TRUE; -#endif -} - -static -void qt_skip_input_data(j_decompress_ptr cinfo, long num_bytes) -{ - my_jpeg_source_mgr* src = (my_jpeg_source_mgr*)cinfo->src; - - // `dumb' implementation from jpeglib - - /* Just a dumb implementation for now. Could use fseek() except - * it doesn't work on pipes. Not clear that being smart is worth - * any trouble anyway --- large skips are infrequent. - */ - if (num_bytes > 0) { - while (num_bytes > (long) src->bytes_in_buffer) { - num_bytes -= (long) src->bytes_in_buffer; - (void) qt_fill_input_buffer(cinfo); - /* note we assume that qt_fill_input_buffer will never return FALSE, - * so suspension need not be handled. - */ - } - src->next_input_byte += (size_t) num_bytes; - src->bytes_in_buffer -= (size_t) num_bytes; - } -} - -static -void qt_term_source(j_decompress_ptr) -{ -} - -#if defined(TQ_C_CALLBACKS) -} -#endif - - -inline my_jpeg_source_mgr::my_jpeg_source_mgr(TQImageIO* iioptr) -{ - jpeg_source_mgr::init_source = qt_init_source; - jpeg_source_mgr::fill_input_buffer = qt_fill_input_buffer; - jpeg_source_mgr::skip_input_data = qt_skip_input_data; - jpeg_source_mgr::resync_to_restart = jpeg_resync_to_restart; - jpeg_source_mgr::term_source = qt_term_source; - iio = iioptr; - bytes_in_buffer = 0; - next_input_byte = buffer; -} - - -static -void scaleSize( int &reqW, int &reqH, int imgW, int imgH, TQ_ScaleMode mode ) -{ - if ( mode == TQ_ScaleFree ) - return; - int t1 = imgW * reqH; - int t2 = reqW * imgH; - if (( mode == TQ_ScaleMin && (t1 > t2) ) || ( mode == TQ_ScaleMax && (t1 < t2) )) - reqH = t2 / imgW; - else - reqW = t1 / imgH; -} - - -static -void read_jpeg_image(TQImageIO* iio) -{ - TQImage image; - - struct jpeg_decompress_struct cinfo; - - struct my_jpeg_source_mgr *iod_src = new my_jpeg_source_mgr(iio); - struct my_error_mgr jerr; - - cinfo.err = jpeg_std_error(&jerr); - jerr.error_exit = my_error_exit; - - jpeg_create_decompress(&cinfo); - - cinfo.src = iod_src; - - if (!setjmp(jerr.setjmp_buffer)) { -#if defined(TQ_OS_UNIXWARE) - (void) jpeg_read_header(&cinfo, B_TRUE); -#else - (void) jpeg_read_header(&cinfo, TRUE); -#endif - - (void) jpeg_start_decompress(&cinfo); - - TQString params = iio->parameters(); - params.simplifyWhiteSpace(); - int sWidth = 0, sHeight = 0; - char sModeStr[1024] = ""; - TQ_ScaleMode sMode; - - if ( params.contains( "GetHeaderInformation" ) ) { - - // Create TQImage's without allocating the data - if ( cinfo.output_components == 3 || cinfo.output_components == 4) { - image = TQImage( NULL, cinfo.output_width, cinfo.output_height, 32, NULL, 0, TQImage::IgnoreEndian ); - } else if ( cinfo.output_components == 1 ) { - image = TQImage( NULL, cinfo.output_width, cinfo.output_height, 8, NULL, 0, TQImage::IgnoreEndian ); - } else { - // Unsupported format - } - - - } else if ( params.contains( "Scale" ) ) { - sscanf( params.latin1(), "Scale( %i, %i, %1023s )", - &sWidth, &sHeight, sModeStr ); - - TQString sModeTQStr( sModeStr ); - if ( sModeTQStr == "ScaleFree" ) { - sMode = TQ_ScaleFree; - } else if ( sModeTQStr == "ScaleMin" ) { - sMode = TQ_ScaleMin; - } else if ( sModeTQStr == "ScaleMax" ) { - sMode = TQ_ScaleMax; - } else { - qDebug("read_jpeg_image: invalid scale mode \"%s\", see TTQ_ScaleMode documentation", sModeStr); - sMode = TQ_ScaleFree; - } - -// qDebug( "Parameters ask to scale the image to %i x %i ScaleMode: %s", sWidth, sHeight, sModeStr ); - scaleSize( sWidth, sHeight, cinfo.output_width, cinfo.output_height, sMode ); -// qDebug( "Scaling the jpeg to %i x %i", sWidth, sHeight, sModeStr ); - - bool created = FALSE; - if ( cinfo.output_components == 3 || cinfo.output_components == 4) { - created = image.create( sWidth, sHeight, 32 ); - } else if ( cinfo.output_components == 1 ) { - created = image.create( sWidth, sHeight, 8, 256 ); - for (int i=0; i<256; i++) - image.setColor(i, tqRgb(i,i,i)); - } else { - // Unsupported format - } - if (!created) - image = TQImage(); - - if (!image.isNull()) { - TQImage tmpImage( cinfo.output_width, 1, 32 ); - uchar** inLines = tmpImage.jumpTable(); - uchar** outLines = image.jumpTable(); - while (cinfo.output_scanline < cinfo.output_height) { - int outputLine = sHeight * cinfo.output_scanline / cinfo.output_height; - (void) jpeg_read_scanlines(&cinfo, inLines, 1); - if ( cinfo.output_components == 3 ) { - uchar *in = inLines[0]; - TQRgb *out = (TQRgb*)outLines[outputLine]; - for (uint i=0; i<cinfo.output_width; i++ ) { -// ### Only scaling down an image works, I don't think scaling up will work at the moment -// ### An idea I have to make this a smooth scale is to progressively add the pixel values up -// When scaling down, multiple values are being over drawn in to the output buffer. -// Instead, a weighting based on the distance the line or pixel is from the output pixel determines -// the weight of it when added to the output buffer. At present it is a non-smooth scale which is -// inefficently implemented, it still uncompresses all the jpeg, an optimization for progressive -// jpegs could be made if scaling by say 50% or some other special cases - out[sWidth * i / cinfo.output_width] = tqRgb( in[0], in[1], in[2] ); - in += 3; - } - } else { -// ### Need to test the case where the jpeg is grayscale, need some black and white jpegs to test -// this code. (also only scales down and probably won't scale to a larger size) - uchar *in = inLines[0]; - uchar *out = outLines[outputLine]; - for (uint i=0; i<cinfo.output_width; i++ ) { - out[sWidth * i / cinfo.output_width] = in[i]; - } - } - } - (void) jpeg_finish_decompress(&cinfo); - } - - } else { - - bool created = FALSE; - if ( cinfo.output_components == 3 || cinfo.output_components == 4) { - created = image.create( cinfo.output_width, cinfo.output_height, 32 ); - } else if ( cinfo.output_components == 1 ) { - created = image.create( cinfo.output_width, cinfo.output_height, 8, 256 ); - for (int i=0; i<256; i++) - image.setColor(i, tqRgb(i,i,i)); - } else { - // Unsupported format - } - if (!created) - image = TQImage(); - - if (!image.isNull()) { - uchar** lines = image.jumpTable(); - while (cinfo.output_scanline < cinfo.output_height) - (void) jpeg_read_scanlines(&cinfo, - lines + cinfo.output_scanline, - cinfo.output_height); - (void) jpeg_finish_decompress(&cinfo); - - if ( cinfo.output_components == 3 ) { - // Expand 24->32 bpp. - for (uint j=0; j<cinfo.output_height; j++) { - uchar *in = image.scanLine(j) + cinfo.output_width * 3; - TQRgb *out = (TQRgb*)image.scanLine(j); - - for (uint i=cinfo.output_width; i--; ) { - in-=3; - out[i] = tqRgb(in[0], in[1], in[2]); - } - } - } - } - } - - if (!image.isNull()) { - if ( cinfo.density_unit == 1 ) { - image.setDotsPerMeterX( int(100. * cinfo.X_density / 2.54) ); - image.setDotsPerMeterY( int(100. * cinfo.Y_density / 2.54) ); - } else if ( cinfo.density_unit == 2 ) { - image.setDotsPerMeterX( int(100. * cinfo.X_density) ); - image.setDotsPerMeterY( int(100. * cinfo.Y_density) ); - } - } - - iio->setImage(image); - iio->setqStatus(image.isNull()); - } - - jpeg_destroy_decompress(&cinfo); - delete iod_src; -} - - -struct my_jpeg_destination_mgr : public jpeg_destination_mgr { - // Nothing dynamic - cannot rely on destruction over longjump - TQImageIO* iio; - JOCTET buffer[max_buf]; - -public: - my_jpeg_destination_mgr(TQImageIO*); -}; - - -#if defined(TQ_C_CALLBACKS) -extern "C" { -#endif - -static -void qt_init_destination(j_compress_ptr) -{ -} - -static -void qt_exit_on_error(j_compress_ptr cinfo, TQIODevice* dev) -{ - if (dev->status() == IO_Ok) { - return; - } else { - // cinfo->err->msg_code = JERR_FILE_WRITE; - (*cinfo->err->error_exit)((j_common_ptr)cinfo); - } -} - -static -boolean qt_empty_output_buffer(j_compress_ptr cinfo) -{ - my_jpeg_destination_mgr* dest = (my_jpeg_destination_mgr*)cinfo->dest; - TQIODevice* dev = dest->iio->ioDevice(); - - if ( dev->writeBlock( (char*)dest->buffer, max_buf ) != max_buf ) - qt_exit_on_error(cinfo, dev); - - dest->next_output_byte = dest->buffer; - dest->free_in_buffer = max_buf; - -#if defined(TQ_OS_UNIXWARE) - return B_TRUE; -#else - return TRUE; -#endif -} - -static -void qt_term_destination(j_compress_ptr cinfo) -{ - my_jpeg_destination_mgr* dest = (my_jpeg_destination_mgr*)cinfo->dest; - TQIODevice* dev = dest->iio->ioDevice(); - TQ_LONG n = max_buf - dest->free_in_buffer; - - if ( dev->writeBlock( (char*)dest->buffer, n ) != n ) - qt_exit_on_error(cinfo, dev); - - dev->flush(); - - qt_exit_on_error(cinfo, dev); -} - -#if defined(TQ_C_CALLBACKS) -} -#endif - - -inline -my_jpeg_destination_mgr::my_jpeg_destination_mgr(TQImageIO* iioptr) -{ - jpeg_destination_mgr::init_destination = qt_init_destination; - jpeg_destination_mgr::empty_output_buffer = qt_empty_output_buffer; - jpeg_destination_mgr::term_destination = qt_term_destination; - iio = iioptr; - next_output_byte = buffer; - free_in_buffer = max_buf; -} - - -static -void write_jpeg_image(TQImageIO* iio) -{ - TQImage image = iio->image(); - - struct jpeg_compress_struct cinfo; - JSAMPROW row_pointer[1]; - row_pointer[0] = 0; - - struct my_jpeg_destination_mgr *iod_dest = new my_jpeg_destination_mgr(iio); - struct my_error_mgr jerr; - - cinfo.err = jpeg_std_error(&jerr); - - jerr.error_exit = my_error_exit; - - if (!setjmp(jerr.setjmp_buffer)) { - jpeg_create_compress(&cinfo); - - cinfo.dest = iod_dest; - - cinfo.image_width = image.width(); - cinfo.image_height = image.height(); - - TQRgb* cmap=0; - bool gray=FALSE; - switch ( image.depth() ) { - case 1: - case 8: - cmap = image.tqcolorTable(); - gray = TRUE; - int i; - for (i=image.numColors(); gray && i--; ) { - gray = gray & ( tqRed(cmap[i]) == tqGreen(cmap[i]) && - tqRed(cmap[i]) == tqBlue(cmap[i]) ); - } - cinfo.input_components = gray ? 1 : 3; - cinfo.in_color_space = gray ? JCS_GRAYSCALE : JCS_RGB; - break; - case 32: - cinfo.input_components = 3; - cinfo.in_color_space = JCS_RGB; - } - - jpeg_set_defaults(&cinfo); - - float diffInch = TQABS(image.dotsPerMeterX()*2.54/100. - tqRound(image.dotsPerMeterX()*2.54/100.)) - + TQABS(image.dotsPerMeterY()*2.54/100. - tqRound(image.dotsPerMeterY()*2.54/100.)); - float diffCm = (TQABS(image.dotsPerMeterX()/100. - tqRound(image.dotsPerMeterX()/100.)) - + TQABS(image.dotsPerMeterY()/100. - tqRound(image.dotsPerMeterY()/100.)))*2.54; - if (diffInch < diffCm) { - cinfo.density_unit = 1; // dots/inch - cinfo.X_density = tqRound(image.dotsPerMeterX()*2.54/100.); - cinfo.Y_density = tqRound(image.dotsPerMeterY()*2.54/100.); - } else { - cinfo.density_unit = 2; // dots/cm - cinfo.X_density = (image.dotsPerMeterX()+50) / 100; - cinfo.Y_density = (image.dotsPerMeterY()+50) / 100; - } - - int quality = iio->quality() >= 0 ? TQMIN(iio->quality(),100) : 75; -#if defined(TQ_OS_UNIXWARE) - jpeg_set_quality(&cinfo, quality, B_TRUE /* limit to baseline-JPEG values */); - jpeg_start_compress(&cinfo, B_TRUE); -#else - jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */); - jpeg_start_compress(&cinfo, TRUE); -#endif - - row_pointer[0] = new uchar[cinfo.image_width*cinfo.input_components]; - int w = cinfo.image_width; - while (cinfo.next_scanline < cinfo.image_height) { - uchar *row = row_pointer[0]; - switch ( image.depth() ) { - case 1: - if (gray) { - uchar* data = image.scanLine(cinfo.next_scanline); - if ( image.bitOrder() == TQImage::LittleEndian ) { - for (int i=0; i<w; i++) { - bool bit = !!(*(data + (i >> 3)) & (1 << (i & 7))); - row[i] = tqRed(cmap[bit]); - } - } else { - for (int i=0; i<w; i++) { - bool bit = !!(*(data + (i >> 3)) & (1 << (7 -(i & 7)))); - row[i] = tqRed(cmap[bit]); - } - } - } else { - uchar* data = image.scanLine(cinfo.next_scanline); - if ( image.bitOrder() == TQImage::LittleEndian ) { - for (int i=0; i<w; i++) { - bool bit = !!(*(data + (i >> 3)) & (1 << (i & 7))); - *row++ = tqRed(cmap[bit]); - *row++ = tqGreen(cmap[bit]); - *row++ = tqBlue(cmap[bit]); - } - } else { - for (int i=0; i<w; i++) { - bool bit = !!(*(data + (i >> 3)) & (1 << (7 -(i & 7)))); - *row++ = tqRed(cmap[bit]); - *row++ = tqGreen(cmap[bit]); - *row++ = tqBlue(cmap[bit]); - } - } - } - break; - case 8: - if (gray) { - uchar* pix = image.scanLine(cinfo.next_scanline); - for (int i=0; i<w; i++) { - *row = tqRed(cmap[*pix]); - ++row; ++pix; - } - } else { - uchar* pix = image.scanLine(cinfo.next_scanline); - for (int i=0; i<w; i++) { - *row++ = tqRed(cmap[*pix]); - *row++ = tqGreen(cmap[*pix]); - *row++ = tqBlue(cmap[*pix]); - ++pix; - } - } - break; - case 32: { - TQRgb* rgb = (TQRgb*)image.scanLine(cinfo.next_scanline); - for (int i=0; i<w; i++) { - *row++ = tqRed(*rgb); - *row++ = tqGreen(*rgb); - *row++ = tqBlue(*rgb); - ++rgb; - } - } - } - jpeg_write_scanlines(&cinfo, row_pointer, 1); - } - - jpeg_finish_compress(&cinfo); - jpeg_destroy_compress(&cinfo); - - iio->setqStatus(0); - } - - delete iod_dest; - delete [] row_pointer[0]; -} - -void qInitJpegIO() -{ - // Not much to go on - just 3 bytes: 0xFF, M_SOI, 0xFF - // Even the third is not strictly specified as required. - TQImageIO::defineIOHandler("JPEG", "^\377\330\377", 0, read_jpeg_image, write_jpeg_image); -} - -#endif |