home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / gnu / lucid / xpm-3.2a / scan.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-16  |  14.7 KB  |  568 lines

  1. /* Copyright 1990,91 GROUPE BULL -- See license conditions in file COPYRIGHT */
  2. /*****************************************************************************\
  3. * scan.c:                                                                     *
  4. *                                                                             *
  5. *  XPM library                                                                *
  6. *  Scanning utility for XPM file format                                        *
  7. *                                                                             *
  8. *  Developed by Arnaud Le Hors                                                *
  9. \*****************************************************************************/
  10.  
  11. #include "xpmP.h"
  12.  
  13. #define MAXPRINTABLE 93            /* number of printable ascii chars
  14.                      * minus \ and " for string compat
  15.                      * and / to avoid comment conflicts. */
  16.  
  17. static char *printable =
  18. " .XoO+@#$%&*=-;:?>,<1234567890qwertyuipasdfghjklzxcvbnmMNBVCZ\
  19. ASDFGHJKLPIUYTREWQ!~^/()_`'][{}|";
  20.  
  21.  /*
  22.   * printable begin with a space, so in most case, due to my algorithm, when
  23.   * the number of different colors is less than MAXPRINTABLE, it will give a
  24.   * char follow by "nothing" (a space) in the readable xpm file 
  25.   */
  26.  
  27.  
  28. typedef struct {
  29.     Pixel *pixels;
  30.     unsigned int *pixelindex;
  31.     unsigned int size;
  32.     unsigned int ncolors;
  33.     unsigned int mask_pixel;        /* whether there is or not */
  34. }      PixelsMap;
  35.  
  36. LFUNC(storePixel, int, (Pixel pixel, PixelsMap * pmap,
  37.             unsigned int *index_return));
  38.  
  39. LFUNC(storeMaskPixel, int, (Pixel pixel, PixelsMap * pmap,
  40.                 unsigned int *index_return));
  41.  
  42. LFUNC(GetImagePixels, int, (XImage * image, unsigned int width,
  43.                 unsigned int height, PixelsMap * pmap));
  44.  
  45. LFUNC(GetImagePixels32, int, (XImage * image, unsigned int width,
  46.                   unsigned int height, PixelsMap * pmap));
  47.  
  48. LFUNC(GetImagePixels16, int, (XImage * image, unsigned int width,
  49.                   unsigned int height, PixelsMap * pmap));
  50.  
  51. LFUNC(GetImagePixels8, int, (XImage * image, unsigned int width,
  52.                  unsigned int height, PixelsMap * pmap));
  53.  
  54. LFUNC(GetImagePixels1, int, (XImage * image, unsigned int width,
  55.                  unsigned int height, PixelsMap * pmap,
  56.                  int (*storeFunc) ()));
  57.  
  58. /*
  59.  * This function stores the given pixel in the given arrays which are grown
  60.  * if not large enough.
  61.  */
  62. static int
  63. storePixel(pixel, pmap, index_return)
  64.     Pixel pixel;
  65.     PixelsMap *pmap;
  66.     unsigned int *index_return;
  67. {
  68.     register unsigned int a;
  69.     register Pixel *p;
  70.     register unsigned int ncolors;
  71.  
  72.     if (*index_return) {        /* this is a transparent pixel! */
  73.     *index_return = 0;
  74.     return 0;
  75.     }
  76.     ncolors = pmap->ncolors;
  77.     p = &(pmap->pixels[pmap->mask_pixel]);
  78.     for (a = pmap->mask_pixel; a < ncolors; a++, p++)
  79.     if (*p == pixel)
  80.         break;
  81.     if (a == ncolors) {
  82.     if (ncolors > pmap->size) {
  83.  
  84.         pmap->size *= 2;
  85.         p = (Pixel *) realloc(pmap->pixels, sizeof(Pixel) * pmap->size);
  86.         if (!p)
  87.         return (1);
  88.         pmap->pixels = p;
  89.  
  90.     }
  91.     (pmap->pixels)[ncolors] = pixel;
  92.     pmap->ncolors++;
  93.     }
  94.     *index_return = a;
  95.     return 0;
  96. }
  97.  
  98. static int
  99. storeMaskPixel(pixel, pmap, index_return)
  100.     Pixel pixel;
  101.     PixelsMap *pmap;
  102.     unsigned int *index_return;
  103. {
  104.     if (!pixel) {
  105.     if (!pmap->ncolors) {
  106.         pmap->ncolors = 1;
  107.         (pmap->pixels)[0] = 0;
  108.         pmap->mask_pixel = 1;
  109.     }
  110.     *index_return = 1;
  111.     } else
  112.     *index_return = 0;
  113.     return 0;
  114. }
  115.  
  116. /* function call in case of error, frees only locally allocated variables */
  117. #undef RETURN
  118. #define RETURN(status) \
  119.   { if (pmap.pixelindex) free(pmap.pixelindex); \
  120.     if (pmap.pixels) free(pmap.pixels); \
  121.     if (xcolors) free(xcolors); \
  122.     if (colorStrings) { \
  123.     for (a = 0; a < pmap.ncolors; a++) \
  124.         if (colorStrings[a]) \
  125.         free(colorStrings[a]); \
  126.     free(colorStrings); \
  127.     } \
  128.     return(status); }
  129.  
  130. /*
  131.  * This function scans the given image and stores the found informations in
  132.  * the xpmInternAttrib structure which is returned.
  133.  */
  134. int
  135. xpmScanImage(display, image, shapeimage, attributes, attrib)
  136.     Display *display;
  137.     XImage *image;
  138.     XImage *shapeimage;
  139.     XpmAttributes *attributes;
  140.     xpmInternAttrib *attrib;
  141.  
  142. {
  143.     /* variables stored in the XpmAttributes structure */
  144.     Colormap colormap;
  145.     unsigned int cpp;
  146.  
  147.     /* variables to return */
  148.     PixelsMap pmap;
  149.     char **colorStrings = NULL;
  150.     XColor *xcolors = NULL;
  151.     unsigned int ErrorStatus;
  152.  
  153.     /* calculation variables */
  154.     unsigned int width = 0;
  155.     unsigned int height = 0;
  156.     unsigned int cppm;            /* minimum chars per pixel */
  157.     unsigned int a, b, c;
  158.     register char *s;
  159.  
  160.     /* initialize pmap */
  161.     pmap.pixels = NULL;
  162.     pmap.pixelindex = NULL;
  163.     pmap.size = 256;            /* should be enough most of the time */
  164.     pmap.ncolors = 0;
  165.     pmap.mask_pixel = 0;
  166.  
  167.     /*
  168.      * get geometry 
  169.      */
  170.     if (image) {
  171.     width = image->width;
  172.     height = image->height;
  173.     } else if (shapeimage) {
  174.     width = shapeimage->width;
  175.     height = shapeimage->height;
  176.     }
  177.  
  178.     /*
  179.      * retrieve information from the XpmAttributes 
  180.      */
  181.     if (attributes && attributes->valuemask & XpmColormap)
  182.     colormap = attributes->colormap;
  183.     else
  184.     colormap = DefaultColormap(display, DefaultScreen(display));
  185.  
  186.     if (attributes && (attributes->valuemask & XpmCharsPerPixel
  187.                || attributes->valuemask & XpmInfos))
  188.     cpp = attributes->cpp;
  189.     else
  190.     cpp = 0;
  191.  
  192.     pmap.pixelindex =
  193.     (unsigned int *) calloc(width * height, sizeof(unsigned int));
  194.     if (!pmap.pixelindex)
  195.     RETURN(XpmNoMemory);
  196.  
  197.     pmap.pixels = (Pixel *) malloc(sizeof(Pixel) * pmap.size);
  198.     if (!pmap.pixels)
  199.     RETURN(XpmNoMemory);
  200.  
  201.     /*
  202.      * scan shape mask if any 
  203.      */
  204.     if (shapeimage) {
  205.     ErrorStatus = GetImagePixels1(shapeimage, width, height, &pmap,
  206.                       storeMaskPixel);
  207.     if (ErrorStatus != XpmSuccess)
  208.         RETURN(ErrorStatus);
  209.     }
  210.  
  211.     /*
  212.      * scan the image data 
  213.      *
  214.      * In case depth is 1 or bits_per_pixel is 4, 6, 8, 24 or 32 use optimized
  215.      * functions, otherwise use slower but sure general one. 
  216.      *
  217.      */
  218.  
  219.     if (image) {
  220.     if (image->depth == 1)
  221.         ErrorStatus = GetImagePixels1(image, width, height, &pmap,
  222.                       storePixel);
  223.     else if (image->bits_per_pixel == 8)
  224.         ErrorStatus = GetImagePixels8(image, width, height, &pmap);
  225.     else if (image->bits_per_pixel == 16)
  226.         ErrorStatus = GetImagePixels16(image, width, height, &pmap);
  227.     else if (image->bits_per_pixel == 32)
  228.         ErrorStatus = GetImagePixels32(image, width, height, &pmap);
  229.     else
  230.         ErrorStatus = GetImagePixels(image, width, height, &pmap);
  231.  
  232.     if (ErrorStatus != XpmSuccess)
  233.         RETURN(ErrorStatus);
  234.     }
  235.  
  236.     /*
  237.      * get rgb values and a string of char for each color 
  238.      */
  239.  
  240.     xcolors = (XColor *) malloc(sizeof(XColor) * pmap.ncolors);
  241.     if (!xcolors)
  242.     RETURN(XpmNoMemory);
  243.     colorStrings = (char **) calloc(pmap.ncolors, sizeof(char *));
  244.     if (!colorStrings)
  245.     RETURN(XpmNoMemory);
  246.  
  247.     for (cppm = 1, c = MAXPRINTABLE; pmap.ncolors > c; cppm++)
  248.     c *= MAXPRINTABLE;
  249.     if (cpp < cppm)
  250.     cpp = cppm;
  251.  
  252.     for (a = 0; a < pmap.ncolors; a++) {
  253.     if (!(s = colorStrings[a] = (char *) malloc(cpp)))
  254.         RETURN(XpmNoMemory);
  255.     *s++ = printable[c = a % MAXPRINTABLE];
  256.     for (b = 1; b < cpp; b++, s++)
  257.         *s = printable[c = ((a - c) / MAXPRINTABLE) % MAXPRINTABLE];
  258.     xcolors[a].pixel = pmap.pixels[a];
  259.     }
  260.  
  261.     XQueryColors(display, colormap, xcolors, pmap.ncolors);
  262.  
  263.     /*
  264.      * store found informations in the xpmInternAttrib structure 
  265.      */
  266.     attrib->width = width;
  267.     attrib->height = height;
  268.     attrib->cpp = cpp;
  269.     attrib->ncolors = pmap.ncolors;
  270.     attrib->mask_pixel = pmap.mask_pixel ? 0 : UNDEF_PIXEL;
  271.     attrib->pixelindex = pmap.pixelindex;
  272.     attrib->xcolors = xcolors;
  273.     attrib->colorStrings = colorStrings;
  274.  
  275.     free(pmap.pixels);
  276.     return (XpmSuccess);
  277. }
  278.  
  279.  
  280.  
  281. /*
  282.  * The functions below are written from X11R5 MIT's code (XImUtil.c)
  283.  *
  284.  * The idea is to have faster functions than the standard XGetPixel function
  285.  * to scan the image data. Indeed we can speed up things by suppressing tests
  286.  * performed for each pixel. We do exactly the same tests but at the image
  287.  * level. Assuming that we use only ZPixmap images. 
  288.  */
  289.  
  290. static unsigned long Const low_bits_table[] = {
  291.                 0x00000000, 0x00000001, 0x00000003, 0x00000007,
  292.                 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
  293.                 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
  294.                 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
  295.                 0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
  296.                 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
  297.                 0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
  298.                 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
  299.                            0xffffffff
  300. };
  301.  
  302. /*
  303.  * Default method to scan pixels of a Z image data structure.
  304.  * The algorithm used is:
  305.  *
  306.  *    copy the source bitmap_unit or Zpixel into temp
  307.  *    normalize temp if needed
  308.  *    extract the pixel bits into return value
  309.  *
  310.  */
  311.  
  312. static int
  313. GetImagePixels(image, width, height, pmap)
  314.     XImage *image;
  315.     unsigned int width;
  316.     unsigned int height;
  317.     PixelsMap *pmap;
  318. {
  319.     register char *src;
  320.     register char *dst;
  321.     register unsigned int *iptr;
  322.     register char *data;
  323.     register int x, y, i;
  324.     int bits, depth, ibu, ibpp;
  325.     unsigned long lbt;
  326.     Pixel pixel, px;
  327.  
  328.     data = image->data;
  329.     iptr = pmap->pixelindex;
  330.     depth = image->depth;
  331.     lbt = low_bits_table[depth];
  332.     ibpp = image->bits_per_pixel;
  333.     if (image->depth == 1) {
  334.     ibu = image->bitmap_unit;
  335.     for (y = 0; y < height; y++)
  336.         for (x = 0; x < width; x++, iptr++) {
  337.         src = &data[XYINDEX(x, y, image)];
  338.         dst = (char *) &pixel;
  339.         pixel = 0;
  340.         for (i = ibu >> 3; --i >= 0;)
  341.             *dst++ = *src++;
  342.         XYNORMALIZE(&pixel, image);
  343.         bits = x % ibu;
  344.         pixel = ((((char *) &pixel)[bits >> 3]) >> (bits & 7)) & 1;
  345.         if (ibpp != depth)
  346.             pixel &= lbt;
  347.         if (storePixel(pixel, pmap, iptr))
  348.             return (XpmNoMemory);
  349.         }
  350.     } else {
  351.     for (y = 0; y < height; y++)
  352.         for (x = 0; x < width; x++, iptr++) {
  353.         src = &data[ZINDEX(x, y, image)];
  354.         dst = (char *) &px;
  355.         px = 0;
  356.         for (i = (ibpp + 7) >> 3; --i >= 0;)
  357.             *dst++ = *src++;
  358.         ZNORMALIZE(&px, image);
  359.         pixel = 0;
  360.         for (i = sizeof(unsigned long); --i >= 0;)
  361.             pixel = (pixel << 8) | ((unsigned char *) &px)[i];
  362.         if (ibpp == 4) {
  363.             if (x & 1)
  364.             pixel >>= 4;
  365.             else
  366.             pixel &= 0xf;
  367.         }
  368.         if (ibpp != depth)
  369.             pixel &= lbt;
  370.         if (storePixel(pixel, pmap, iptr))
  371.             return (XpmNoMemory);
  372.         }
  373.     }
  374.     return(XpmSuccess);
  375. }
  376.  
  377. /*
  378.  * scan pixels of a 32-bits Z image data structure
  379.  */
  380.  
  381. #ifndef WORD64
  382. static unsigned long byteorderpixel = MSBFirst << 24;
  383.  
  384. #endif
  385.  
  386. static int
  387. GetImagePixels32(image, width, height, pmap)
  388.     XImage *image;
  389.     unsigned int width;
  390.     unsigned int height;
  391.     PixelsMap *pmap;
  392. {
  393.     register unsigned char *addr;
  394.     register unsigned char *data;
  395.     register unsigned int *iptr;
  396.     register int x, y;
  397.     unsigned long lbt;
  398.     Pixel pixel;
  399.     int depth;
  400.  
  401.     data = (unsigned char *) image->data;
  402.     iptr = pmap->pixelindex;
  403.     depth = image->depth;
  404.     lbt = low_bits_table[depth];
  405. #ifndef WORD64
  406.     if (*((char *) &byteorderpixel) == image->byte_order) {
  407.     for (y = 0; y < height; y++)
  408.         for (x = 0; x < width; x++, iptr++) {
  409.         addr = &data[ZINDEX32(x, y, image)];
  410.         pixel = *((unsigned long *)addr);
  411.         if (depth != 32)
  412.             pixel &= lbt;
  413.         if (storePixel(pixel, pmap, iptr))
  414.             return (XpmNoMemory);
  415.         }
  416.     } else
  417. #endif
  418.     if (image->byte_order == MSBFirst)
  419.     for (y = 0; y < height; y++)
  420.         for (x = 0; x < width; x++, iptr++) {
  421.         addr = &data[ZINDEX32(x, y, image)];
  422.         pixel = ((unsigned long) addr[0] << 24 |
  423.              (unsigned long) addr[1] << 16 |
  424.              (unsigned long) addr[2] << 8 |
  425.              addr[4]);
  426.         if (depth != 32)
  427.             pixel &= lbt;
  428.         if (storePixel(pixel, pmap, iptr))
  429.             return (XpmNoMemory);
  430.         }
  431.     else
  432.     for (y = 0; y < height; y++)
  433.         for (x = 0; x < width; x++, iptr++) {
  434.         addr = &data[ZINDEX32(x, y, image)];
  435.         pixel = (addr[0] |
  436.              (unsigned long) addr[1] << 8 |
  437.              (unsigned long) addr[2] << 16 |
  438.              (unsigned long) addr[3] << 24);
  439.         if (depth != 32)
  440.             pixel &= lbt;
  441.         if (storePixel(pixel, pmap, iptr))
  442.             return (XpmNoMemory);
  443.         }
  444.     return(XpmSuccess);
  445. }
  446.  
  447. /*
  448.  * scan pixels of a 16-bits Z image data structure
  449.  */
  450.  
  451. static int
  452. GetImagePixels16(image, width, height, pmap)
  453.     XImage *image;
  454.     unsigned int width;
  455.     unsigned int height;
  456.     PixelsMap *pmap;
  457. {
  458.     register unsigned char *addr;
  459.     register unsigned char *data;
  460.     register unsigned int *iptr;
  461.     register int x, y;
  462.     unsigned long lbt;
  463.     Pixel pixel;
  464.     int depth;
  465.  
  466.     data = (unsigned char *) image->data;
  467.     iptr = pmap->pixelindex;
  468.     depth = image->depth;
  469.     lbt = low_bits_table[depth];
  470.     if (image->byte_order == MSBFirst)
  471.     for (y = 0; y < height; y++)
  472.         for (x = 0; x < width; x++, iptr++) {
  473.         addr = &data[ZINDEX16(x, y, image)];
  474.         pixel = addr[0] << 8 | addr[1];
  475.         if (depth != 16)
  476.             pixel &= lbt;
  477.         if (storePixel(pixel, pmap, iptr))
  478.             return (XpmNoMemory);
  479.         }
  480.     else
  481.     for (y = 0; y < height; y++)
  482.         for (x = 0; x < width; x++, iptr++) {
  483.         addr = &data[ZINDEX16(x, y, image)];
  484.         pixel = addr[0] | addr[1] << 8;
  485.         if (depth != 16)
  486.             pixel &= lbt;
  487.         if (storePixel(pixel, pmap, iptr))
  488.             return (XpmNoMemory);
  489.         }
  490.     return(XpmSuccess);
  491. }
  492.  
  493. /*
  494.  * scan pixels of a 8-bits Z image data structure
  495.  */
  496.  
  497. static int
  498. GetImagePixels8(image, width, height, pmap)
  499.     XImage *image;
  500.     unsigned int width;
  501.     unsigned int height;
  502.     PixelsMap *pmap;
  503. {
  504.     register unsigned int *iptr;
  505.     register unsigned char *data;
  506.     register int x, y;
  507.     unsigned long lbt;
  508.     Pixel pixel;
  509.     int depth;
  510.  
  511.     data = (unsigned char *) image->data;
  512.     iptr = pmap->pixelindex;
  513.     depth = image->depth;
  514.     lbt = low_bits_table[depth];
  515.     for (y = 0; y < height; y++)
  516.     for (x = 0; x < width; x++, iptr++) {
  517.         pixel = data[ZINDEX8(x, y, image)];
  518.         if (depth != 8)
  519.         pixel &= lbt;
  520.         if (storePixel(pixel, pmap, iptr))
  521.         return (XpmNoMemory);
  522.     }
  523.     return(XpmSuccess);
  524. }
  525.  
  526. /*
  527.  * scan pixels of a 1-bit depth Z image data structure
  528.  */
  529.  
  530. static int
  531. GetImagePixels1(image, width, height, pmap, storeFunc)
  532.     XImage *image;
  533.     unsigned int width;
  534.     unsigned int height;
  535.     PixelsMap *pmap;
  536.     int (*storeFunc) ();
  537.  
  538. {
  539.     register unsigned int *iptr;
  540.     register int x, y;
  541.     register char *data;
  542.     Pixel pixel;
  543.  
  544.     if (image->byte_order != image->bitmap_bit_order)
  545.     return(GetImagePixels(image, width, height, pmap));
  546.     else {
  547.     data = image->data;
  548.     iptr = pmap->pixelindex;
  549.     if (image->bitmap_bit_order == MSBFirst)
  550.         for (y = 0; y < height; y++)
  551.         for (x = 0; x < width; x++, iptr++) {
  552.             pixel = (data[ZINDEX1(x, y, image)] & (0x80 >> (x & 7)))
  553.             ? 1 : 0;
  554.             if ((*storeFunc) (pixel, pmap, iptr))
  555.             return (XpmNoMemory);
  556.         }
  557.     else
  558.         for (y = 0; y < height; y++)
  559.         for (x = 0; x < width; x++, iptr++) {
  560.             pixel = (data[ZINDEX1(x, y, image)] & (1 << (x & 7)))
  561.             ? 1 : 0;
  562.             if ((*storeFunc) (pixel, pmap, iptr))
  563.             return (XpmNoMemory);
  564.         }
  565.     }
  566.     return(XpmSuccess);
  567. }
  568.