📄 qpixmap_x11.cpp
字号:
*dst++ = pixel >> 16; *dst++ = pixel >> 24; } ) break; default: qFatal("Logic error 2"); } } xi->data = (char *)newbits; } if (d == 8 && !trucol) { // 8 bit pixmap int pop[256]; // pixel popularity if (image.numColors() == 0) image.setNumColors(1); const QImage &cimage = image; memset(pop, 0, sizeof(int)*256); // reset popularity array for (int i = 0; i < h; i++) { // for each scanline... const uchar* p = cimage.scanLine(i); const uchar *end = p + w; while (p < end) // compute popularity pop[*p++]++; } newbits = (uchar *)malloc(nbytes); // copy image into newbits Q_CHECK_PTR(newbits); if (!newbits) // no memory return QPixmap(); uchar* p = newbits; memcpy(p, cimage.bits(), nbytes); // copy image data into newbits /* * The code below picks the most important colors. It is based on the * diversity algorithm, implemented in XV 3.10. XV is (C) by John Bradley. */ struct PIX { // pixel sort element uchar r,g,b,n; // color + pad int use; // popularity int index; // index in colormap int mindist; }; int ncols = 0; for (int i=0; i< cimage.numColors(); i++) { // compute number of colors if (pop[i] > 0) ncols++; } for (int i = cimage.numColors(); i < 256; i++) // ignore out-of-range pixels pop[i] = 0; // works since we make sure above to have at least // one color in the image if (ncols == 0) ncols = 1; PIX pixarr[256]; // pixel array PIX pixarr_sorted[256]; // pixel array (sorted) memset(pixarr, 0, ncols*sizeof(PIX)); PIX *px = &pixarr[0]; int maxpop = 0; int maxpix = 0; uint j = 0; QVector<QRgb> ctable = cimage.colorTable(); for (int i = 0; i < 256; i++) { // init pixel array if (pop[i] > 0) { px->r = qRed (ctable[i]); px->g = qGreen(ctable[i]); px->b = qBlue (ctable[i]); px->n = 0; px->use = pop[i]; if (pop[i] > maxpop) { // select most popular entry maxpop = pop[i]; maxpix = j; } px->index = i; px->mindist = 1000000; px++; j++; } } pixarr_sorted[0] = pixarr[maxpix]; pixarr[maxpix].use = 0; for (int i = 1; i < ncols; i++) { // sort pixels int minpix = -1, mindist = -1; px = &pixarr_sorted[i-1]; int r = px->r; int g = px->g; int b = px->b; int dist; if ((i & 1) || i<10) { // sort on max distance for (int j=0; j<ncols; j++) { px = &pixarr[j]; if (px->use) { dist = (px->r - r)*(px->r - r) + (px->g - g)*(px->g - g) + (px->b - b)*(px->b - b); if (px->mindist > dist) px->mindist = dist; if (px->mindist > mindist) { mindist = px->mindist; minpix = j; } } } } else { // sort on max popularity for (int j=0; j<ncols; j++) { px = &pixarr[j]; if (px->use) { dist = (px->r - r)*(px->r - r) + (px->g - g)*(px->g - g) + (px->b - b)*(px->b - b); if (px->mindist > dist) px->mindist = dist; if (px->use > mindist) { mindist = px->use; minpix = j; } } } } pixarr_sorted[i] = pixarr[minpix]; pixarr[minpix].use = 0; } QColormap cmap = QColormap::instance(pixmap.data->xinfo.screen()); uint pix[256]; // pixel translation table px = &pixarr_sorted[0]; for (int i = 0; i < ncols; i++) { // allocate colors QColor c(px->r, px->g, px->b); pix[px->index] = cmap.pixel(c); px++; } p = newbits; for (int i = 0; i < nbytes; i++) { // translate pixels *p = pix[*p]; p++; } } if (!xi) { // X image not created xi = XCreateImage(dpy, visual, dd, ZPixmap, 0, 0, w, h, 32, 0); if (xi->bits_per_pixel == 16) { // convert 8 bpp ==> 16 bpp ushort *p2; int p2inc = xi->bytes_per_line/sizeof(ushort); ushort *newerbits = (ushort *)malloc(xi->bytes_per_line * h); Q_CHECK_PTR(newerbits); if (!newerbits) // no memory return QPixmap(); uchar* p = newbits; for (int y = 0; y < h; y++) { // OOPS: Do right byte order!! p2 = newerbits + p2inc*y; for (int x = 0; x < w; x++) *p2++ = *p++; } free(newbits); newbits = (uchar *)newerbits; } else if (xi->bits_per_pixel != 8) { qWarning("QPixmap::convertFromImage: Display not supported " "(bpp=%d)", xi->bits_per_pixel); } xi->data = (char *)newbits; } pixmap.data->hd = (Qt::HANDLE)XCreatePixmap(X11->display, RootWindow(X11->display, pixmap.data->xinfo.screen()), w, h, dd); 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); pixmap.data->w = w; pixmap.data->h = h; pixmap.data->d = dd;#ifndef QT_NO_XRENDER if (X11->use_xrender) { XRenderPictFormat *format = pixmap.data->d == 1 ? XRenderFindStandardFormat(X11->display, PictStandardA1) : XRenderFindVisualFormat(X11->display, (Visual *) pixmap.data->xinfo.visual()); pixmap.data->picture = XRenderCreatePicture(X11->display, pixmap.data->hd, format, 0, 0); }#endif if (image.hasAlphaChannel()) { QBitmap m = QBitmap::fromImage(image.createAlphaMask(flags)); pixmap.setMask(m); } return pixmap;}/*! \fn QPixmap QPixmap::grabWindow(WId window, int x, int y, int width, int height) Creates and returns a pixmap constructed by grabbing the contents of the given \a window restricted by QRect(\a x, \a y, \a width, \a height). The arguments (\a{x}, \a{y}) specify the offset in the window, whereas (\a{width}, \a{height}) specify the area to be copied. If \a width is negative, the function copies everything to the right border of the window. If \a height is negative, the function copies everything to the bottom of the window. The window system identifier (\c WId) can be retrieved using the QWidget::WId() function. The rationale for using a window identifier and not a QWidget, is to enable grabbing of windows that are not part of the application, window system frames, and so on. The grabWindow() function grabs pixels from the screen, not from the window, i.e. if there is another window partially or entirely over the one you grab, you get pixels from the overlying window, too. The mouse cursor is generally not grabbed. Note on X11that if the given \a window doesn't have the same depth as the root window, and another window partially or entirely obscures the one you grab, you will \e not get pixels from the overlying window. The contents of the obscured areas in the pixmap will be undefined and uninitialized. \warning In general, grabbing an area outside the screen is not safe. This depends on the underlying window system. \sa grabWidget()*/QPixmap QPixmap::grabWindow(WId window, int x, int y, int w, int h){ if (w == 0 || h == 0) return QPixmap(); Display *dpy = X11->display; XWindowAttributes window_attr; if (! XGetWindowAttributes(dpy, window, &window_attr)) return QPixmap(); if (w < 0) w = window_attr.width - x; if (h < 0) h = window_attr.height - y; // determine the screen int scr; for (scr = 0; scr < ScreenCount(dpy); ++scr) { if (window_attr.root == RootWindow(dpy, scr)) // found it break; } if (scr >= ScreenCount(dpy)) // sanity check return QPixmap(); // get the depth of the root window XWindowAttributes root_attr; if (! XGetWindowAttributes(dpy, window_attr.root, &root_attr)) return QPixmap(); if (window_attr.depth == root_attr.depth) { // if the depth of the specified window and the root window are the // same, grab pixels from the root window (so that we get the any // overlapping windows and window manager frames) // map x and y to the root window WId unused; if (! XTranslateCoordinates(dpy, window, window_attr.root, x, y, &x, &y, &unused)) return QPixmap(); window = window_attr.root; window_attr = root_attr; } QPixmap pm(w, h); pm.data->uninit = false; pm.x11SetScreen(scr);#ifndef QT_NO_XRENDER if (pm.data->picture) { XRenderPictFormat *format = XRenderFindVisualFormat(dpy, window_attr.visual); XRenderPictureAttributes pattr; pattr.subwindow_mode = IncludeInferiors; Picture src_pict = XRenderCreatePicture(dpy, window, format, CPSubwindowMode, &pattr); Picture dst_pict = pm.x11PictureHandle(); XRenderComposite(dpy, PictOpSrc, src_pict, 0, dst_pict, x, y, x, y, 0, 0, w, h); XRenderFreePicture(dpy, src_pict); } else#endif { GC gc = XCreateGC(dpy, pm.handle(), 0, 0); XSetSubwindowMode(dpy, gc, IncludeInferiors); XCopyArea(dpy, window, pm.handle(), gc, x, y, w, h, 0, 0); XFreeGC(dpy, gc); } return pm;}/*! Returns a copy of the pixmap that is transformed using the given transformation \a matrix and transformation \a mode. The original pixmap is not changed. The transformation \a matrix is internally adjusted to compensate for unwanted translation; i.e. the pixmap produced is the smallest pixmap that contains all the transformed points of the original pixmap. Use the trueMatrix() function to retrieve the actual matrix used for transforming the pixmap. This function is slow because it involves transformation to a QImage, non-trivial computations and a transformation back to a QPixmap. \sa trueMatrix(), {QPixmap#Pixmap Transformations}{Pixmap Transformations}*/QPixmap QPixmap::transformed(const QMatrix &matrix, Qt::TransformationMode mode) const{ int w = 0; int h = 0; // size of target pixmap int ws, hs; // size of source pixmap uchar *dptr; // data in target pixmap int dbpl, dbytes; // bytes per line/bytes total uchar *sptr; // data in original pixmap int sbpl; // bytes per line in original int bpp; // bits per pixel bool depth1 = depth() == 1; Display *dpy = X11->display; if (isNull()) // this is a null pixmap return copy(); ws = width(); hs = height(); QMatrix mat(matrix.m11(), matrix.m12(), matrix.m21(), matrix.m22(), 0., 0.); bool complex_xform = false; if (mat.m12() == 0.0F && mat.m21() == 0.0F) { if (mat.m11() == 1.0F && mat.m22() == 1.0F) // identity matrix return *this; h = int(qAbs(mat.m22()) * hs + 0.9999); w = int(qAbs(mat.m11()) * ws + 0.9999); h = qAbs(h); w = qAbs(w); } else { // rotation or shearing QPolygonF a(QRectF(0, 0, ws+1, hs+1)); a = mat.map(a); QRectF r = a.boundingRect().normalized(); w = int(r.width() + 0.9999); h = int(r.height() + 0.9999); complex_xform = true; } mat = trueMatrix(mat, ws, hs); // true matrix bool invertible; mat = mat.inverted(&invertibl
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -