⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qjpeghandler.cpp

📁 qt-x11-opensource-src-4.1.4.tar.gz源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved.**** This file is part of the plugins of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.0 as published by the Free Software Foundation** and appearing in the file LICENSE.GPL included in the packaging of** this file.  Please review the following information to ensure GNU** General Public Licensing requirements will be met:** http://www.trolltech.com/products/qt/opensource.html**** If you are unsure which license is appropriate for your use, please** review the following information:** http://www.trolltech.com/products/qt/licensing.html or contact the** sales department at sales@trolltech.com.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include "qjpeghandler.h"#include <qimage.h>#include <qvariant.h>#include <qvector.h>#include <stdio.h>      // jpeglib needs this to be pre-included#include <setjmp.h>#ifdef FAR#undef FAR#endif// including jpeglib.h seems to be a little messyextern "C" {// mingw includes rpcndr.h but does not define boolean#if defined(Q_OS_WIN) && defined(Q_CC_GNU)#   if defined(__RPCNDR_H__) && !defined(boolean)        typedef unsigned char boolean;#       define HAVE_BOOLEAN#   endif#endif#define XMD_H           // shut JPEGlib up#if defined(Q_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(Q_C_CALLBACKS)extern "C" {#endifstaticvoid 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("%s", buffer);    longjmp(myerr->setjmp_buffer, 1);}#if defined(Q_C_CALLBACKS)}#endifstatic const int max_buf = 4096;struct my_jpeg_source_mgr : public jpeg_source_mgr {    // Nothing dynamic - cannot rely on destruction over longjump    QIODevice *device;    JOCTET buffer[max_buf];public:    my_jpeg_source_mgr(QIODevice *device);};#if defined(Q_C_CALLBACKS)extern "C" {#endifstaticvoid qt_init_source(j_decompress_ptr){}staticboolean qt_fill_input_buffer(j_decompress_ptr cinfo){    int num_read;    my_jpeg_source_mgr* src = (my_jpeg_source_mgr*)cinfo->src;    src->next_input_byte = src->buffer;    num_read = src->device->read((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(Q_OS_UNIXWARE)    return B_TRUE;#else    return true;#endif}staticvoid 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;    }}staticvoid qt_term_source(j_decompress_ptr){}#if defined(Q_C_CALLBACKS)}#endifinline my_jpeg_source_mgr::my_jpeg_source_mgr(QIODevice *device){    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;    this->device = device;    bytes_in_buffer = 0;    next_input_byte = buffer;}staticvoid scaleSize(int &reqW, int &reqH, int imgW, int imgH, Qt::AspectRatioMode mode){    if (mode == Qt::IgnoreAspectRatio)        return;    int t1 = imgW * reqH;    int t2 = reqW * imgH;    if ((mode == Qt::KeepAspectRatio && (t1 > t2)) || (mode == Qt::KeepAspectRatioByExpanding && (t1 < t2)))        reqH = t2 / imgW;    else        reqW = t1 / imgH;}static bool read_jpeg_image(QIODevice *device, QImage *outImage, const QByteArray &parameters){    QImage image;    struct jpeg_decompress_struct cinfo;    struct my_jpeg_source_mgr *iod_src = new my_jpeg_source_mgr(device);    struct my_error_mgr jerr;    jpeg_create_decompress(&cinfo);    cinfo.src = iod_src;    cinfo.err = jpeg_std_error(&jerr);    jerr.error_exit = my_error_exit;    if (!setjmp(jerr.setjmp_buffer)) {#if defined(Q_OS_UNIXWARE)        (void) jpeg_read_header(&cinfo, B_TRUE);#else        (void) jpeg_read_header(&cinfo, true);#endif        (void) jpeg_start_decompress(&cinfo);        QString params = parameters;        params.simplified();        int sWidth = 0, sHeight = 0;        char sModeStr[1024] = "";        Qt::AspectRatioMode sMode;        if (params.contains("GetHeaderInformation")) {            // Create QImage but don't read the pixels            if (cinfo.output_components == 3 || cinfo.output_components == 4) {                image = QImage(cinfo.output_width, cinfo.output_height, QImage::Format_RGB32);            } else if (cinfo.output_components == 1) {                image = QImage(cinfo.output_width, cinfo.output_height, QImage::Format_Indexed8);            } else {                // Unsupported format            }        } else if (params.contains("Scale")) {#if defined(_MSC_VER) && _MSC_VER >= 1400            sscanf_s(params.toLatin1().data(), "Scale(%i, %i, %1023s)",                   &sWidth, &sHeight, sModeStr, sizeof(sModeStr));#else            sscanf(params.toLatin1().data(), "Scale(%i, %i, %1023s)",                   &sWidth, &sHeight, sModeStr);#endif            QString sModeQStr(sModeStr);            if (sModeQStr == "IgnoreAspectRatio") {                sMode = Qt::IgnoreAspectRatio;            } else if (sModeQStr == "KeepAspectRatio") {                sMode = Qt::KeepAspectRatio;            } else if (sModeQStr == "KeepAspectRatioByExpanding") {                sMode = Qt::KeepAspectRatioByExpanding;            } else {                qDebug("read_jpeg_image: invalid aspect ratio mode \"%s\", see QImage::AspectRatioMode documentation", sModeStr);                sMode = Qt::KeepAspectRatio;            }//            qDebug("Parameters ask to scale the image to %i x %i AspectRatioMode: %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);            if (cinfo.output_components == 3 || cinfo.output_components == 4) {                image = QImage(sWidth, sHeight, QImage::Format_RGB32);            } else if (cinfo.output_components == 1) {                image = QImage(sWidth, sHeight, QImage::Format_Indexed8);                image.setNumColors(256);                for (int i=0; i<256; i++)                    image.setColor(i, qRgb(i,i,i));            } else {                // Unsupported format            }            if (image.isNull())                return false;            if (!image.isNull()) {                QImage tmpImage(cinfo.output_width, 1, QImage::Format_RGB32);                uchar* inData = tmpImage.bits();                uchar* outData = image.bits();                int out_bpl = image.bytesPerLine();                while (cinfo.output_scanline < cinfo.output_height) {                    int outputLine = sHeight * cinfo.output_scanline / cinfo.output_height;                    (void) jpeg_read_scanlines(&cinfo, &inData, 1);                    if (cinfo.output_components == 3) {                        uchar *in = inData;                        QRgb *out = (QRgb*)outData + outputLine * out_bpl;                        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] = qRgb(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 = inData;                        uchar *out = outData + outputLine*out_bpl;                        for (uint i=0; i<cinfo.output_width; i++) {                            out[sWidth * i / cinfo.output_width] = in[i];                        }                    }                }                (void) jpeg_finish_decompress(&cinfo);            }        } else {            if (cinfo.output_components == 3 || cinfo.output_components == 4) {                image = QImage(cinfo.output_width, cinfo.output_height, QImage::Format_RGB32);            } else if (cinfo.output_components == 1) {                image = QImage(cinfo.output_width, cinfo.output_height, QImage::Format_Indexed8);                image.setNumColors(256);                for (int i=0; i<256; i++)                    image.setColor(i, qRgb(i,i,i));            } else {                // Unsupported format            }            if (image.isNull())                return false;            if (!image.isNull()) {                uchar* data = image.bits();                int bpl = image.bytesPerLine();                while (cinfo.output_scanline < cinfo.output_height) {                    uchar *d = data + cinfo.output_scanline * bpl;                    (void) jpeg_read_scanlines(&cinfo,                                               &d,                                               1);                }                (void) jpeg_finish_decompress(&cinfo);                if (cinfo.output_components == 3) {                    // Expand 24->32 bpp.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -