📄 qbmphandler.cpp
字号:
/******************************************************************************** Copyright (C) 1992-2007 Trolltech ASA. All rights reserved.**** This file is part of the QtGui module 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://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.**** In addition, as a special exception, Trolltech gives you certain** additional rights. These rights are described in the Trolltech GPL** Exception version 1.0, which can be found at** http://www.trolltech.com/products/qt/gplexception/ and in the file** GPL_EXCEPTION.txt in this package.**** In addition, as a special exception, Trolltech, as the sole copyright** holder for Qt Designer, grants users of the Qt/Eclipse Integration** plug-in the right for the Qt/Eclipse Integration to link to** functionality provided by Qt Designer and its related libraries.**** Trolltech reserves all rights not expressly granted herein.**** 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 "private/qbmphandler_p.h"#ifndef QT_NO_IMAGEFORMAT_BMP#include <qimage.h>#include <qvariant.h>#include <qvector.h>static void swapPixel01(QImage *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; i<nbytes/4; i++) { *p = ~*p; p++; } uchar *p2 = (uchar *)p; for (i=0; i<(nbytes&3); i++) { *p2 = ~*p2; p2++; } QRgb t = image->color(0); // swap color 0 and 1 image->setColor(0, image->color(1)); image->setColor(1, t); }}/* QImageIO::defineIOHandler("BMP", "^BM", 0, read_bmp_image, write_bmp_image);*//***************************************************************************** BMP (DIB) image read/write functions *****************************************************************************/const int BMP_FILEHDR_SIZE = 14; // size of BMP_FILEHDR dataQDataStream &operator>>(QDataStream &s, BMP_FILEHDR &bf){ // read file header s.readRawData(bf.bfType, 2); s >> bf.bfSize >> bf.bfReserved1 >> bf.bfReserved2 >> bf.bfOffBits; return s;}QDataStream &operator<<(QDataStream &s, const BMP_FILEHDR &bf){ // write file header s.writeRawData(bf.bfType, 2); s << bf.bfSize << bf.bfReserved1 << bf.bfReserved2 << bf.bfOffBits; return s;}const int BMP_OLD = 12; // old Windows/OS2 BMP sizeconst int BMP_WIN = 40; // new Windows BMP sizeconst int BMP_OS2 = 64; // new OS/2 BMP sizeconst int BMP_RGB = 0; // no compressionconst int BMP_RLE8 = 1; // run-length encoded, 8 bitsconst int BMP_RLE4 = 2; // run-length encoded, 4 bitsconst int BMP_BITFIELDS = 3; // RGB values encoded in data as bit-fieldsQDataStream &operator>>(QDataStream &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 qint16 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;}QDataStream &operator<<(QDataStream &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_fileheader(QDataStream &s, BMP_FILEHDR &bf){ // read BMP file header s >> bf; if (s.status() != QDataStream::Ok) return false; // check header if (qstrncmp(bf.bfType,"BM",2) != 0) return false; return true;}static bool read_dib_infoheader(QDataStream &s, BMP_INFOHDR &bi){ s >> bi; // read BMP info header if (s.status() != QDataStream::Ok) return false; int nbits = bi.biBitCount; int comp = bi.biCompression; 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 return true;}static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, int offset, int startpos, QImage &image){ QIODevice* d = s.device(); 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 = 0; int green_mask = 0; int blue_mask = 0; int red_shift = 0; int green_shift = 0; int blue_shift = 0; int red_scale = 0; int green_scale = 0; int blue_scale = 0; int ncols = 0; int depth = 0; QImage::Format format; switch (nbits) { case 32: case 24: case 16: depth = 32; format = QImage::Format_RGB32; break; case 8: case 4: depth = 8; format = QImage::Format_Indexed8; break; default: depth = 1; format = QImage::Format_Mono; } if (bi.biHeight < 0) h = -h; // support images with negative height if (image.size() != QSize(w, h) || image.format() != format) { image = QImage(w, h, format); if (image.isNull()) // could not create image return false; } if (depth != 32) { ncols = bi.biClrUsed ? bi.biClrUsed : 1 << nbits; image.setNumColors(ncols); } image.setDotsPerMeterX(bi.biXPelsPerMeter); image.setDotsPerMeterY(bi.biYPelsPerMeter); if (!d->isSequential()) d->seek(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; i<ncols; i++) { if (d->read((char *)rgb, rgb_len) != rgb_len) return false; image.setColor(i, qRgb(rgb[2],rgb[1],rgb[0])); if (d->atEnd()) // truncated file return false; } } else if (comp == BMP_BITFIELDS && (nbits == 16 || nbits == 32)) { if (d->read((char *)&red_mask, sizeof(red_mask)) != sizeof(red_mask)) return false; if (d->read((char *)&green_mask, sizeof(green_mask)) != sizeof(green_mask)) return false; if (d->read((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) { blue_mask = 0x001f; green_mask = 0x03e0; red_mask = 0x7c00; blue_shift = 0; green_shift = 2; red_shift = 7; red_scale = 1; green_scale = 1; blue_scale = 8; } // offset can be bogus, be careful if (offset>=0 && startpos + offset > d->pos()) { if (!d->isSequential()) d->seek(startpos + offset); // start of image data } int bpl = image.bytesPerLine(); uchar *data = image.bits(); if (nbits == 1) { // 1 bit BMP image while (--h >= 0) { if (d->read((char*)(data + h*bpl), bpl) != bpl) break; } if (ncols == 2 && qGray(image.color(0)) < qGray(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]; if (comp == BMP_RLE4) { // run length compression int x=0, y=0, c, i; quint8 b; register uchar *p = data + (h-1)*bpl; const uchar *endp = p + w; while (y < h) { if (!d->getChar((char *)&b)) break; if (b == 0) { // escape code if (!d->getChar((char *)&b) || b == 1) { y = h; // exit loop } else switch (b) { case 0: // end of line x = 0; y++; p = data + (h-y-1)*bpl; break; case 2: // delta (jump) { quint8 tmp; d->getChar((char *)&tmp); x += tmp; d->getChar((char *)&tmp); y += tmp; } // Protection if ((uint)x >= (uint)w) x = w-1; if ((uint)y >= (uint)h) y = h-1; p = data + (h-y-1)*bpl + x; break; default: // absolute mode // Protection if (p + b > endp) b = endp-p; i = (c = b)/2; while (i--) { d->getChar((char *)&b); *p++ = b >> 4; *p++ = b & 0x0f; } if (c & 1) { unsigned char tmp; d->getChar((char *)&tmp); *p++ = tmp >> 4; } if ((((c & 3) + 1) & 2) == 2) d->getChar(0); // align on word boundary x += c; } } else { // encoded mode // Protection if (p + b > endp) b = endp-p; i = (c = b)/2; d->getChar((char *)&b); // 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 memset(data, 0, h*bpl); while (--h >= 0) { if (d->read((char*)buf,buflen) != buflen) break; register uchar *p = data + h*bpl; uchar *b = buf; for (int i=0; i<w/2; i++) { // convert nibbles to bytes *p++ = *b >> 4; *p++ = *b++ & 0x0f; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -