Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

Palm2QImage.cpp

Go to the documentation of this file.
00001 /* -*- mode: c; indent-tabs-mode: nil; -*- */
00002 
00003 #include <stdio.h>
00004 #include <stdlib.h>
00005 #include <string.h>
00006 #ifndef _WINDOWS
00007 #include <unistd.h>     /* for link */
00008 #endif
00009 #include <sys/types.h>
00010 #include <sys/stat.h>
00011 #include <stdarg.h>
00012 
00013 #include <qimage.h>
00014 
00015 /***********************************************************************/
00016 /***********************************************************************/
00017 /*****                                                             *****/
00018 /*****   Code to decode the Palm image format to JPEG              *****/
00019 /*****                                                             *****/
00020 /***********************************************************************/
00021 /***********************************************************************/
00022 
00023 #define READ_BIGENDIAN_SHORT(p) (((p)[0] << 8)|((p)[1]))
00024 #define READ_BIGENDIAN_LONG(p)  (((p)[0] << 24)|((p)[1] << 16)|((p)[2] << 8)|((p)[3]))
00025 
00026 #define PALM_IS_COMPRESSED_FLAG        0x8000
00027 #define PALM_HAS_COLORMAP_FLAG        0x4000
00028 #define PALM_HAS_TRANSPARENCY_FLAG    0x2000
00029 #define PALM_DIRECT_COLOR_FLAG        0x0400
00030 #define PALM_4_BYTE_FIELD_FLAG        0x0200
00031 
00032 #define PALM_COMPRESSION_SCANLINE    0x00
00033 #define PALM_COMPRESSION_RLE        0x01
00034 #define PALM_COMPRESSION_PACKBITS    0x02
00035 #define PALM_COMPRESSION_NONE        0xFF
00036 
00037 #define PALM_COLORMAP_SIZE 232
00038 
00039 typedef struct {
00040   unsigned char red;
00041   unsigned char green;
00042   unsigned char blue;
00043 } ColorMapEntry;
00044 
00045 static ColorMapEntry Palm8BitColormap[] = {
00046   { 255, 255, 255 }, { 255, 204, 255 }, { 255, 153, 255 }, { 255, 102, 255 }, 
00047   { 255,  51, 255 }, { 255,   0, 255 }, { 255, 255, 204 }, { 255, 204, 204 }, 
00048   { 255, 153, 204 }, { 255, 102, 204 }, { 255,  51, 204 }, { 255,   0, 204 }, 
00049   { 255, 255, 153 }, { 255, 204, 153 }, { 255, 153, 153 }, { 255, 102, 153 }, 
00050   { 255,  51, 153 }, { 255,   0, 153 }, { 204, 255, 255 }, { 204, 204, 255 },
00051   { 204, 153, 255 }, { 204, 102, 255 }, { 204,  51, 255 }, { 204,   0, 255 },
00052   { 204, 255, 204 }, { 204, 204, 204 }, { 204, 153, 204 }, { 204, 102, 204 },
00053   { 204,  51, 204 }, { 204,   0, 204 }, { 204, 255, 153 }, { 204, 204, 153 },
00054   { 204, 153, 153 }, { 204, 102, 153 }, { 204,  51, 153 }, { 204,   0, 153 },
00055   { 153, 255, 255 }, { 153, 204, 255 }, { 153, 153, 255 }, { 153, 102, 255 },
00056   { 153,  51, 255 }, { 153,   0, 255 }, { 153, 255, 204 }, { 153, 204, 204 },
00057   { 153, 153, 204 }, { 153, 102, 204 }, { 153,  51, 204 }, { 153,   0, 204 },
00058   { 153, 255, 153 }, { 153, 204, 153 }, { 153, 153, 153 }, { 153, 102, 153 },
00059   { 153,  51, 153 }, { 153,   0, 153 }, { 102, 255, 255 }, { 102, 204, 255 },
00060   { 102, 153, 255 }, { 102, 102, 255 }, { 102,  51, 255 }, { 102,   0, 255 },
00061   { 102, 255, 204 }, { 102, 204, 204 }, { 102, 153, 204 }, { 102, 102, 204 },
00062   { 102,  51, 204 }, { 102,   0, 204 }, { 102, 255, 153 }, { 102, 204, 153 },
00063   { 102, 153, 153 }, { 102, 102, 153 }, { 102,  51, 153 }, { 102,   0, 153 },
00064   {  51, 255, 255 }, {  51, 204, 255 }, {  51, 153, 255 }, {  51, 102, 255 },
00065   {  51,  51, 255 }, {  51,   0, 255 }, {  51, 255, 204 }, {  51, 204, 204 },
00066   {  51, 153, 204 }, {  51, 102, 204 }, {  51,  51, 204 }, {  51,   0, 204 },
00067   {  51, 255, 153 }, {  51, 204, 153 }, {  51, 153, 153 }, {  51, 102, 153 },
00068   {  51,  51, 153 }, {  51,   0, 153 }, {   0, 255, 255 }, {   0, 204, 255 },
00069   {   0, 153, 255 }, {   0, 102, 255 }, {   0,  51, 255 }, {   0,   0, 255 },
00070   {   0, 255, 204 }, {   0, 204, 204 }, {   0, 153, 204 }, {   0, 102, 204 },
00071   {   0,  51, 204 }, {   0,   0, 204 }, {   0, 255, 153 }, {   0, 204, 153 },
00072   {   0, 153, 153 }, {   0, 102, 153 }, {   0,  51, 153 }, {   0,   0, 153 },
00073   { 255, 255, 102 }, { 255, 204, 102 }, { 255, 153, 102 }, { 255, 102, 102 },
00074   { 255,  51, 102 }, { 255,   0, 102 }, { 255, 255,  51 }, { 255, 204,  51 },
00075   { 255, 153,  51 }, { 255, 102,  51 }, { 255,  51,  51 }, { 255,   0,  51 },
00076   { 255, 255,   0 }, { 255, 204,   0 }, { 255, 153,   0 }, { 255, 102,   0 },
00077   { 255,  51,   0 }, { 255,   0,   0 }, { 204, 255, 102 }, { 204, 204, 102 },
00078   { 204, 153, 102 }, { 204, 102, 102 }, { 204,  51, 102 }, { 204,   0, 102 },
00079   { 204, 255,  51 }, { 204, 204,  51 }, { 204, 153,  51 }, { 204, 102,  51 },
00080   { 204,  51,  51 }, { 204,   0,  51 }, { 204, 255,   0 }, { 204, 204,   0 },
00081   { 204, 153,   0 }, { 204, 102,   0 }, { 204,  51,   0 }, { 204,   0,   0 },
00082   { 153, 255, 102 }, { 153, 204, 102 }, { 153, 153, 102 }, { 153, 102, 102 },
00083   { 153,  51, 102 }, { 153,   0, 102 }, { 153, 255,  51 }, { 153, 204,  51 },
00084   { 153, 153,  51 }, { 153, 102,  51 }, { 153,  51,  51 }, { 153,   0,  51 },
00085   { 153, 255,   0 }, { 153, 204,   0 }, { 153, 153,   0 }, { 153, 102,   0 },
00086   { 153,  51,   0 }, { 153,   0,   0 }, { 102, 255, 102 }, { 102, 204, 102 },
00087   { 102, 153, 102 }, { 102, 102, 102 }, { 102,  51, 102 }, { 102,   0, 102 },
00088   { 102, 255,  51 }, { 102, 204,  51 }, { 102, 153,  51 }, { 102, 102,  51 },
00089   { 102,  51,  51 }, { 102,   0,  51 }, { 102, 255,   0 }, { 102, 204,   0 },
00090   { 102, 153,   0 }, { 102, 102,   0 }, { 102,  51,   0 }, { 102,   0,   0 },
00091   {  51, 255, 102 }, {  51, 204, 102 }, {  51, 153, 102 }, {  51, 102, 102 },
00092   {  51,  51, 102 }, {  51,   0, 102 }, {  51, 255,  51 }, {  51, 204,  51 },
00093   {  51, 153,  51 }, {  51, 102,  51 }, {  51,  51,  51 }, {  51,   0,  51 },
00094   {  51, 255,   0 }, {  51, 204,   0 }, {  51, 153,   0 }, {  51, 102,   0 },
00095   {  51,  51,   0 }, {  51,   0,   0 }, {   0, 255, 102 }, {   0, 204, 102 },
00096   {   0, 153, 102 }, {   0, 102, 102 }, {   0,  51, 102 }, {   0,   0, 102 },
00097   {   0, 255,  51 }, {   0, 204,  51 }, {   0, 153,  51 }, {   0, 102,  51 },
00098   {   0,  51,  51 }, {   0,   0,  51 }, {   0, 255,   0 }, {   0, 204,   0 },
00099   {   0, 153,   0 }, {   0, 102,   0 }, {   0,  51,   0 }, {  17,  17,  17 },
00100   {  34,  34,  34 }, {  68,  68,  68 }, {  85,  85,  85 }, { 119, 119, 119 },
00101   { 136, 136, 136 }, { 170, 170, 170 }, { 187, 187, 187 }, { 221, 221, 221 },
00102   { 238, 238, 238 }, { 192, 192, 192 }, { 128,   0,   0 }, { 128,   0, 128 },
00103   {   0, 128,   0 }, {   0, 128, 128 }, {   0,   0,   0 }, {   0,   0,   0 },
00104   {   0,   0,   0 }, {   0,   0,   0 }, {   0,   0,   0 }, {   0,   0,   0 },
00105   {   0,   0,   0 }, {   0,   0,   0 }, {   0,   0,   0 }, {   0,   0,   0 },
00106   {   0,   0,   0 }, {   0,   0,   0 }, {   0,   0,   0 }, {   0,   0,   0 },
00107   {   0,   0,   0 }, {   0,   0,   0 }, {   0,   0,   0 }, {   0,   0,   0 },
00108   {   0,   0,   0 }, {   0,   0,   0 }, {   0,   0,   0 }, {   0,   0,   0 },
00109   {   0,   0,   0 }, {   0,   0,   0 }, {   0,   0,   0 }, {   0,   0,   0 }};
00110 
00111 static ColorMapEntry Palm1BitColormap[] = {{ 255, 255, 255 }, { 0, 0, 0 }};
00112 
00113 static ColorMapEntry Palm2BitColormap[] = {
00114   { 255, 255, 255 }, { 192, 192, 192 }, { 128, 128, 128 }, { 0, 0, 0 }};
00115 
00116 static ColorMapEntry Palm4BitColormap[] = {
00117   { 255, 255, 255 }, { 238, 238, 238 }, { 221, 221, 221 }, { 204, 204, 204 },
00118   { 187, 187, 187 }, { 170, 170, 170 }, { 153, 153, 153 }, { 136, 136, 136 },
00119   { 119, 119, 119 }, { 102, 102, 102 }, {  85,  85,  85 }, {  68,  68,  68 },
00120   {  51,  51,  51 }, {  34,  34,  34 }, {  17,  17,  17 }, {   0,   0,   0 }};
00121 
00122 QImage* Palm2QImage
00123   (unsigned char *image_bytes_in, int byte_count_in)
00124 {
00125   unsigned int width, height, bytes_per_row, flags, next_depth_offset;
00126   unsigned int bits_per_pixel, version, transparent_index, compression_type, i, j, inval, inbit, mask, incount;
00127   unsigned int palm_red_bits, palm_green_bits, palm_blue_bits;
00128   unsigned char *palm_ptr, *x_ptr, *imagedata, *inbyte, *rowbuf, *lastrow,
00129   *imagedatastart, *palmimage;
00130   ColorMapEntry *colormap;
00131 
00132   palmimage = image_bytes_in;
00133   width = READ_BIGENDIAN_SHORT(palmimage + 0);
00134   height = READ_BIGENDIAN_SHORT(palmimage + 2);
00135   bytes_per_row = READ_BIGENDIAN_SHORT(palmimage + 4);
00136   flags = READ_BIGENDIAN_SHORT(palmimage + 6);
00137   bits_per_pixel = palmimage[8];
00138   version = palmimage[9];
00139   next_depth_offset = READ_BIGENDIAN_SHORT(palmimage + 10);
00140   transparent_index = palmimage[12];
00141   compression_type = palmimage[13];
00142   /* bytes 14 and 15 are reserved by Palm and always 0 */
00143   
00144 #if 0
00145 //  qDebug ("Palm image is %dx%d, %d bpp, version %d, flags 0x%x, compression %d", width, height, bits_per_pixel, version, flags, compression_type);
00146 #endif
00147 
00148   if (compression_type == PALM_COMPRESSION_PACKBITS) {
00149 //    qDebug ("Image uses packbits compression; not yet supported");
00150     return NULL;
00151   } else if ((compression_type != PALM_COMPRESSION_NONE) &&
00152     (compression_type != PALM_COMPRESSION_RLE) &&
00153       (compression_type != PALM_COMPRESSION_SCANLINE)) {
00154 //    qDebug ("Image uses unknown compression, code 0x%x", compression_type);
00155     return NULL;
00156   }
00157 
00158   /* as of PalmOS 4.0, there are 6 different kinds of Palm pixmaps:
00159      
00160      1, 2, or 4 bit grayscale
00161      8-bit StaticColor using the Palm standard colormap
00162      8-bit PseudoColor using a user-specified colormap
00163      16-bit DirectColor using 5 bits for red, 6 for green, and 5 for blue
00164      
00165      Each of these can be compressed with one of four compression schemes,
00166      "RLE", "Scanline", "PackBits", or none.
00167      
00168      We begin by constructing the colormap.
00169      */
00170 
00171   if (flags & PALM_HAS_COLORMAP_FLAG) {
00172 //    qDebug("Palm images with custom colormaps are not currently supported.\n");
00173     return NULL;
00174   } else if (bits_per_pixel == 1) {
00175     colormap = Palm1BitColormap;
00176     imagedatastart = palmimage + 16;
00177   } else if (bits_per_pixel == 2) {
00178     colormap = Palm2BitColormap;
00179     imagedatastart = palmimage + 16;
00180   } else if (bits_per_pixel == 4) {
00181     colormap = Palm4BitColormap;
00182     imagedatastart = palmimage + 16;
00183   } else if (bits_per_pixel == 8) {
00184     colormap = Palm8BitColormap;
00185     imagedatastart = palmimage + 16;
00186   } else if (bits_per_pixel == 16 && (flags & PALM_DIRECT_COLOR_FLAG)) {
00187     colormap = NULL;
00188     palm_red_bits = palmimage[16];
00189     palm_green_bits = palmimage[17];
00190     palm_blue_bits = palmimage[18];
00191 //    qDebug("Bits:%d, %d, %d", palm_red_bits, palm_green_bits, palm_blue_bits);
00192     if (palm_blue_bits > 8 || palm_green_bits > 8 || palm_red_bits > 8) {
00193 //      qDebug("Can't handle this format DirectColor image -- too wide in some color (%d:%d:%d)\n", palm_red_bits, palm_green_bits, palm_blue_bits);
00194       return NULL;
00195     }
00196     if (bits_per_pixel > (8 * sizeof(unsigned long))) {
00197 //      qDebug ("Can't handle this format DirectColor image -- too many bits per pixel (%d)\n", bits_per_pixel);
00198       return NULL;
00199     }
00200     imagedatastart = palmimage + 24;
00201   } else {
00202 //    qDebug("Unknown bits-per-pixel of %d encountered.\n", bits_per_pixel);
00203     return NULL;
00204   }
00205 
00206 #ifndef USEQPE
00207   QImage* qimage = new QImage(width, height, 32);
00208 #else
00209       QImage* qimage = new QImage(width, height, 16);
00210 #endif
00211 
00212   /* row by row, uncompress the Palm image and copy it to the JPEG buffer */
00213   rowbuf = new unsigned char[bytes_per_row * width];
00214   lastrow = new unsigned char[bytes_per_row * width];
00215 
00216   for (i=0, palm_ptr = imagedatastart , x_ptr = imagedata;  i < height;  ++i) {
00217 //        qDebug("inval:%x palm_ptr:%x x_ptr:%x bpr:%x", inval, palm_ptr, x_ptr, bytes_per_row);
00218 
00219     /* first, uncompress the Palm image */
00220     if ((flags & PALM_IS_COMPRESSED_FLAG) && (compression_type == PALM_COMPRESSION_RLE)) {
00221       for (j = 0;  j < bytes_per_row;  ) {
00222         incount = *palm_ptr++;
00223         inval = *palm_ptr++;
00224         memset(rowbuf + j, inval, incount);
00225         j += incount;
00226       }
00227     } else if ((flags & PALM_IS_COMPRESSED_FLAG) && (compression_type == PALM_COMPRESSION_SCANLINE)) {
00228       for (j = 0;  j < bytes_per_row;  j += 8) {
00229         incount = *palm_ptr++;
00230         inval = ((bytes_per_row - j) < 8) ? (bytes_per_row - j) : 8;
00231         for (inbit = 0;  inbit < inval;  inbit += 1) {
00232           if (incount & (1 << (7 - inbit)))
00233             rowbuf[j + inbit] = *palm_ptr++;
00234           else
00235             rowbuf[j + inbit] = lastrow[j + inbit];
00236         }
00237       }
00238       memcpy (lastrow, rowbuf, bytes_per_row);
00239     } else if (((flags & PALM_IS_COMPRESSED_FLAG) &&
00240                 (compression_type == PALM_COMPRESSION_NONE)) ||
00241                ((flags & PALM_IS_COMPRESSED_FLAG) == 0))
00242     {
00243         memcpy (rowbuf, palm_ptr, bytes_per_row);
00244         palm_ptr += bytes_per_row;
00245     }
00246     else {
00247         qDebug("Case 4");
00248         qDebug("Is compressed:%s", ((flags & PALM_IS_COMPRESSED_FLAG) == 0) ? "false" : "true");
00249         qDebug("Has colourmap:%s", ((flags & PALM_HAS_COLORMAP_FLAG) == 0) ? "false" : "true");
00250         qDebug("Has transparency:%s", ((flags & PALM_HAS_TRANSPARENCY_FLAG) == 0) ? "false" : "true");
00251         qDebug("Direct colour:%s", ((flags & PALM_DIRECT_COLOR_FLAG) == 0) ? "false" : "true");
00252         qDebug("four byte field:%s", ((flags & PALM_4_BYTE_FIELD_FLAG) == 0) ? "false" : "true");
00253       memcpy (rowbuf, palm_ptr, bytes_per_row);
00254       palm_ptr += bytes_per_row;
00255     }
00256     /* next, write it to the GDK bitmap */
00257     if (colormap) {
00258       mask = (1 << bits_per_pixel) - 1;
00259       for (inbit = 8 - bits_per_pixel, inbyte = rowbuf, j = 0; j < width; ++j) {
00260         inval = ((*inbyte) & (mask << inbit)) >> inbit;
00261         /* correct for oddity of the 8-bit color Palm pixmap... */
00262         if ((bits_per_pixel == 8) && (inval == 0xFF)) inval = 231;
00263         /* now lookup the correct color and set the pixel in the GTK bitmap */
00264         QRgb colour = qRgb(colormap[inval].red, colormap[inval].green, colormap[inval].blue);
00265         qimage->setPixel(j, i, colour);
00266         if (!inbit) {
00267           ++inbyte;
00268           inbit = 8 - bits_per_pixel;
00269         } else {
00270           inbit -= bits_per_pixel;
00271         }
00272       }
00273     } else if (!colormap &&
00274       bits_per_pixel == 16) {
00275       for (inbyte = rowbuf, j = 0; j < width; ++j) {
00276         inval = ((unsigned short)inbyte[0] << (unsigned short)8) | inbyte[1];
00277 
00278 /*
00279         qDebug ("pixel is %d,%d (%d:%d:%d)",
00280                       j, i,
00281                       ((inval >> (bits_per_pixel - palm_red_bits)) & ((1 << palm_red_bits) - 1)) << (8-palm_red_bits),
00282                       ((inval >> palm_blue_bits) & ((1 << palm_green_bits) - 1)) << (8-palm_green_bits),
00283                       ((inval >> 0) & ((1 << palm_blue_bits) - 1)) << (8-palm_blue_bits));
00284 */
00285         QRgb colour = qRgb(
00286             ((inval >> (bits_per_pixel - palm_red_bits)) & ((1 << palm_red_bits) - 1)) << (8-palm_red_bits), 
00287             ((inval >> palm_blue_bits) & ((1 << palm_green_bits) - 1)) << (8-palm_green_bits),
00288             ((inval >> 0) & ((1 << palm_blue_bits) - 1)) << (8-palm_blue_bits));
00289         qimage->setPixel(j, i, colour);
00290         inbyte += 2;
00291       }
00292     }
00293   }
00294 
00295   delete [] rowbuf;
00296   delete [] lastrow;
00297 
00298   return qimage;
00299 }

Generated on Sat Nov 5 16:16:56 2005 for OPIE by  doxygen 1.4.2