kpixmapio.cpp

00001 /* vi: ts=8 sts=4 sw=4
00002  *
00003  *
00004  * This file is part of the KDE project, module kdeui.
00005  * Copyright (C) 2000 Geert Jansen <jansen@kde.org>.
00006  *
00007  * You can Freely distribute this program under the GNU Library General
00008  * Public License. See the file "COPYING.LIB" for the exact licensing terms.
00009  *
00010  * kpixmapio.cpp: Fast pixmap <-> image conversion.
00011  */
00012 
00013 #include "kpixmapio.h"
00014 #include "config.h"
00015 
00016 #include <qimage.h>
00017 #include <qpixmap.h>
00018 #include <qcolor.h>
00019 #include <qglobal.h>
00020 
00021 #include <kglobal.h>
00022 #include <kconfig.h>
00023 #include <kdebug.h>
00024 
00025 #include <sys/types.h>
00026 #ifdef Q_OS_UNIX
00027 #include <sys/ipc.h>
00028 #include <sys/shm.h>
00029 #endif
00030 
00031 #ifdef Q_WS_X11
00032 #include <X11/X.h> 
00033 #include <X11/Xlib.h> 
00034 #include <X11/Xutil.h> 
00035 #ifdef HAVE_MITSHM
00036 #include <X11/extensions/XShm.h> 
00037 #endif
00038 #ifdef __osf__
00039 extern "C" int XShmQueryExtension(Display *display);
00040 #endif
00041 #else
00042 #undef HAVE_MITSHM
00043 #endif
00044 
00045 // d pointer
00046 
00047 struct KPixmapIOPrivate
00048 {
00049     int shmsize;
00050     int shmpolicy;
00051     int threshold;
00052     int bpp;
00053     int byteorder;
00054 #ifdef Q_WS_X11
00055     XImage *ximage;
00056 #ifdef HAVE_MITSHM
00057     XShmSegmentInfo *shminfo;
00058     bool first_try;
00059 #endif
00060 #else
00061     void *ximage;
00062 #endif
00063 };
00064 
00065 
00066 //  From Qt: Returns the position of the lowest set bit in val.
00067 
00068 typedef unsigned char uchar;
00069 typedef unsigned int uint;
00070 
00071 #ifdef HAVE_MITSHM
00072 static int lowest_bit(uint val)
00073 {
00074     int i;
00075     uint test = 1;
00076     for (i=0; (!(val & test)) && i<32; i++, test<<=1);
00077     return (i == 32) ? -1 : i;
00078 }
00079 #endif
00080 
00081 /*** KPixmapIO ***/
00082 
00083 KPixmapIO::KPixmapIO()
00084 {
00085     m_bShm = false;
00086     d = new KPixmapIOPrivate;
00087 
00088 #ifdef HAVE_MITSHM
00089     setShmPolicy(ShmDontKeep);
00090     KConfig *config = KGlobal::config();
00091     if (!config->readBoolEntry("UseMitShm", true))
00092     return;
00093 
00094     int ignore;
00095     if (XQueryExtension(qt_xdisplay(), "MIT-SHM", &ignore, &ignore, &ignore))
00096     {
00097     if (XShmQueryExtension(qt_xdisplay()))
00098         m_bShm = true;
00099     }
00100     if (!m_bShm)
00101     {
00102     kdDebug(290) << k_lineinfo << "MIT-SHM not available!\n";
00103         d->ximage = 0;
00104     d->shminfo = 0;
00105     d->shmsize = 0;
00106     return;
00107     }
00108 
00109     // Sort out bit format. Create a temporary XImage for this.
00110     d->shminfo = new XShmSegmentInfo;
00111     d->ximage = XShmCreateImage(qt_xdisplay(), (Visual *) QPaintDevice::x11AppVisual(),
00112         QPaintDevice::x11AppDepth(), ZPixmap, 0L, d->shminfo, 10, 10);
00113     d->bpp = d->ximage->bits_per_pixel;
00114     d->first_try = true;
00115     int bpp = d->bpp;
00116     if (d->ximage->byte_order == LSBFirst)
00117     bpp++;
00118     int red_shift = lowest_bit(d->ximage->red_mask);
00119     int green_shift = lowest_bit(d->ximage->green_mask);
00120     int blue_shift = lowest_bit(d->ximage->blue_mask);
00121     XDestroyImage(d->ximage); d->ximage = 0L;
00122     d->shmsize = 0;
00123 
00124     // Offer discrete possibilities for the bitformat. Each will have its
00125     // own routine. The general algorithm using bitshifts is much too slow;
00126     // this has to be done for every pixel!
00127 
00128     if ((bpp == 32) && (red_shift == 16) && (green_shift == 8) &&
00129         (blue_shift == 0))
00130     d->byteorder = bo32_ARGB;
00131     else if ((bpp == 33) && (red_shift == 16) && (green_shift == 8) &&
00132         (blue_shift == 0))
00133     d->byteorder = bo32_BGRA;
00134     else if ((bpp == 24) && (red_shift == 16) && (green_shift == 8) &&
00135         (blue_shift == 0))
00136     d->byteorder = bo24_RGB;
00137     else if ((bpp == 25) && (red_shift == 16) && (green_shift == 8) &&
00138         (blue_shift == 0))
00139     d->byteorder = bo24_BGR;
00140     else if ((bpp == 16) && (red_shift == 11) && (green_shift == 5) &&
00141         (blue_shift == 0))
00142     d->byteorder = bo16_RGB_565;
00143     else if ((bpp == 16) && (red_shift == 10) && (green_shift == 5) &&
00144         (blue_shift == 0))
00145     d->byteorder = bo16_RGB_555;
00146     else if ((bpp == 17) && (red_shift == 11) && (green_shift == 5) &&
00147         (blue_shift == 0))
00148     d->byteorder = bo16_BGR_565;
00149     else if ((bpp == 17) && (red_shift == 10) && (green_shift == 5) &&
00150         (blue_shift == 0))
00151     d->byteorder = bo16_BGR_555;
00152     else if ((bpp == 8) || (bpp == 9))
00153     d->byteorder = bo8;
00154     else
00155     {
00156     m_bShm = false;
00157     kdWarning(290) << "Byte order not supported!" << endl;
00158     kdWarning(290) << "red = " << red_shift
00159         << ", green = " << green_shift
00160         << ", blue = " << blue_shift << endl;
00161     kdWarning(290) << "Please report to <jansen@kde.org>\n";
00162     }
00163 #else
00164     d->shmsize = 0;
00165     d->ximage = 0;
00166 #endif
00167 }
00168 
00169 
00170 KPixmapIO::~KPixmapIO()
00171 {
00172     destroyXImage();
00173     destroyShmSegment();
00174 #ifdef HAVE_MITSHM
00175     delete d->shminfo;
00176 #endif
00177     delete d;
00178 }
00179 
00180 
00181 QPixmap KPixmapIO::convertToPixmap(const QImage &img)
00182 {
00183     int size = img.width() * img.height();
00184     if (m_bShm && (img.depth() > 1) && (d->bpp > 8) && (size > d->threshold))
00185     {
00186     QPixmap dst(img.width(), img.height());
00187     putImage(&dst, 0, 0, &img);
00188     return dst;
00189     } else
00190     {
00191     QPixmap dst;
00192     dst.convertFromImage(img);
00193     return dst;
00194     }
00195 
00196 }
00197 
00198 
00199 QImage KPixmapIO::convertToImage(const QPixmap &pm)
00200 {
00201     QImage image;
00202     int size = pm.width() * pm.height();
00203     if (m_bShm && (d->bpp >= 8) && (size > d->threshold))
00204     image = getImage(&pm, 0, 0, pm.width(), pm.height());
00205     else
00206     image = pm.convertToImage();
00207     return image;
00208 }
00209 
00210 
00211 void KPixmapIO::putImage(QPixmap *dst, const QPoint &offset,
00212     const QImage *src)
00213 {
00214     putImage(dst, offset.x(), offset.y(), src);
00215 }
00216 
00217 
00218 void KPixmapIO::putImage(QPixmap *dst, int dx, int dy, const QImage *src)
00219 {
00220     int size = src->width() * src->height();
00221     bool fallback = true;
00222     if (m_bShm && (src->depth() > 1) && (d->bpp > 8) && (size > d->threshold))
00223     {
00224 #ifdef HAVE_MITSHM
00225     if( initXImage(src->width(), src->height()))
00226     {
00227         convertToXImage(*src);
00228         XShmPutImage(qt_xdisplay(), dst->handle(), qt_xget_temp_gc(qt_xscreen(), false), d->ximage,
00229             dx, dy, 0, 0, src->width(), src->height(), false);
00230             // coolo: do we really need this here? I see no good for it
00231         XSync(qt_xdisplay(), false);
00232         doneXImage();
00233         fallback  = false;
00234     }
00235 #endif
00236     }
00237     if( fallback )
00238     {
00239     QPixmap pix;
00240     pix.convertFromImage(*src);
00241     bitBlt(dst, dx, dy, &pix, 0, 0, pix.width(), pix.height());
00242     }
00243 }
00244 
00245 
00246 QImage KPixmapIO::getImage(const QPixmap *src, const QRect &rect)
00247 {
00248     return getImage(src, rect.x(), rect.y(), rect.width(), rect.height());
00249 }
00250 
00251 
00252 QImage KPixmapIO::getImage(const QPixmap *src, int sx, int sy, int sw, int sh)
00253 {
00254     QImage image;
00255     int size = src->width() * src->height();
00256     bool fallback = true;
00257     if ((m_bShm) && (d->bpp >= 8) && (size > d->threshold))
00258     {
00259 #ifdef HAVE_MITSHM
00260     if( initXImage(sw, sh))
00261     {
00262         XShmGetImage(qt_xdisplay(), src->handle(), d->ximage, sx, sy, AllPlanes);
00263         image = convertFromXImage();
00264         doneXImage();
00265         fallback = false;
00266     }
00267 #endif
00268     }
00269     if( fallback )
00270     {
00271     QPixmap pix(sw, sh);
00272     bitBlt(&pix, 0, 0, src, sx, sy, sw, sh);
00273     image = pix.convertToImage();
00274     }
00275     return image;
00276 }
00277 
00278 
00279 #ifdef HAVE_MITSHM
00280 
00281 void KPixmapIO::preAllocShm(int size)
00282 {
00283     destroyXImage();
00284     createShmSegment(size);
00285 }
00286 
00287 
00288 void KPixmapIO::setShmPolicy(int policy)
00289 {
00290     switch (policy)
00291     {
00292     case ShmDontKeep:
00293     d->shmpolicy = ShmDontKeep;
00294     d->threshold = 5000;
00295     break;
00296     case ShmKeepAndGrow:
00297     d->shmpolicy = ShmKeepAndGrow;
00298     d->threshold = 2000;
00299     break;
00300     default:
00301     break;
00302     }
00303 }
00304 
00305 
00306 bool KPixmapIO::initXImage(int w, int h)
00307 {
00308     if (d->ximage && (w == d->ximage->width) && (h == d->ximage->height))
00309     return true;
00310 
00311     if( !createXImage(w, h))
00312     return false;
00313     int size = d->ximage->bytes_per_line * d->ximage->height;
00314     if (size > d->shmsize)
00315     {
00316     if( !createShmSegment(size))
00317     {
00318         destroyXImage();
00319         return false;
00320     }
00321     }
00322     d->ximage->data = d->shminfo->shmaddr;
00323     return true;
00324 }
00325 
00326 
00327 void KPixmapIO::doneXImage()
00328 {
00329     if (d->shmpolicy == ShmDontKeep)
00330     {
00331     destroyXImage();
00332     destroyShmSegment();
00333     }
00334 }
00335 
00336 
00337 void KPixmapIO::destroyXImage()
00338 {
00339     if (d->ximage)
00340     {
00341     XDestroyImage(d->ximage);
00342     d->ximage = 0L;
00343     }
00344 }
00345 
00346 
00347 bool KPixmapIO::createXImage(int w, int h)
00348 {
00349     destroyXImage();
00350     d->ximage = XShmCreateImage(qt_xdisplay(), (Visual *) QPaintDevice::x11AppVisual(),
00351         QPaintDevice::x11AppDepth(), ZPixmap, 0L, d->shminfo, w, h);
00352     return d->ximage != None;
00353 }
00354 
00355 
00356 void KPixmapIO::destroyShmSegment()
00357 {
00358     if (d->shmsize)
00359     {
00360     XShmDetach(qt_xdisplay(), d->shminfo);
00361     shmdt(d->shminfo->shmaddr);
00362         shmctl(d->shminfo->shmid, IPC_RMID, 0);
00363     d->shmsize = 0;
00364     }
00365 }
00366 
00367 static bool use_xshm = true;
00368 static unsigned long kpixmapio_serial;
00369 static int (*old_errhandler)(Display *dpy, XErrorEvent *ev) = 0;
00370 
00371 static int kpixmapio_errorhandler(Display *dpy, XErrorEvent *ev)
00372 {
00373     if(ev->serial == kpixmapio_serial) {
00374         /* assuming that xshm errors mean it can't be used at all
00375            (e.g. remote display) */
00376         use_xshm = false;
00377         kdDebug(290) << "Disabling Xshm" << endl;
00378         return 0;
00379     } else {
00380         // another error
00381         return old_errhandler(dpy, ev);
00382     }
00383 }
00384 
00385 bool KPixmapIO::createShmSegment(int size)
00386 {
00387     destroyShmSegment();
00388     d->shminfo->shmid = shmget(IPC_PRIVATE, size, IPC_CREAT|0600);
00389     if ( d->shminfo->shmid < 0)
00390     {
00391     kdWarning(290) << "Could not get shared memory segment.\n";
00392     m_bShm = false;
00393     return false;
00394     }
00395 
00396     d->shminfo->shmaddr = (char *) shmat(d->shminfo->shmid, 0, 0);
00397     if (d->shminfo->shmaddr == (char *)-1)
00398     {
00399     kdWarning(290) << "Could not attach shared memory segment.\n";
00400     m_bShm = false;
00401     shmctl(d->shminfo->shmid, IPC_RMID, 0);
00402     return false;
00403     }
00404 
00405     d->shminfo->readOnly = false;
00406 
00407     if (d->first_try) {
00408         // make sure that we don't get errors of old stuff
00409         XSync(qt_xdisplay(), False);
00410         old_errhandler = XSetErrorHandler(kpixmapio_errorhandler);
00411         kpixmapio_serial = NextRequest(qt_xdisplay());
00412     }
00413 
00414     if ( !XShmAttach(qt_xdisplay(), d->shminfo))
00415     {
00416     kdWarning() << "X-Server could not attach shared memory segment.\n";
00417     m_bShm = false;
00418     shmdt(d->shminfo->shmaddr);
00419     shmctl(d->shminfo->shmid, IPC_RMID, 0);
00420     }
00421 
00422     if (d->first_try) {
00423         XSync(qt_xdisplay(), false);
00424 
00425         if (!use_xshm)
00426             m_bShm = false;
00427 
00428         XSetErrorHandler(old_errhandler);
00429         d->first_try = false;
00430     }
00431     d->shmsize = size;
00432 
00433     return m_bShm;
00434 }
00435 
00436 
00437 /*
00438  * The following functions convertToXImage/convertFromXImage are a little
00439  * long. This is because of speed, I want to get as much out of the inner
00440  * loop as possible.
00441  */
00442 
00443 QImage KPixmapIO::convertFromXImage()
00444 {
00445     int x, y;
00446     int width = d->ximage->width, height = d->ximage->height;
00447     int bpl = d->ximage->bytes_per_line;
00448     char *data = d->ximage->data;
00449 
00450     QImage image;
00451     if (d->bpp == 8)
00452     {
00453     image.create(width, height, 8);
00454 
00455     // Query color map. Don't remove unused entries as a speed
00456     // optmization.
00457     int i, ncells = 256;
00458     XColor *cmap = new XColor[ncells];
00459     for (i=0; i<ncells; i++)
00460         cmap[i].pixel = i;
00461     XQueryColors(qt_xdisplay(), QPaintDevice::x11AppColormap(),
00462         cmap, ncells);
00463     image.setNumColors(ncells);
00464     for (i=0; i<ncells; i++)
00465         image.setColor(i, qRgb(cmap[i].red, cmap[i].green, cmap[i].blue >> 8));
00466     } else
00467     image.create(width, height, 32);
00468 
00469     switch (d->byteorder)
00470     {
00471 
00472     case bo8:
00473     {
00474     for (y=0; y<height; y++)
00475         memcpy(image.scanLine(y), data + y*bpl, width);
00476     break;
00477     }
00478 
00479     case bo16_RGB_565:
00480     case bo16_BGR_565:
00481     {
00482     Q_INT32 pixel, *src;
00483     QRgb *dst, val;
00484     for (y=0; y<height; y++)
00485     {
00486         src = (Q_INT32 *) (data + y*bpl);
00487         dst = (QRgb *) image.scanLine(y);
00488         for (x=0; x<width/2; x++)
00489         {
00490         pixel = *src++;
00491         val = ((pixel & 0xf800) << 8) | ((pixel & 0x7e0) << 5) |
00492             ((pixel & 0x1f) << 3);
00493         *dst++ = val;
00494         pixel >>= 16;
00495         val = ((pixel & 0xf800) << 8) | ((pixel & 0x7e0) << 5) |
00496             ((pixel & 0x1f) << 3);
00497         *dst++ = val;
00498         }
00499         if (width%2)
00500         {
00501         pixel = *src++;
00502         val = ((pixel & 0xf800) << 8) | ((pixel & 0x7e0) << 5) |
00503             ((pixel & 0x1f) << 3);
00504         *dst++ = val;
00505         }
00506     }
00507     break;
00508     }
00509 
00510     case bo16_RGB_555:
00511     case bo16_BGR_555:
00512     {
00513     Q_INT32 pixel, *src;
00514     QRgb *dst, val;
00515     for (y=0; y<height; y++)
00516     {
00517         src = (Q_INT32 *) (data + y*bpl);
00518         dst = (QRgb *) image.scanLine(y);
00519         for (x=0; x<width/2; x++)
00520         {
00521         pixel = *src++;
00522         val = ((pixel & 0x7c00) << 9) | ((pixel & 0x3e0) << 6) |
00523             ((pixel & 0x1f) << 3);
00524         *dst++ = val;
00525         pixel >>= 16;
00526         val = ((pixel & 0x7c00) << 9) | ((pixel & 0x3e0) << 6) |
00527             ((pixel & 0x1f) << 3);
00528         *dst++ = val;
00529         }
00530         if (width%2)
00531         {
00532         pixel = *src++;
00533         val = ((pixel & 0x7c00) << 9) | ((pixel & 0x3e0) << 6) |
00534             ((pixel & 0x1f) << 3);
00535         *dst++ = val;
00536         }
00537     }
00538     break;
00539     }
00540 
00541     case bo24_RGB:
00542     {
00543     char *src;
00544     QRgb *dst;
00545     int w1 = width/4;
00546     Q_INT32 d1, d2, d3;
00547     for (y=0; y<height; y++)
00548     {
00549         src = data + y*bpl;
00550         dst = (QRgb *) image.scanLine(y);
00551         for (x=0; x<w1; x++)
00552         {
00553         d1 = *((Q_INT32 *)src);
00554         d2 = *((Q_INT32 *)src + 1);
00555         d3 = *((Q_INT32 *)src + 2);
00556         src += 12;
00557         *dst++ = d1;
00558         *dst++ = (d1 >> 24) | (d2 << 8);
00559         *dst++ = (d3 << 16) | (d2 >> 16);
00560         *dst++ = d3 >> 8;
00561         }
00562         for (x=w1*4; x<width; x++)
00563         {
00564         d1 = *src++ << 16;
00565         d1 += *src++ << 8;
00566         d1 += *src++;
00567         *dst++ = d1;
00568         }
00569     }
00570     break;
00571     }
00572 
00573     case bo24_BGR:
00574     {
00575     char *src;
00576     QRgb *dst;
00577     int w1 = width/4;
00578     Q_INT32 d1, d2, d3;
00579     for (y=0; y<height; y++)
00580     {
00581         src = data + y*bpl;
00582         dst = (QRgb *) image.scanLine(y);
00583         for (x=0; x<w1; x++)
00584         {
00585         d1 = *((Q_INT32 *)src);
00586         d2 = *((Q_INT32 *)src + 1);
00587         d3 = *((Q_INT32 *)src + 2);
00588         src += 12;
00589         *dst++ = d1;
00590         *dst++ = (d1 >> 24) | (d2 << 8);
00591         *dst++ = (d3 << 16) | (d2 >> 16);
00592         *dst++ = d3 >> 8;
00593         }
00594         for (x=w1*4; x<width; x++)
00595         {
00596         d1 = *src++;
00597         d1 += *src++ << 8;
00598         d1 += *src++ << 16;
00599         *dst++ = d1;
00600         }
00601     }
00602     break;
00603     }
00604 
00605     case bo32_ARGB:
00606     case bo32_BGRA:
00607     {
00608     for (y=0; y<height; y++)
00609         memcpy(image.scanLine(y), data + y*bpl, width*4);
00610     break;
00611     }
00612 
00613     }
00614 
00615     return image;
00616 }
00617 
00618 
00619 void KPixmapIO::convertToXImage(const QImage &img)
00620 {
00621     int x, y;
00622     int width = d->ximage->width, height = d->ximage->height;
00623     int bpl = d->ximage->bytes_per_line;
00624     char *data = d->ximage->data;
00625 
00626     switch (d->byteorder)
00627     {
00628 
00629     case bo16_RGB_555:
00630     case bo16_BGR_555:
00631 
00632     if (img.depth() == 32)
00633     {
00634         QRgb *src, pixel;
00635         Q_INT32 *dst, val;
00636         for (y=0; y<height; y++)
00637         {
00638         src = (QRgb *) img.scanLine(y);
00639         dst = (Q_INT32 *) (data + y*bpl);
00640         for (x=0; x<width/2; x++)
00641         {
00642             pixel = *src++;
00643             val = ((pixel & 0xf80000) >> 9) | ((pixel & 0xf800) >> 6) |
00644                  ((pixel & 0xff) >> 3);
00645             pixel = *src++;
00646             val |= (((pixel & 0xf80000) >> 9) | ((pixel & 0xf800) >> 6) |
00647                 ((pixel & 0xff) >> 3)) << 16;
00648             *dst++ = val;
00649         }
00650         if (width%2)
00651         {
00652             pixel = *src++;
00653             *((Q_INT16 *)dst) = ((pixel & 0xf80000) >> 9) |
00654                 ((pixel & 0xf800) >> 6) | ((pixel & 0xff) >> 3);
00655         }
00656         }
00657     } else
00658     {
00659         uchar *src;
00660         Q_INT32 val, *dst;
00661         QRgb pixel, *clut = img.colorTable();
00662         for (y=0; y<height; y++)
00663         {
00664         src = img.scanLine(y);
00665         dst = (Q_INT32 *) (data + y*bpl);
00666         for (x=0; x<width/2; x++)
00667         {
00668             pixel = clut[*src++];
00669             val = ((pixel & 0xf80000) >> 9) | ((pixel & 0xf800) >> 6) |
00670                 ((pixel & 0xff) >> 3);
00671             pixel = clut[*src++];
00672             val |= (((pixel & 0xf80000) >> 9) | ((pixel & 0xf800) >> 6) |
00673                 ((pixel & 0xff) >> 3)) << 16;
00674             *dst++ = val;
00675         }
00676         if (width%2)
00677         {
00678             pixel = clut[*src++];
00679             *((Q_INT16 *)dst) = ((pixel & 0xf80000) >> 9) |
00680                 ((pixel & 0xf800) >> 6) | ((pixel & 0xff) >> 3);
00681         }
00682         }
00683     }
00684     break;
00685 
00686     case bo16_RGB_565:
00687     case bo16_BGR_565:
00688 
00689     if (img.depth() == 32)
00690     {
00691         QRgb *src, pixel;
00692         Q_INT32 *dst, val;
00693         for (y=0; y<height; y++)
00694         {
00695         src = (QRgb *) img.scanLine(y);
00696         dst = (Q_INT32 *) (data + y*bpl);
00697         for (x=0; x<width/2; x++)
00698         {
00699             pixel = *src++;
00700             val = ((pixel & 0xf80000) >> 8) | ((pixel & 0xfc00) >> 5) |
00701                  ((pixel & 0xff) >> 3);
00702             pixel = *src++;
00703             val |= (((pixel & 0xf80000) >> 8) | ((pixel & 0xfc00) >> 5) |
00704                 ((pixel & 0xff) >> 3)) << 16;
00705             *dst++ = val;
00706         }
00707         if (width%2)
00708         {
00709             pixel = *src++;
00710             *((Q_INT16 *)dst) = ((pixel & 0xf80000) >> 8) |
00711                 ((pixel & 0xfc00) >> 5) | ((pixel & 0xff) >> 3);
00712         }
00713         }
00714     } else
00715     {
00716         uchar *src;
00717         Q_INT32 val, *dst;
00718         QRgb pixel, *clut = img.colorTable();
00719         for (y=0; y<height; y++)
00720         {
00721         src = img.scanLine(y);
00722         dst = (Q_INT32 *) (data + y*bpl);
00723         for (x=0; x<width/2; x++)
00724         {
00725             pixel = clut[*src++];
00726             val = ((pixel & 0xf80000) >> 8) | ((pixel & 0xfc00) >> 5) |
00727                 ((pixel & 0xff) >> 3);
00728             pixel = clut[*src++];
00729             val |= (((pixel & 0xf80000) >> 8) | ((pixel & 0xfc00) >> 5) |
00730                 ((pixel & 0xff) >> 3)) << 16;
00731             *dst++ = val;
00732         }
00733         if (width%2)
00734         {
00735             pixel = clut[*src++];
00736             *((Q_INT16 *)dst) = ((pixel & 0xf80000) >> 8) |
00737                 ((pixel & 0xfc00) >> 5) | ((pixel & 0xff) >> 3);
00738         }
00739         }
00740     }
00741     break;
00742 
00743     case bo24_RGB:
00744 
00745     if (img.depth() == 32)
00746     {
00747         char *dst;
00748         int w1 = width/4;
00749         QRgb *src, d1, d2, d3, d4;
00750         for (y=0; y<height; y++)
00751         {
00752         src = (QRgb *) img.scanLine(y);
00753         dst = data + y*bpl;
00754         for (x=0; x<w1; x++)
00755         {
00756             d1 = (*src++ & 0xffffff);
00757             d2 = (*src++ & 0xffffff);
00758             d3 = (*src++ & 0xffffff);
00759             d4 = (*src++ & 0xffffff);
00760             *((Q_INT32 *)dst) = d1 | (d2 << 24);
00761             *((Q_INT32 *)dst+1) = (d2 >> 8) | (d3 << 16);
00762             *((Q_INT32 *)dst+2) = (d4 << 8) | (d3 >> 16);
00763             dst += 12;
00764         }
00765         for (x=w1*4; x<width; x++)
00766         {
00767             d1 = *src++;
00768             *dst++ = qRed(d1);
00769             *dst++ = qGreen(d1);
00770             *dst++ = qBlue(d1);
00771         }
00772         }
00773     } else
00774     {
00775         uchar *src, *dst;
00776         int w1 = width/4;
00777         QRgb *clut = img.colorTable(), d1, d2, d3, d4;
00778         for (y=0; y<height; y++)
00779         {
00780         src = img.scanLine(y);
00781         dst = (uchar *) data + y*bpl;
00782         for (x=0; x<w1; x++)
00783         {
00784             d1 = (clut[*src++] & 0xffffff);
00785             d2 = (clut[*src++] & 0xffffff);
00786             d3 = (clut[*src++] & 0xffffff);
00787             d4 = (clut[*src++] & 0xffffff);
00788             *((Q_INT32 *)dst) = d1 | (d2 << 24);
00789             *((Q_INT32 *)dst+1) = (d2 >> 8) | (d3 << 16);
00790             *((Q_INT32 *)dst+2) = (d4 << 8) | (d3 >> 16);
00791             dst += 12;
00792         }
00793         for (x=w1*4; x<width; x++)
00794         {
00795             d1 = clut[*src++];
00796             *dst++ = qRed(d1);
00797             *dst++ = qGreen(d1);
00798             *dst++ = qBlue(d1);
00799         }
00800         }
00801     }
00802     break;
00803 
00804     case bo24_BGR:
00805 
00806     if (img.depth() == 32)
00807     {
00808         char *dst;
00809         QRgb *src, d1, d2, d3, d4;
00810         int w1 = width/4;
00811         for (y=0; y<height; y++)
00812         {
00813         src = (QRgb *) img.scanLine(y);
00814         dst = data + y*bpl;
00815         for (x=0; x<w1; x++)
00816         {
00817             d1 = (*src++ & 0xffffff);
00818             d2 = (*src++ & 0xffffff);
00819             d3 = (*src++ & 0xffffff);
00820             d4 = (*src++ & 0xffffff);
00821             *((Q_INT32 *)dst) = d1 | (d2 << 24);
00822             *((Q_INT32 *)dst+1) = (d2 >> 8) | (d3 << 16);
00823             *((Q_INT32 *)dst+2) = (d4 << 8) | (d3 >> 16);
00824             dst += 12;
00825         }
00826         for (x=w1*4; x<width; x++)
00827         {
00828             d1 = *src++;
00829             *dst++ = qBlue(d1);
00830             *dst++ = qGreen(d1);
00831             *dst++ = qRed(d1);
00832         }
00833         }
00834     } else
00835     {
00836         uchar *src, *dst;
00837         int w1 = width/4;
00838         QRgb *clut = img.colorTable(), d1, d2, d3, d4;
00839         for (y=0; y<height; y++)
00840         {
00841         src = img.scanLine(y);
00842         dst = (uchar *) data + y*bpl;
00843         for (x=0; x<w1; x++)
00844         {
00845             d1 = (clut[*src++] & 0xffffff);
00846             d2 = (clut[*src++] & 0xffffff);
00847             d3 = (clut[*src++] & 0xffffff);
00848             d4 = (clut[*src++] & 0xffffff);
00849             *((Q_INT32 *)dst) = d1 | (d2 << 24);
00850             *((Q_INT32 *)dst+1) = (d2 >> 8) | (d3 << 16);
00851             *((Q_INT32 *)dst+2) = (d4 << 8) | (d3 >> 16);
00852             dst += 12;
00853         }
00854         for (x=w1*4; x<width; x++)
00855         {
00856             d1 = clut[*src++];
00857             *dst++ = qBlue(d1);
00858             *dst++ = qGreen(d1);
00859             *dst++ = qRed(d1);
00860         }
00861         }
00862     }
00863     break;
00864 
00865     case bo32_ARGB:
00866     case bo32_BGRA:
00867 
00868     if (img.depth() == 32)
00869     {
00870         for (y=0; y<height; y++)
00871         memcpy(data + y*bpl, img.scanLine(y), width*4);
00872     } else
00873     {
00874         uchar *src;
00875         QRgb *dst, *clut = img.colorTable();
00876         for (y=0; y<height; y++)
00877         {
00878         src = img.scanLine(y);
00879         dst = (QRgb *) (data + y*bpl);
00880         for (x=0; x<width; x++)
00881             *dst++ = clut[*src++];
00882         }
00883     }
00884     break;
00885 
00886     }
00887 }
00888 
00889 #else
00890 
00891 void KPixmapIO::preAllocShm(int) {}
00892 void KPixmapIO::setShmPolicy(int) {}
00893 bool KPixmapIO::initXImage(int, int) { return false; }
00894 void KPixmapIO::doneXImage() {}
00895 bool KPixmapIO::createXImage(int, int) { return false; }
00896 void KPixmapIO::destroyXImage() {}
00897 bool KPixmapIO::createShmSegment(int) { return false; }
00898 void KPixmapIO::destroyShmSegment() {}
00899 QImage KPixmapIO::convertFromXImage() { return QImage(); }
00900 void KPixmapIO::convertToXImage(const QImage &) {}
00901 
00902 #endif // HAVE_MITSHM
KDE Home | KDE Accessibility Home | Description of Access Keys