summaryrefslogtreecommitdiffstats
path: root/kdeui/kpixmapio.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kdeui/kpixmapio.cpp')
-rw-r--r--kdeui/kpixmapio.cpp908
1 files changed, 908 insertions, 0 deletions
diff --git a/kdeui/kpixmapio.cpp b/kdeui/kpixmapio.cpp
new file mode 100644
index 000000000..fd2854fb0
--- /dev/null
+++ b/kdeui/kpixmapio.cpp
@@ -0,0 +1,908 @@
+/* vi: ts=8 sts=4 sw=4
+ *
+ *
+ * This file is part of the KDE project, module kdeui.
+ * Copyright (C) 2000 Geert Jansen <jansen@kde.org>.
+ *
+ * You can Freely distribute this program under the GNU Library General
+ * Public License. See the file "COPYING.LIB" for the exact licensing terms.
+ *
+ * kpixmapio.cpp: Fast pixmap <-> image conversion.
+ */
+
+#include "kpixmapio.h"
+#include "config.h"
+
+#include <qimage.h>
+#include <qpixmap.h>
+#include <qcolor.h>
+#include <qglobal.h>
+
+#include <kglobal.h>
+#include <kconfig.h>
+#include <kdebug.h>
+
+#include <sys/types.h>
+#ifdef Q_OS_UNIX
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#endif
+
+#ifdef Q_WS_X11
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#ifdef HAVE_MITSHM
+#include <X11/extensions/XShm.h>
+#endif
+#ifdef __osf__
+extern "C" int XShmQueryExtension(Display *display);
+#endif
+#else
+#undef HAVE_MITSHM
+#endif
+
+// d pointer
+
+struct KPixmapIOPrivate
+{
+ int shmsize;
+ int shmpolicy;
+ int threshold;
+ int bpp;
+ int byteorder;
+#ifdef Q_WS_X11
+ XImage *ximage;
+#ifdef HAVE_MITSHM
+ XShmSegmentInfo *shminfo;
+ bool first_try;
+#endif
+#else
+ void *ximage;
+#endif
+};
+
+
+// From Qt: Returns the position of the lowest set bit in val.
+
+typedef unsigned char uchar;
+typedef unsigned int uint;
+
+#ifdef HAVE_MITSHM
+static int lowest_bit(uint val)
+{
+ int i;
+ uint test = 1;
+ for (i=0; (!(val & test)) && i<32; i++, test<<=1);
+ return (i == 32) ? -1 : i;
+}
+#endif
+
+/*** KPixmapIO ***/
+
+KPixmapIO::KPixmapIO()
+{
+ m_bShm = false;
+ d = new KPixmapIOPrivate;
+
+#ifdef HAVE_MITSHM
+ setShmPolicy(ShmDontKeep);
+ KConfig *config = KGlobal::config();
+ if (!config->readBoolEntry("UseMitShm", true))
+ return;
+
+ int ignore;
+ if (XQueryExtension(qt_xdisplay(), "MIT-SHM", &ignore, &ignore, &ignore))
+ {
+ if (XShmQueryExtension(qt_xdisplay()))
+ m_bShm = true;
+ }
+ if (!m_bShm)
+ {
+ kdDebug(290) << k_lineinfo << "MIT-SHM not available!\n";
+ d->ximage = 0;
+ d->shminfo = 0;
+ d->shmsize = 0;
+ return;
+ }
+
+ // Sort out bit format. Create a temporary XImage for this.
+ d->shminfo = new XShmSegmentInfo;
+ d->ximage = XShmCreateImage(qt_xdisplay(), (Visual *) QPaintDevice::x11AppVisual(),
+ QPaintDevice::x11AppDepth(), ZPixmap, 0L, d->shminfo, 10, 10);
+ d->bpp = d->ximage->bits_per_pixel;
+ d->first_try = true;
+ int bpp = d->bpp;
+ if (d->ximage->byte_order == LSBFirst)
+ bpp++;
+ int red_shift = lowest_bit(d->ximage->red_mask);
+ int green_shift = lowest_bit(d->ximage->green_mask);
+ int blue_shift = lowest_bit(d->ximage->blue_mask);
+ XDestroyImage(d->ximage); d->ximage = 0L;
+ d->shmsize = 0;
+
+ // Offer discrete possibilities for the bitformat. Each will have its
+ // own routine. The general algorithm using bitshifts is much too slow;
+ // this has to be done for every pixel!
+
+ if ((bpp == 32) && (red_shift == 16) && (green_shift == 8) &&
+ (blue_shift == 0))
+ d->byteorder = bo32_ARGB;
+ else if ((bpp == 32) && (red_shift == 0) && (green_shift == 8) &&
+ (blue_shift == 16))
+ d->byteorder = bo32_BGRA;
+ else if ((bpp == 33) && (red_shift == 16) && (green_shift == 8) &&
+ (blue_shift == 0))
+ d->byteorder = bo32_BGRA;
+ else if ((bpp == 24) && (red_shift == 16) && (green_shift == 8) &&
+ (blue_shift == 0))
+ d->byteorder = bo24_RGB;
+ else if ((bpp == 24) && (red_shift == 0) && (green_shift == 8) &&
+ (blue_shift == 16))
+ d->byteorder = bo24_BGR;
+ else if ((bpp == 25) && (red_shift == 16) && (green_shift == 8) &&
+ (blue_shift == 0))
+ d->byteorder = bo24_BGR;
+ else if ((bpp == 16) && (red_shift == 11) && (green_shift == 5) &&
+ (blue_shift == 0))
+ d->byteorder = bo16_RGB_565;
+ else if ((bpp == 16) && (red_shift == 10) && (green_shift == 5) &&
+ (blue_shift == 0))
+ d->byteorder = bo16_RGB_555;
+ else if ((bpp == 17) && (red_shift == 11) && (green_shift == 5) &&
+ (blue_shift == 0))
+ d->byteorder = bo16_BGR_565;
+ else if ((bpp == 17) && (red_shift == 10) && (green_shift == 5) &&
+ (blue_shift == 0))
+ d->byteorder = bo16_BGR_555;
+ else if ((bpp == 8) || (bpp == 9))
+ d->byteorder = bo8;
+ else
+ {
+ m_bShm = false;
+ kdWarning(290) << "Byte order not supported!" << endl;
+ kdWarning(290) << "red = " << red_shift
+ << ", green = " << green_shift
+ << ", blue = " << blue_shift << endl;
+ kdWarning(290) << "Please report to <jansen@kde.org>\n";
+ }
+#else
+ d->shmsize = 0;
+ d->ximage = 0;
+#endif
+}
+
+
+KPixmapIO::~KPixmapIO()
+{
+ destroyXImage();
+ destroyShmSegment();
+#ifdef HAVE_MITSHM
+ delete d->shminfo;
+#endif
+ delete d;
+}
+
+
+QPixmap KPixmapIO::convertToPixmap(const QImage &img)
+{
+ int size = img.width() * img.height();
+ if (m_bShm && (img.depth() > 1) && (d->bpp > 8) && (size > d->threshold))
+ {
+ QPixmap dst(img.width(), img.height());
+ putImage(&dst, 0, 0, &img);
+ return dst;
+ } else
+ {
+ QPixmap dst;
+ dst.convertFromImage(img);
+ return dst;
+ }
+
+}
+
+
+QImage KPixmapIO::convertToImage(const QPixmap &pm)
+{
+ QImage image;
+ int size = pm.width() * pm.height();
+ if (m_bShm && (d->bpp >= 8) && (size > d->threshold))
+ image = getImage(&pm, 0, 0, pm.width(), pm.height());
+ else
+ image = pm.convertToImage();
+ return image;
+}
+
+
+void KPixmapIO::putImage(QPixmap *dst, const QPoint &offset,
+ const QImage *src)
+{
+ putImage(dst, offset.x(), offset.y(), src);
+}
+
+
+void KPixmapIO::putImage(QPixmap *dst, int dx, int dy, const QImage *src)
+{
+ int size = src->width() * src->height();
+ bool fallback = true;
+ if (m_bShm && (src->depth() > 1) && (d->bpp > 8) && (size > d->threshold))
+ {
+#ifdef HAVE_MITSHM
+ if( initXImage(src->width(), src->height()))
+ {
+ convertToXImage(*src);
+ XShmPutImage(qt_xdisplay(), dst->handle(), qt_xget_temp_gc(qt_xscreen(), false), d->ximage,
+ dx, dy, 0, 0, src->width(), src->height(), false);
+ // coolo: do we really need this here? I see no good for it
+ XSync(qt_xdisplay(), false);
+ doneXImage();
+ fallback = false;
+ }
+#endif
+ }
+ if( fallback )
+ {
+ QPixmap pix;
+ pix.convertFromImage(*src);
+ bitBlt(dst, dx, dy, &pix, 0, 0, pix.width(), pix.height());
+ }
+}
+
+
+QImage KPixmapIO::getImage(const QPixmap *src, const QRect &rect)
+{
+ return getImage(src, rect.x(), rect.y(), rect.width(), rect.height());
+}
+
+
+QImage KPixmapIO::getImage(const QPixmap *src, int sx, int sy, int sw, int sh)
+{
+ QImage image;
+ int size = src->width() * src->height();
+ bool fallback = true;
+ if ((m_bShm) && (d->bpp >= 8) && (size > d->threshold))
+ {
+#ifdef HAVE_MITSHM
+ if( initXImage(sw, sh))
+ {
+ XShmGetImage(qt_xdisplay(), src->handle(), d->ximage, sx, sy, AllPlanes);
+ image = convertFromXImage();
+ doneXImage();
+ fallback = false;
+ }
+#endif
+ }
+ if( fallback )
+ {
+ QPixmap pix(sw, sh);
+ bitBlt(&pix, 0, 0, src, sx, sy, sw, sh);
+ image = pix.convertToImage();
+ }
+ return image;
+}
+
+
+#ifdef HAVE_MITSHM
+
+void KPixmapIO::preAllocShm(int size)
+{
+ destroyXImage();
+ createShmSegment(size);
+}
+
+
+void KPixmapIO::setShmPolicy(int policy)
+{
+ switch (policy)
+ {
+ case ShmDontKeep:
+ d->shmpolicy = ShmDontKeep;
+ d->threshold = 5000;
+ break;
+ case ShmKeepAndGrow:
+ d->shmpolicy = ShmKeepAndGrow;
+ d->threshold = 2000;
+ break;
+ default:
+ break;
+ }
+}
+
+
+bool KPixmapIO::initXImage(int w, int h)
+{
+ if (d->ximage && (w == d->ximage->width) && (h == d->ximage->height))
+ return true;
+
+ if( !createXImage(w, h))
+ return false;
+ int size = d->ximage->bytes_per_line * d->ximage->height;
+ if (size > d->shmsize)
+ {
+ if( !createShmSegment(size))
+ {
+ destroyXImage();
+ return false;
+ }
+ }
+ d->ximage->data = d->shminfo->shmaddr;
+ return true;
+}
+
+
+void KPixmapIO::doneXImage()
+{
+ if (d->shmpolicy == ShmDontKeep)
+ {
+ destroyXImage();
+ destroyShmSegment();
+ }
+}
+
+
+void KPixmapIO::destroyXImage()
+{
+ if (d->ximage)
+ {
+ XDestroyImage(d->ximage);
+ d->ximage = 0L;
+ }
+}
+
+
+bool KPixmapIO::createXImage(int w, int h)
+{
+ destroyXImage();
+ d->ximage = XShmCreateImage(qt_xdisplay(), (Visual *) QPaintDevice::x11AppVisual(),
+ QPaintDevice::x11AppDepth(), ZPixmap, 0L, d->shminfo, w, h);
+ return d->ximage != None;
+}
+
+
+void KPixmapIO::destroyShmSegment()
+{
+ if (d->shmsize)
+ {
+ XShmDetach(qt_xdisplay(), d->shminfo);
+ shmdt(d->shminfo->shmaddr);
+ shmctl(d->shminfo->shmid, IPC_RMID, 0);
+ d->shmsize = 0;
+ }
+}
+
+static bool use_xshm = true;
+static unsigned long kpixmapio_serial;
+static int (*old_errhandler)(Display *dpy, XErrorEvent *ev) = 0;
+
+static int kpixmapio_errorhandler(Display *dpy, XErrorEvent *ev)
+{
+ if(ev->serial == kpixmapio_serial) {
+ /* assuming that xshm errors mean it can't be used at all
+ (e.g. remote display) */
+ use_xshm = false;
+ kdDebug(290) << "Disabling Xshm" << endl;
+ return 0;
+ } else {
+ // another error
+ return old_errhandler(dpy, ev);
+ }
+}
+
+bool KPixmapIO::createShmSegment(int size)
+{
+ destroyShmSegment();
+ d->shminfo->shmid = shmget(IPC_PRIVATE, size, IPC_CREAT|0600);
+ if ( d->shminfo->shmid < 0)
+ {
+ kdWarning(290) << "Could not get shared memory segment.\n";
+ m_bShm = false;
+ return false;
+ }
+
+ d->shminfo->shmaddr = (char *) shmat(d->shminfo->shmid, 0, 0);
+ if (d->shminfo->shmaddr == (char *)-1)
+ {
+ kdWarning(290) << "Could not attach shared memory segment.\n";
+ m_bShm = false;
+ shmctl(d->shminfo->shmid, IPC_RMID, 0);
+ return false;
+ }
+
+ d->shminfo->readOnly = false;
+
+ if (d->first_try) {
+ // make sure that we don't get errors of old stuff
+ XSync(qt_xdisplay(), False);
+ old_errhandler = XSetErrorHandler(kpixmapio_errorhandler);
+ kpixmapio_serial = NextRequest(qt_xdisplay());
+ }
+
+ if ( !XShmAttach(qt_xdisplay(), d->shminfo))
+ {
+ kdWarning() << "X-Server could not attach shared memory segment.\n";
+ m_bShm = false;
+ shmdt(d->shminfo->shmaddr);
+ shmctl(d->shminfo->shmid, IPC_RMID, 0);
+ }
+
+ if (d->first_try) {
+ XSync(qt_xdisplay(), false);
+
+ if (!use_xshm)
+ m_bShm = false;
+
+ XSetErrorHandler(old_errhandler);
+ d->first_try = false;
+ }
+ d->shmsize = size;
+
+ return m_bShm;
+}
+
+
+/*
+ * The following functions convertToXImage/convertFromXImage are a little
+ * long. This is because of speed, I want to get as much out of the inner
+ * loop as possible.
+ */
+
+QImage KPixmapIO::convertFromXImage()
+{
+ int x, y;
+ int width = d->ximage->width, height = d->ximage->height;
+ int bpl = d->ximage->bytes_per_line;
+ char *data = d->ximage->data;
+
+ QImage image;
+ if (d->bpp == 8)
+ {
+ image.create(width, height, 8);
+
+ // Query color map. Don't remove unused entries as a speed
+ // optmization.
+ int i, ncells = 256;
+ XColor *cmap = new XColor[ncells];
+ for (i=0; i<ncells; i++)
+ cmap[i].pixel = i;
+ XQueryColors(qt_xdisplay(), QPaintDevice::x11AppColormap(),
+ cmap, ncells);
+ image.setNumColors(ncells);
+ for (i=0; i<ncells; i++)
+ image.setColor(i, qRgb(cmap[i].red, cmap[i].green, cmap[i].blue >> 8));
+ } else
+ image.create(width, height, 32);
+
+ switch (d->byteorder)
+ {
+
+ case bo8:
+ {
+ for (y=0; y<height; y++)
+ memcpy(image.scanLine(y), data + y*bpl, width);
+ break;
+ }
+
+ case bo16_RGB_565:
+ case bo16_BGR_565:
+ {
+ Q_INT32 pixel, *src;
+ QRgb *dst, val;
+ for (y=0; y<height; y++)
+ {
+ src = (Q_INT32 *) (data + y*bpl);
+ dst = (QRgb *) image.scanLine(y);
+ for (x=0; x<width/2; x++)
+ {
+ pixel = *src++;
+ val = ((pixel & 0xf800) << 8) | ((pixel & 0x7e0) << 5) |
+ ((pixel & 0x1f) << 3);
+ *dst++ = val;
+ pixel >>= 16;
+ val = ((pixel & 0xf800) << 8) | ((pixel & 0x7e0) << 5) |
+ ((pixel & 0x1f) << 3);
+ *dst++ = val;
+ }
+ if (width%2)
+ {
+ pixel = *src++;
+ val = ((pixel & 0xf800) << 8) | ((pixel & 0x7e0) << 5) |
+ ((pixel & 0x1f) << 3);
+ *dst++ = val;
+ }
+ }
+ break;
+ }
+
+ case bo16_RGB_555:
+ case bo16_BGR_555:
+ {
+ Q_INT32 pixel, *src;
+ QRgb *dst, val;
+ for (y=0; y<height; y++)
+ {
+ src = (Q_INT32 *) (data + y*bpl);
+ dst = (QRgb *) image.scanLine(y);
+ for (x=0; x<width/2; x++)
+ {
+ pixel = *src++;
+ val = ((pixel & 0x7c00) << 9) | ((pixel & 0x3e0) << 6) |
+ ((pixel & 0x1f) << 3);
+ *dst++ = val;
+ pixel >>= 16;
+ val = ((pixel & 0x7c00) << 9) | ((pixel & 0x3e0) << 6) |
+ ((pixel & 0x1f) << 3);
+ *dst++ = val;
+ }
+ if (width%2)
+ {
+ pixel = *src++;
+ val = ((pixel & 0x7c00) << 9) | ((pixel & 0x3e0) << 6) |
+ ((pixel & 0x1f) << 3);
+ *dst++ = val;
+ }
+ }
+ break;
+ }
+
+ case bo24_RGB:
+ {
+ char *src;
+ QRgb *dst;
+ int w1 = width/4;
+ Q_INT32 d1, d2, d3;
+ for (y=0; y<height; y++)
+ {
+ src = data + y*bpl;
+ dst = (QRgb *) image.scanLine(y);
+ for (x=0; x<w1; x++)
+ {
+ d1 = *((Q_INT32 *)src);
+ d2 = *((Q_INT32 *)src + 1);
+ d3 = *((Q_INT32 *)src + 2);
+ src += 12;
+ *dst++ = d1;
+ *dst++ = (d1 >> 24) | (d2 << 8);
+ *dst++ = (d3 << 16) | (d2 >> 16);
+ *dst++ = d3 >> 8;
+ }
+ for (x=w1*4; x<width; x++)
+ {
+ d1 = *src++ << 16;
+ d1 += *src++ << 8;
+ d1 += *src++;
+ *dst++ = d1;
+ }
+ }
+ break;
+ }
+
+ case bo24_BGR:
+ {
+ char *src;
+ QRgb *dst;
+ int w1 = width/4;
+ Q_INT32 d1, d2, d3;
+ for (y=0; y<height; y++)
+ {
+ src = data + y*bpl;
+ dst = (QRgb *) image.scanLine(y);
+ for (x=0; x<w1; x++)
+ {
+ d1 = *((Q_INT32 *)src);
+ d2 = *((Q_INT32 *)src + 1);
+ d3 = *((Q_INT32 *)src + 2);
+ src += 12;
+ *dst++ = d1;
+ *dst++ = (d1 >> 24) | (d2 << 8);
+ *dst++ = (d3 << 16) | (d2 >> 16);
+ *dst++ = d3 >> 8;
+ }
+ for (x=w1*4; x<width; x++)
+ {
+ d1 = *src++;
+ d1 += *src++ << 8;
+ d1 += *src++ << 16;
+ *dst++ = d1;
+ }
+ }
+ break;
+ }
+
+ case bo32_ARGB:
+ case bo32_BGRA:
+ {
+ for (y=0; y<height; y++)
+ memcpy(image.scanLine(y), data + y*bpl, width*4);
+ break;
+ }
+
+ }
+
+ return image;
+}
+
+
+void KPixmapIO::convertToXImage(const QImage &img)
+{
+ int x, y;
+ int width = d->ximage->width, height = d->ximage->height;
+ int bpl = d->ximage->bytes_per_line;
+ char *data = d->ximage->data;
+
+ switch (d->byteorder)
+ {
+
+ case bo16_RGB_555:
+ case bo16_BGR_555:
+
+ if (img.depth() == 32)
+ {
+ QRgb *src, pixel;
+ Q_INT32 *dst, val;
+ for (y=0; y<height; y++)
+ {
+ src = (QRgb *) img.scanLine(y);
+ dst = (Q_INT32 *) (data + y*bpl);
+ for (x=0; x<width/2; x++)
+ {
+ pixel = *src++;
+ val = ((pixel & 0xf80000) >> 9) | ((pixel & 0xf800) >> 6) |
+ ((pixel & 0xff) >> 3);
+ pixel = *src++;
+ val |= (((pixel & 0xf80000) >> 9) | ((pixel & 0xf800) >> 6) |
+ ((pixel & 0xff) >> 3)) << 16;
+ *dst++ = val;
+ }
+ if (width%2)
+ {
+ pixel = *src++;
+ *((Q_INT16 *)dst) = ((pixel & 0xf80000) >> 9) |
+ ((pixel & 0xf800) >> 6) | ((pixel & 0xff) >> 3);
+ }
+ }
+ } else
+ {
+ uchar *src;
+ Q_INT32 val, *dst;
+ QRgb pixel, *clut = img.colorTable();
+ for (y=0; y<height; y++)
+ {
+ src = img.scanLine(y);
+ dst = (Q_INT32 *) (data + y*bpl);
+ for (x=0; x<width/2; x++)
+ {
+ pixel = clut[*src++];
+ val = ((pixel & 0xf80000) >> 9) | ((pixel & 0xf800) >> 6) |
+ ((pixel & 0xff) >> 3);
+ pixel = clut[*src++];
+ val |= (((pixel & 0xf80000) >> 9) | ((pixel & 0xf800) >> 6) |
+ ((pixel & 0xff) >> 3)) << 16;
+ *dst++ = val;
+ }
+ if (width%2)
+ {
+ pixel = clut[*src++];
+ *((Q_INT16 *)dst) = ((pixel & 0xf80000) >> 9) |
+ ((pixel & 0xf800) >> 6) | ((pixel & 0xff) >> 3);
+ }
+ }
+ }
+ break;
+
+ case bo16_RGB_565:
+ case bo16_BGR_565:
+
+ if (img.depth() == 32)
+ {
+ QRgb *src, pixel;
+ Q_INT32 *dst, val;
+ for (y=0; y<height; y++)
+ {
+ src = (QRgb *) img.scanLine(y);
+ dst = (Q_INT32 *) (data + y*bpl);
+ for (x=0; x<width/2; x++)
+ {
+ pixel = *src++;
+ val = ((pixel & 0xf80000) >> 8) | ((pixel & 0xfc00) >> 5) |
+ ((pixel & 0xff) >> 3);
+ pixel = *src++;
+ val |= (((pixel & 0xf80000) >> 8) | ((pixel & 0xfc00) >> 5) |
+ ((pixel & 0xff) >> 3)) << 16;
+ *dst++ = val;
+ }
+ if (width%2)
+ {
+ pixel = *src++;
+ *((Q_INT16 *)dst) = ((pixel & 0xf80000) >> 8) |
+ ((pixel & 0xfc00) >> 5) | ((pixel & 0xff) >> 3);
+ }
+ }
+ } else
+ {
+ uchar *src;
+ Q_INT32 val, *dst;
+ QRgb pixel, *clut = img.colorTable();
+ for (y=0; y<height; y++)
+ {
+ src = img.scanLine(y);
+ dst = (Q_INT32 *) (data + y*bpl);
+ for (x=0; x<width/2; x++)
+ {
+ pixel = clut[*src++];
+ val = ((pixel & 0xf80000) >> 8) | ((pixel & 0xfc00) >> 5) |
+ ((pixel & 0xff) >> 3);
+ pixel = clut[*src++];
+ val |= (((pixel & 0xf80000) >> 8) | ((pixel & 0xfc00) >> 5) |
+ ((pixel & 0xff) >> 3)) << 16;
+ *dst++ = val;
+ }
+ if (width%2)
+ {
+ pixel = clut[*src++];
+ *((Q_INT16 *)dst) = ((pixel & 0xf80000) >> 8) |
+ ((pixel & 0xfc00) >> 5) | ((pixel & 0xff) >> 3);
+ }
+ }
+ }
+ break;
+
+ case bo24_RGB:
+
+ if (img.depth() == 32)
+ {
+ char *dst;
+ int w1 = width/4;
+ QRgb *src, d1, d2, d3, d4;
+ for (y=0; y<height; y++)
+ {
+ src = (QRgb *) img.scanLine(y);
+ dst = data + y*bpl;
+ for (x=0; x<w1; x++)
+ {
+ d1 = (*src++ & 0xffffff);
+ d2 = (*src++ & 0xffffff);
+ d3 = (*src++ & 0xffffff);
+ d4 = (*src++ & 0xffffff);
+ *((Q_INT32 *)dst) = d1 | (d2 << 24);
+ *((Q_INT32 *)dst+1) = (d2 >> 8) | (d3 << 16);
+ *((Q_INT32 *)dst+2) = (d4 << 8) | (d3 >> 16);
+ dst += 12;
+ }
+ for (x=w1*4; x<width; x++)
+ {
+ d1 = *src++;
+ *dst++ = qRed(d1);
+ *dst++ = qGreen(d1);
+ *dst++ = qBlue(d1);
+ }
+ }
+ } else
+ {
+ uchar *src, *dst;
+ int w1 = width/4;
+ QRgb *clut = img.colorTable(), d1, d2, d3, d4;
+ for (y=0; y<height; y++)
+ {
+ src = img.scanLine(y);
+ dst = (uchar *) data + y*bpl;
+ for (x=0; x<w1; x++)
+ {
+ d1 = (clut[*src++] & 0xffffff);
+ d2 = (clut[*src++] & 0xffffff);
+ d3 = (clut[*src++] & 0xffffff);
+ d4 = (clut[*src++] & 0xffffff);
+ *((Q_INT32 *)dst) = d1 | (d2 << 24);
+ *((Q_INT32 *)dst+1) = (d2 >> 8) | (d3 << 16);
+ *((Q_INT32 *)dst+2) = (d4 << 8) | (d3 >> 16);
+ dst += 12;
+ }
+ for (x=w1*4; x<width; x++)
+ {
+ d1 = clut[*src++];
+ *dst++ = qRed(d1);
+ *dst++ = qGreen(d1);
+ *dst++ = qBlue(d1);
+ }
+ }
+ }
+ break;
+
+ case bo24_BGR:
+
+ if (img.depth() == 32)
+ {
+ char *dst;
+ QRgb *src, d1, d2, d3, d4;
+ int w1 = width/4;
+ for (y=0; y<height; y++)
+ {
+ src = (QRgb *) img.scanLine(y);
+ dst = data + y*bpl;
+ for (x=0; x<w1; x++)
+ {
+ d1 = (*src++ & 0xffffff);
+ d2 = (*src++ & 0xffffff);
+ d3 = (*src++ & 0xffffff);
+ d4 = (*src++ & 0xffffff);
+ *((Q_INT32 *)dst) = d1 | (d2 << 24);
+ *((Q_INT32 *)dst+1) = (d2 >> 8) | (d3 << 16);
+ *((Q_INT32 *)dst+2) = (d4 << 8) | (d3 >> 16);
+ dst += 12;
+ }
+ for (x=w1*4; x<width; x++)
+ {
+ d1 = *src++;
+ *dst++ = qBlue(d1);
+ *dst++ = qGreen(d1);
+ *dst++ = qRed(d1);
+ }
+ }
+ } else
+ {
+ uchar *src, *dst;
+ int w1 = width/4;
+ QRgb *clut = img.colorTable(), d1, d2, d3, d4;
+ for (y=0; y<height; y++)
+ {
+ src = img.scanLine(y);
+ dst = (uchar *) data + y*bpl;
+ for (x=0; x<w1; x++)
+ {
+ d1 = (clut[*src++] & 0xffffff);
+ d2 = (clut[*src++] & 0xffffff);
+ d3 = (clut[*src++] & 0xffffff);
+ d4 = (clut[*src++] & 0xffffff);
+ *((Q_INT32 *)dst) = d1 | (d2 << 24);
+ *((Q_INT32 *)dst+1) = (d2 >> 8) | (d3 << 16);
+ *((Q_INT32 *)dst+2) = (d4 << 8) | (d3 >> 16);
+ dst += 12;
+ }
+ for (x=w1*4; x<width; x++)
+ {
+ d1 = clut[*src++];
+ *dst++ = qBlue(d1);
+ *dst++ = qGreen(d1);
+ *dst++ = qRed(d1);
+ }
+ }
+ }
+ break;
+
+ case bo32_ARGB:
+ case bo32_BGRA:
+
+ if (img.depth() == 32)
+ {
+ for (y=0; y<height; y++)
+ memcpy(data + y*bpl, img.scanLine(y), width*4);
+ } else
+ {
+ uchar *src;
+ QRgb *dst, *clut = img.colorTable();
+ for (y=0; y<height; y++)
+ {
+ src = img.scanLine(y);
+ dst = (QRgb *) (data + y*bpl);
+ for (x=0; x<width; x++)
+ *dst++ = clut[*src++];
+ }
+ }
+ break;
+
+ }
+}
+
+#else
+
+void KPixmapIO::preAllocShm(int) {}
+void KPixmapIO::setShmPolicy(int) {}
+bool KPixmapIO::initXImage(int, int) { return false; }
+void KPixmapIO::doneXImage() {}
+bool KPixmapIO::createXImage(int, int) { return false; }
+void KPixmapIO::destroyXImage() {}
+bool KPixmapIO::createShmSegment(int) { return false; }
+void KPixmapIO::destroyShmSegment() {}
+QImage KPixmapIO::convertFromXImage() { return QImage(); }
+void KPixmapIO::convertToXImage(const QImage &) {}
+
+#endif // HAVE_MITSHM