📄 qpixmap_x11.cpp
字号:
if (isNull()) return QImage(); // null image int w = width(); int h = height(); int d = depth(); Visual *visual = (Visual *) data->xinfo.visual(); bool trucol = (visual->c_class >= TrueColor) && d > 1; QImage::Format format = QImage::Format_Mono; if (d > 1 && d <= 8) { d = 8; format = QImage::Format_Indexed8; } // we could run into the situation where d == 8 AND trucol is true, which can // cause problems when converting to and from images. in this case, always treat // the depth as 32... if (d > 8 || trucol) { d = 32; format = QImage::Format_RGB32; } XImage *xi = XGetImage(X11->display, data->hd, 0, 0, w, h, AllPlanes, (d == 1) ? XYPixmap : ZPixmap); Q_CHECK_PTR(xi); if (!xi) return QImage(); if (data->picture && data->d == 32) { QImage image(data->w, data->h, QImage::Format_ARGB32_Premultiplied); memcpy(image.bits(), xi->data, xi->bytes_per_line * xi->height); // we may have to swap the byte order if ((QSysInfo::ByteOrder == QSysInfo::LittleEndian && xi->byte_order == MSBFirst) || (QSysInfo::ByteOrder == QSysInfo::BigEndian)) { for (int i=0; i < image.height(); i++) { uint *p = (uint*) image.scanLine(i); uint *end = p + image.width(); if ((xi->byte_order == LSBFirst && QSysInfo::ByteOrder == QSysInfo::BigEndian) || (xi->byte_order == MSBFirst && QSysInfo::ByteOrder == QSysInfo::LittleEndian)) { while (p < end) { *p = ((*p << 24) & 0xff000000) | ((*p << 8) & 0x00ff0000) | ((*p >> 8) & 0x0000ff00) | ((*p >> 24) & 0x000000ff); p++; } } else if (xi->byte_order == MSBFirst && QSysInfo::ByteOrder == QSysInfo::BigEndian) { while (p < end) { *p = ((*p << 16) & 0x00ff0000) | ((*p >> 16) & 0x000000ff) | ((*p ) & 0xff00ff00); p++; } } } } // throw away image data qSafeXDestroyImage(xi); return image; } if (d == 1 && xi->bitmap_bit_order == LSBFirst) format = QImage::Format_MonoLSB; if (data->x11_mask && format == QImage::Format_RGB32) format = QImage::Format_ARGB32; QImage image(w, h, format); if (image.isNull()) // could not create image return image; QImage alpha; if (data->x11_mask) { alpha = mask().toImage(); } bool ale = alpha.format() == QImage::Format_MonoLSB; if (trucol) { // truecolor const uint red_mask = (uint)visual->red_mask; const uint green_mask = (uint)visual->green_mask; const uint blue_mask = (uint)visual->blue_mask; const int red_shift = highest_bit(red_mask) - 7; const int green_shift = highest_bit(green_mask) - 7; const int blue_shift = highest_bit(blue_mask) - 7; const uint red_bits = n_bits(red_mask); const uint green_bits = n_bits(green_mask); const uint blue_bits = n_bits(blue_mask); static uint red_table_bits = 0; static uint green_table_bits = 0; static uint blue_table_bits = 0; if (red_bits < 8 && red_table_bits != red_bits) { build_scale_table(&red_scale_table, red_bits); red_table_bits = red_bits; } if (blue_bits < 8 && blue_table_bits != blue_bits) { build_scale_table(&blue_scale_table, blue_bits); blue_table_bits = blue_bits; } if (green_bits < 8 && green_table_bits != green_bits) { build_scale_table(&green_scale_table, green_bits); green_table_bits = green_bits; } int r, g, b; QRgb *dst; uchar *src; uint pixel; int bppc = xi->bits_per_pixel; if (bppc > 8 && xi->byte_order == LSBFirst) bppc++; for (int y = 0; y < h; y++) { uchar* asrc = data->x11_mask ? alpha.scanLine(y) : 0; dst = (QRgb *)image.scanLine(y); src = (uchar *)xi->data + xi->bytes_per_line*y; for (int x = 0; x < w; x++) { switch (bppc) { case 8: pixel = *src++; break; case 16: // 16 bit MSB pixel = src[1] | (uint)src[0] << 8; src += 2; break; case 17: // 16 bit LSB pixel = src[0] | (uint)src[1] << 8; src += 2; break; case 24: // 24 bit MSB pixel = src[2] | (uint)src[1] << 8 | (uint)src[0] << 16; src += 3; break; case 25: // 24 bit LSB pixel = src[0] | (uint)src[1] << 8 | (uint)src[2] << 16; src += 3; break; case 32: // 32 bit MSB pixel = src[3] | (uint)src[2] << 8 | (uint)src[1] << 16 | (uint)src[0] << 24; src += 4; break; case 33: // 32 bit LSB pixel = src[0] | (uint)src[1] << 8 | (uint)src[2] << 16 | (uint)src[3] << 24; src += 4; break; default: // should not really happen x = w; // leave loop y = h; pixel = 0; // eliminate compiler warning qWarning("QPixmap::convertToImage: Invalid depth %d", bppc); } if (red_shift > 0) r = (pixel & red_mask) >> red_shift; else r = (pixel & red_mask) << -red_shift; if (green_shift > 0) g = (pixel & green_mask) >> green_shift; else g = (pixel & green_mask) << -green_shift; if (blue_shift > 0) b = (pixel & blue_mask) >> blue_shift; else b = (pixel & blue_mask) << -blue_shift; if (red_bits < 8) r = red_scale_table[r]; if (green_bits < 8) g = green_scale_table[g]; if (blue_bits < 8) b = blue_scale_table[b]; if (data->x11_mask) { if (ale) { *dst++ = (asrc[x >> 3] & (1 << (x & 7))) ? qRgba(r, g, b, 0xff) : 0; } else { *dst++ = (asrc[x >> 3] & (0x80 >> (x & 7))) ? qRgba(r, g, b, 0xff) : 0; } } else { *dst++ = qRgb(r, g, b); } } } } else if (xi->bits_per_pixel == d) { // compatible depth char *xidata = xi->data; // copy each scanline int bpl = qMin(image.bytesPerLine(),xi->bytes_per_line); for (int y=0; y<h; y++) { memcpy(image.scanLine(y), xidata, bpl); xidata += xi->bytes_per_line; } } else { /* Typically 2 or 4 bits display depth */ qWarning("QPixmap::convertToImage: Display not supported (bpp=%d)", xi->bits_per_pixel); return QImage(); } if (d == 1) { // bitmap image.setNumColors(2); image.setColor(0, qRgb(255,255,255)); image.setColor(1, qRgb(0,0,0)); } else if (!trucol) { // pixmap with colormap register uchar *p; uchar *end; uchar use[256]; // pixel-in-use table uchar pix[256]; // pixel translation table int ncols, bpl; memset(use, 0, 256); memset(pix, 0, 256); bpl = image.bytesPerLine(); if (data->x11_mask) { // which pixels are used? for (int i = 0; i < h; i++) { uchar* asrc = alpha.scanLine(i); p = image.scanLine(i); if (ale) { for (int x = 0; x < w; x++) { if (asrc[x >> 3] & (1 << (x & 7))) use[*p] = 1; ++p; } } else { for (int x = 0; x < w; x++) { if (asrc[x >> 3] & (0x80 >> (x & 7))) use[*p] = 1; ++p; } } } } else { for (int i = 0; i < h; i++) { p = image.scanLine(i); end = p + bpl; while (p < end) use[*p++] = 1; } } ncols = 0; for (int i = 0; i < 256; i++) { // build translation table if (use[i]) pix[i] = ncols++; } for (int i = 0; i < h; i++) { // translate pixels p = image.scanLine(i); end = p + bpl; while (p < end) { *p = pix[*p]; p++; } } if (data->x11_mask) { int trans; if (ncols < 256) { trans = ncols++; image.setNumColors(ncols); // create color table image.setColor(trans, 0x00000000); } else { image.setNumColors(ncols); // create color table // oh dear... no spare "transparent" pixel. // use first pixel in image (as good as any). trans = image.scanLine(0)[0]; } for (int i = 0; i < h; i++) { uchar* asrc = alpha.scanLine(i); p = image.scanLine(i); if (ale) { for (int x = 0; x < w; x++) { if (!(asrc[x >> 3] & (1 << (x & 7)))) *p = trans; ++p; } } else { for (int x = 0; x < w; x++) { if (!(asrc[x >> 3] & (1 << (7 -(x & 7))))) *p = trans; ++p; } } } } else { image.setNumColors(ncols); // create color table } QVector<QColor> colors = QColormap::instance(data->xinfo.screen()).colormap(); int j = 0; for (int i=0; i<colors.size(); i++) { // translate pixels if (use[i]) image.setColor(j++, 0xff000000 | colors.at(i).rgb()); } } qSafeXDestroyImage(xi); return image;}/*! \fn QPixmap QPixmap::fromImage(const QImage &image, Qt::ImageConversionFlags flags) Converts the given \a image to a pixmap using the specified \a flags to control the conversion. The \a flags argument is a bitwise-OR of the \l{Qt::ImageConversionFlags}. Passing 0 for \a flags sets all the default options. In case of monochrome and 8-bit images, the image is first converted to a 32-bit pixmap and then filled with the colors in the color table. If this is too expensive an operation, you can use QBitmap::fromImage() instead. \sa toImage(), {QPixmap#Pixmap Conversion}{Pixmap Conversion}*/QPixmap QPixmap::fromImage(const QImage &img, Qt::ImageConversionFlags flags){ QPixmap pixmap; if (img.isNull()) { qWarning("QPixmap::fromImage: Cannot convert a null image"); return pixmap; } QImage image = img; const int w = image.width(); const int h = image.height(); int d = image.depth(); const int dd = X11->use_xrender && img.hasAlphaChannel() ? 32 : pixmap.data->xinfo.depth(); bool force_mono = (dd == 1 || (flags & Qt::ColorMode_Mask) == Qt::MonoOnly); if (uint(w) >= 32768 || uint(h) >= 32768) return QPixmap(); // must be monochrome if (force_mono) { if (d != 1) { // dither image = image.convertToFormat(QImage::Format_MonoLSB, flags); d = 1; } } else { // can be both bool conv8 = false; if (d > 8 && dd <= 8) { // convert to 8 bit if ((flags & Qt::DitherMode_Mask) == Qt::AutoDither) flags = (flags & ~Qt::DitherMode_Mask) | Qt::PreferDither; conv8 = true; } else if ((flags & Qt::ColorMode_Mask) == Qt::ColorOnly) { conv8 = (d == 1); // native depth wanted } else if (d == 1) { if (image.numColors() == 2) { QRgb c0 = image.color(0); // Auto: convert to best QRgb c1 = image.color(1); conv8 = qMin(c0,c1) != qRgb(0,0,0) || qMax(c0,c1) != qRgb(255,255,255); } else { // eg. 1-color monochrome images (they do exist). conv8 = true; } } if (conv8) { image = image.convertToFormat(QImage::Format_Indexed8, flags); d = 8; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -