📄 qpixmap_x11.cpp
字号:
if (d == 1 || d == 16) { QImage im = image.convertToFormat(QImage::Format_RGB32, flags); return fromImage(im); } Display *dpy = X11->display; Visual *visual = (Visual *) pixmap.data->xinfo.visual(); XImage *xi = 0; bool trucol = (visual->c_class >= TrueColor); int nbytes = image.numBytes(); uchar *newbits= 0;#ifndef QT_NO_XRENDER if (X11->use_xrender && image.hasAlphaChannel()) { const QImage &cimage = image; pixmap.data->w = w; pixmap.data->h = h; pixmap.data->d = 32; pixmap.data->hd = (Qt::HANDLE)XCreatePixmap(dpy, RootWindow(dpy, pixmap.data->xinfo.screen()), w, h, pixmap.data->d); pixmap.data->picture = XRenderCreatePicture(X11->display, pixmap.data->hd, XRenderFindStandardFormat(X11->display, PictStandardARGB32), 0, 0); xi = XCreateImage(dpy, visual, pixmap.data->d, ZPixmap, 0, 0, w, h, 32, 0); Q_CHECK_PTR(xi); newbits = (uchar *)malloc(xi->bytes_per_line*h); Q_CHECK_PTR(newbits); xi->data = (char *)newbits; switch(cimage.format()) { case QImage::Format_Indexed8: { QVector<QRgb> colorTable = cimage.colorTable(); uint *xidata = (uint *)xi->data; for (int y = 0; y < h; ++y) { const uchar *p = cimage.scanLine(y); for (int x = 0; x < w; ++x) { const QRgb rgb = colorTable[p[x]]; const int a = qAlpha(rgb); if (a == 0xff) *xidata = rgb; else // RENDER expects premultiplied alpha *xidata = qRgba(qt_div_255(qRed(rgb) * a), qt_div_255(qGreen(rgb) * a), qt_div_255(qBlue(rgb) * a), a); ++xidata; } } } break; case QImage::Format_RGB32: { uint *xidata = (uint *)xi->data; for (int y = 0; y < h; ++y) { const QRgb *p = (const QRgb *) cimage.scanLine(y); for (int x = 0; x < w; ++x) *xidata++ = p[x] | 0xff000000; } } break; case QImage::Format_ARGB32: { uint *xidata = (uint *)xi->data; for (int y = 0; y < h; ++y) { const QRgb *p = (const QRgb *) cimage.scanLine(y); for (int x = 0; x < w; ++x) { const QRgb rgb = p[x]; const int a = qAlpha(rgb); if (a == 0xff) *xidata = rgb; else // RENDER expects premultiplied alpha *xidata = qRgba(qt_div_255(qRed(rgb) * a), qt_div_255(qGreen(rgb) * a), qt_div_255(qBlue(rgb) * a), a); ++xidata; } } } break; case QImage::Format_ARGB32_Premultiplied: { uint *xidata = (uint *)xi->data; for (int y = 0; y < h; ++y) { const QRgb *p = (const QRgb *) cimage.scanLine(y); memcpy(xidata, p, w*sizeof(QRgb)); xidata += w; } } break; default: Q_ASSERT(false); } if ((xi->byte_order == MSBFirst) != (QSysInfo::ByteOrder == QSysInfo::BigEndian)) { uint *xidata = (uint *)xi->data; uint *xiend = xidata + w*h; while (xidata < xiend) { *xidata = (*xidata >> 24) | ((*xidata >> 8) & 0xff00) | ((*xidata << 8) & 0xff0000) | (*xidata << 24); ++xidata; } } GC gc = XCreateGC(dpy, pixmap.data->hd, 0, 0); XPutImage(dpy, pixmap.data->hd, gc, xi, 0, 0, 0, 0, w, h); XFreeGC(dpy, gc); qSafeXDestroyImage(xi); return pixmap; }#endif // QT_NO_XRENDER if (trucol) { // truecolor display if (image.format() == QImage::Format_ARGB32_Premultiplied) image = image.convertToFormat(QImage::Format_ARGB32); const QImage &cimage = image; QRgb pix[256]; // pixel translation table const bool d8 = (d == 8); 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 rbits = highest_bit(red_mask) - lowest_bit(red_mask) + 1; const uint gbits = highest_bit(green_mask) - lowest_bit(green_mask) + 1; const uint bbits = highest_bit(blue_mask) - lowest_bit(blue_mask) + 1; if (d8) { // setup pixel translation QVector<QRgb> ctable = cimage.colorTable(); for (int i=0; i < cimage.numColors(); i++) { int r = qRed (ctable[i]); int g = qGreen(ctable[i]); int b = qBlue (ctable[i]); r = red_shift > 0 ? r << red_shift : r >> -red_shift; g = green_shift > 0 ? g << green_shift : g >> -green_shift; b = blue_shift > 0 ? b << blue_shift : b >> -blue_shift; pix[i] = (b & blue_mask) | (g & green_mask) | (r & red_mask) | ~(blue_mask | green_mask | red_mask); } } xi = XCreateImage(dpy, visual, dd, ZPixmap, 0, 0, w, h, 32, 0); Q_CHECK_PTR(xi); newbits = (uchar *)malloc(xi->bytes_per_line*h); Q_CHECK_PTR(newbits); if (!newbits) // no memory return QPixmap(); int bppc = xi->bits_per_pixel; bool contig_bits = n_bits(red_mask) == rbits && n_bits(green_mask) == gbits && n_bits(blue_mask) == bbits; bool dither_tc = // Want it? (flags & Qt::Dither_Mask) != Qt::ThresholdDither && (flags & Qt::DitherMode_Mask) != Qt::AvoidDither && // Need it? bppc < 24 && !d8 && // Can do it? (Contiguous bits?) contig_bits; static bool init=false; static int D[16][16]; if (dither_tc && !init) { // I also contributed this code to XV - WWA. /* The dither matrix, D, is obtained with this formula: D2 = [0 2] [3 1] D2*n = [4*Dn 4*Dn+2*Un] [4*Dn+3*Un 4*Dn+1*Un] */ int n,i,j; init=1; /* Set D2 */ D[0][0]=0; D[1][0]=2; D[0][1]=3; D[1][1]=1; /* Expand using recursive definition given above */ for (n=2; n<16; n*=2) { for (i=0; i<n; i++) { for (j=0; j<n; j++) { D[i][j]*=4; D[i+n][j]=D[i][j]+2; D[i][j+n]=D[i][j]+3; D[i+n][j+n]=D[i][j]+1; } } } init=true; } enum { BPP8, BPP16_565, BPP16_555, BPP16_MSB, BPP16_LSB, BPP24_888, BPP24_MSB, BPP24_LSB, BPP32_8888, BPP32_MSB, BPP32_LSB } mode = BPP8; bool same_msb_lsb = (xi->byte_order == MSBFirst) == (QSysInfo::ByteOrder == QSysInfo::BigEndian); if(bppc == 8) // 8 bit mode = BPP8; else if(bppc == 16) { // 16 bit MSB/LSB if(red_shift == 8 && green_shift == 3 && blue_shift == -3 && !d8 && same_msb_lsb) mode = BPP16_565; else if(red_shift == 7 && green_shift == 2 && blue_shift == -3 && !d8 && same_msb_lsb) mode = BPP16_555; else mode = (xi->byte_order == LSBFirst) ? BPP16_LSB : BPP16_MSB; } else if(bppc == 24) { // 24 bit MSB/LSB if (red_shift == 16 && green_shift == 8 && blue_shift == 0 && !d8 && same_msb_lsb) mode = BPP24_888; else mode = (xi->byte_order == LSBFirst) ? BPP24_LSB : BPP24_MSB; } else if(bppc == 32) { // 32 bit MSB/LSB if(red_shift == 16 && green_shift == 8 && blue_shift == 0 && !d8 && same_msb_lsb) mode = BPP32_8888; else mode = (xi->byte_order == LSBFirst) ? BPP32_LSB : BPP32_MSB; } else qFatal("Logic error 3");#define GET_PIXEL \ uint pixel; \ if (d8) pixel = pix[*src++]; \ else { \ int r = qRed (*p); \ int g = qGreen(*p); \ int b = qBlue (*p++); \ r = red_shift > 0 \ ? r << red_shift : r >> -red_shift; \ g = green_shift > 0 \ ? g << green_shift : g >> -green_shift; \ b = blue_shift > 0 \ ? b << blue_shift : b >> -blue_shift; \ pixel = (r & red_mask)|(g & green_mask) | (b & blue_mask) \ | ~(blue_mask | green_mask | red_mask); \ }#define GET_PIXEL_DITHER_TC \ int r = qRed (*p); \ int g = qGreen(*p); \ int b = qBlue (*p++); \ const int thres = D[x%16][y%16]; \ if (r <= (255-(1<<(8-rbits))) && ((r<<rbits) & 255) \ > thres) \ r += (1<<(8-rbits)); \ if (g <= (255-(1<<(8-gbits))) && ((g<<gbits) & 255) \ > thres) \ g += (1<<(8-gbits)); \ if (b <= (255-(1<<(8-bbits))) && ((b<<bbits) & 255) \ > thres) \ b += (1<<(8-bbits)); \ r = red_shift > 0 \ ? r << red_shift : r >> -red_shift; \ g = green_shift > 0 \ ? g << green_shift : g >> -green_shift; \ b = blue_shift > 0 \ ? b << blue_shift : b >> -blue_shift; \ uint pixel = (r & red_mask)|(g & green_mask) | (b & blue_mask);// again, optimized case// can't be optimized that much :(#define GET_PIXEL_DITHER_TC_OPT(red_shift,green_shift,blue_shift,red_mask,green_mask,blue_mask, \ rbits,gbits,bbits) \ const int thres = D[x%16][y%16]; \ int r = qRed (*p); \ if (r <= (255-(1<<(8-rbits))) && ((r<<rbits) & 255) \ > thres) \ r += (1<<(8-rbits)); \ int g = qGreen(*p); \ if (g <= (255-(1<<(8-gbits))) && ((g<<gbits) & 255) \ > thres) \ g += (1<<(8-gbits)); \ int b = qBlue (*p++); \ if (b <= (255-(1<<(8-bbits))) && ((b<<bbits) & 255) \ > thres) \ b += (1<<(8-bbits)); \ uint pixel = ((r red_shift) & red_mask) \ | ((g green_shift) & green_mask) \ | ((b blue_shift) & blue_mask);#define CYCLE(body) \ for (int y=0; y<h; y++) { \ const uchar* src = cimage.scanLine(y); \ uchar* dst = newbits + xi->bytes_per_line*y; \ const QRgb* p = (const QRgb *)src; \ body \ } if (dither_tc) { switch (mode) { case BPP16_565: CYCLE( quint16* dst16 = (quint16*)dst; for (int x=0; x<w; x++) { GET_PIXEL_DITHER_TC_OPT(<<8,<<3,>>3,0xf800,0x7e0,0x1f,5,6,5) *dst16++ = pixel; } ) break; case BPP16_555: CYCLE( quint16* dst16 = (quint16*)dst; for (int x=0; x<w; x++) { GET_PIXEL_DITHER_TC_OPT(<<7,<<2,>>3,0x7c00,0x3e0,0x1f,5,5,5) *dst16++ = pixel; } ) break; case BPP16_MSB: // 16 bit MSB CYCLE( for (int x=0; x<w; x++) { GET_PIXEL_DITHER_TC *dst++ = (pixel >> 8); *dst++ = pixel; } ) break; case BPP16_LSB: // 16 bit LSB CYCLE( for (int x=0; x<w; x++) { GET_PIXEL_DITHER_TC *dst++ = pixel; *dst++ = pixel >> 8; } ) break; default: qFatal("Logic error"); } } else { switch (mode) { case BPP8: // 8 bit CYCLE( Q_UNUSED(p); for (int x=0; x<w; x++) *dst++ = pix[*src++]; ) break; case BPP16_565: CYCLE( quint16* dst16 = (quint16*)dst; for (int x = 0; x < w; x++) { *dst16++ = ((*p >> 8) & 0xf800) | ((*p >> 5) & 0x7e0) | ((*p >> 3) & 0x1f);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -