📄 qbmphandler.cpp
字号:
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; 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) // Protection if ((uint)x >= (uint)w) x = w-1; if ((uint)y >= (uint)h) y = h-1; { quint8 tmp; d->getChar((char *)&tmp); x += tmp; d->getChar((char *)&tmp); y += tmp; } p = data + (h-y-1)*bpl + x; break; default: // absolute mode // Protection if (p + b > endp) b = endp-p; if (d->read((char *)p, b) != b) return false; if ((b & 1) == 1) d->getChar(0); // align on word boundary x += b; p += b; } } else { // encoded mode // Protection if (p + b > endp) b = endp-p; char tmp; d->getChar(&tmp); memset(p, tmp, b); // repeat pixel x += b; p += b; } } } else if (comp == BMP_RGB) { // uncompressed while (--h >= 0) { if (d->read((char *)data + h*bpl, bpl) != bpl) break; } } } else if (nbits == 16 || nbits == 24 || nbits == 32) { // 16,24,32 bit BMP image register QRgb *p; QRgb *end; uchar *buf24 = new uchar[bpl]; int bpl24 = ((w*nbits+31)/32)*4; uchar *b; int c; while (--h >= 0) { p = (QRgb *)(data + h*bpl); end = p + w; if (d->read((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++ = qRgb(((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; } if (bi.biHeight < 0) { // Flip the image uchar *buf = new uchar[bpl]; h = -bi.biHeight; for (int y = 0; y < h/2; ++y) { memcpy(buf, data + y*bpl, bpl); memcpy(data + y*bpl, data + (h-y-1)*bpl, bpl); memcpy(data + (h-y-1)*bpl, buf, bpl); } delete [] buf; } return true;}// this is also used in qmime_win.cppbool qt_write_dib(QDataStream &s, QImage image){ int nbits; int bpl_bmp; int bpl = image.bytesPerLine(); QIODevice* d = s.device(); if (!d->isWritable()) return false; 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 Q_WS_QWS } else if (image.depth() == 1 || image.depth() == 8) { // Qt/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 (s.status() != QDataStream::Ok) return false; if (image.depth() != 32) { // write color table uchar *color_table = new uchar[4*image.numColors()]; uchar *rgb = color_table; QVector<QRgb> c = image.colorTable(); for (int i=0; i<image.numColors(); i++) { *rgb++ = qBlue (c[i]); *rgb++ = qGreen(c[i]); *rgb++ = qRed (c[i]); *rgb++ = 0; } if (d->write((char *)color_table, 4*image.numColors()) == -1) { delete [] color_table; return false; } delete [] color_table; } if (image.format() == QImage::Format_MonoLSB) image = image.convertToFormat(QImage::Format_Mono); int y; if (nbits == 1 || nbits == 8) { // direct output#ifdef Q_WS_QWS // Qt/E doesn't word align. int pad = bpl_bmp - bpl; char padding[4];#endif for (y=image.height()-1; y>=0; y--) { if (d->write((char*)image.scanLine(y), bpl) == -1) return false;#ifdef Q_WS_QWS if (d->write(padding, pad) == -1) return false;#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 QRgb *p = (QRgb *)image.scanLine(y); QRgb *end = p + image.width(); b = buf; while (p < end) { *b++ = qBlue(*p); *b++ = qGreen(*p); *b++ = qRed(*p); p++; } } if (bpl_bmp != d->write((char*)buf, bpl_bmp)) { delete[] buf; return false; } } delete[] buf; return true;}// this is also used in qmime_win.cppbool qt_read_dib(QDataStream &s, QImage &image){ BMP_INFOHDR bi; if (!read_dib_infoheader(s, bi)) return false; return read_dib_body(s, bi, -1, -BMP_FILEHDR_SIZE, image);}QBmpHandler::QBmpHandler() : state(Ready){}bool QBmpHandler::readHeader(){ state = Error; QIODevice *d = device(); QDataStream s(d); startpos = d->pos(); // Intel byte order s.setByteOrder(QDataStream::LittleEndian); // read BMP file header if (!read_dib_fileheader(s, fileHeader)) return false; // read BMP info header if (!read_dib_infoheader(s, infoHeader)) return false; state = ReadHeader; return true;}bool QBmpHandler::canRead() const{ if (state == Ready) { if (!canRead(device())) return false; setFormat("bmp"); return true; } return state != Error;}bool QBmpHandler::canRead(QIODevice *device){ if (!device) { qWarning("QBmpHandler::canRead() called with 0 pointer"); return false; } char head[2]; if (device->peek(head, sizeof(head)) != sizeof(head)) return false; return (qstrncmp(head, "BM", 2) == 0);}bool QBmpHandler::read(QImage *image){ if (state == Error) return false; if (!image) { qWarning("QBmpHandler::read: cannot read into null pointer"); return false; } if (state == Ready && !readHeader()) { state = Error; return false; } QIODevice *d = device(); QDataStream s(d); // Intel byte order s.setByteOrder(QDataStream::LittleEndian); // read image if (!read_dib_body(s, infoHeader, fileHeader.bfOffBits, startpos, *image)) return false; state = Ready; return true;}bool QBmpHandler::write(const QImage &img){ QImage image = img; if (image.format() == QImage::Format_RGB16) image = image.convertToFormat(QImage::Format_RGB32); QIODevice *d = device(); QDataStream 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; } // Intel byte order s.setByteOrder(QDataStream::LittleEndian); // build file header memcpy(bf.bfType, "BM", 2); // write file header bf.bfReserved1 = 0; bf.bfReserved2 = 0; bf.bfOffBits = BMP_FILEHDR_SIZE + BMP_WIN + image.numColors() * 4; bf.bfSize = bf.bfOffBits + bpl_bmp*image.height(); s << bf; // write image return qt_write_dib(s, image);}bool QBmpHandler::supportsOption(ImageOption option) const{ return option == Size;}QVariant QBmpHandler::option(ImageOption option) const{ if (option == Size) { if (state == Error) return QVariant(); if (state == Ready && !const_cast<QBmpHandler*>(this)->readHeader()) return QVariant(); return QSize(infoHeader.biWidth, infoHeader.biHeight); } return QVariant();}void QBmpHandler::setOption(ImageOption option, const QVariant &value){ Q_UNUSED(option); Q_UNUSED(value);}QByteArray QBmpHandler::name() const{ return "bmp";}#endif // QT_NO_IMAGEFORMAT_BMP
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -