Esempio n. 1
0
/*
 * Depending on if the image is stored as 1bpp, 4bpp or 8bpp, the 
 * encoding mechanism is different.
 * 
 * I didn't re-use the code from ppmtobmp since I need to keep the
 * bitmaps in memory till I've loaded all ppms.
 * 
 * 8bpp => 1 byte/palette index.
 * 4bpp => High Nibble, Low Nibble
 * 1bpp => 1 palette value per bit, high bit 1st.
 */
static ICON_bmp 
create1Bitmap (pixel ** const pa, int const cols, int const rows, 
               colorhash_table const cht) {
   /*
    * How wide should the u1 string for each row be?
    * each byte is 8 pixels, but must be a multiple of 4 bytes.
    */
   ICON_bmp icBitmap;
   int xBytes,y,x;
   int wt = cols;
   u1 ** rowData;

   MALLOCVAR_NOFAIL(icBitmap);
   
   wt >>= 3;
   if (wt & 3) {
      wt = (wt & ~3) + 4;
   }
   xBytes = wt;
   MALLOCARRAY_NOFAIL(rowData, rows);
   icBitmap->xBytes = xBytes;
   icBitmap->data   = rowData;
   icBitmap->size   = xBytes * rows;
   for (y=0;y<rows;y++) {
      u1 * row;
      int byteOn = 0;
      int bitOn = 128;
      int value;
      
      MALLOCARRAY_NOFAIL(row, xBytes);
      memset (row, 0, xBytes);
      rowData[rows-y-1] = row;
      /* 
       * Check there's a pixel array, otherwise we're just faking this...
       */
      if (pa) {
     for (x=0;x<cols;x++) {
        /*
         * So we've got a colorhash_table with two colors in it.
         * Which is black?!
         * 
         * Unless the hashing function changes, 0's black.
         */
        value = ppm_lookupcolor(cht, &pa[y][x]);
        if (!value) {
           /* leave black. */
        } else {
           row[byteOn] |= bitOn;
        }
        if (bitOn == 1) {
           byteOn++;
           bitOn = 128;
        } else {
           bitOn >>= 1;
        }
     }
      }
   }
   return icBitmap;
}
Esempio n. 2
0
static void
processColorfileEntry(struct colorfile_entry const ce,
                      colorhash_table        const cht,
                      const char **          const colornames,
                      pixel *                const colors,
                      unsigned int *         const colornameIndexP) {

    if (*colornameIndexP >= MAXCOLORNAMES)
        pm_error("Too many colors in colorname dictionary.  "
                 "Max allowed is %u", MAXCOLORNAMES);
    else {
        pixel color;

        PPM_ASSIGN(color, ce.r, ce.g, ce.b);

        if (ppm_lookupcolor(cht, &color) >= 0) {
            /* The color is already in the hash, which means we saw it
               earlier in the file.  We prefer the first name that the
               file gives for each color, so we just ignore the
               current entry.  
            */
        } else {
            ppm_addtocolorhash(cht, &color, *colornameIndexP);
            colornames[*colornameIndexP] = strdup(ce.colorname);
            colors[*colornameIndexP] = color;
            if (colornames[*colornameIndexP] == NULL)
                pm_error("Unable to allocate space for color name");
            ++(*colornameIndexP);
        }
    }
}
Esempio n. 3
0
static void
writeXpmFile(FILE *          const outfile, 
             pixel **        const pixels, 
             gray **         const alpha, 
             pixval          const alphamaxval,
             char            const name[], 
             int             const cols, 
             int             const rows, 
             unsigned int    const cmapSize,
             unsigned int    const charsPerPixel, 
             cixel_map       const cmap[],
             colorhash_table const cht,
             unsigned int    const transIndex) {
/*----------------------------------------------------------------------------
   Write the whole XPM file to the open stream 'outfile'.

   'cmap' is the colormap to be placed in the XPM.  'cmapSize' is the
   number of entries in it.  'cht' is a hash table that gives you an 
   index into 'cmap' given a color.  'transIndex' is the index into cmap
   of the transparent color, and is valid only if 'alpha' is non-null
   (otherwise, cmap might not contain a transparent color).
-----------------------------------------------------------------------------*/
    /* First the header */
    printf("/* XPM */\n");
    fprintf(outfile, "static char *%s[] = {\n", name);
    fprintf(outfile, "/* width height ncolors chars_per_pixel */\n");
    fprintf(outfile, "\"%d %d %d %d\",\n", cols, rows, 
            cmapSize, charsPerPixel);

    {
        int i;
        /* Write out the colormap (part of header) */
        fprintf(outfile, "/* colors */\n");
        for (i = 0; i < cmapSize; i++) { 
            fprintf(outfile, "\"%s c %s\",\n", cmap[i].cixel, cmap[i].rgbname);
        }
    }
    {
        int row;

        /* And now the raster */
        fprintf(outfile, "/* pixels */\n");
        for (row = 0; row < rows; row++) {
            int col;
            fprintf(outfile, "\"");
            for (col = 0; col < cols; col++) {
                if (alpha && alpha[row][col] <= alphamaxval/2)
                    /* It's a transparent pixel */
                    fprintf(outfile, "%s", cmap[transIndex].cixel);
                else 
                    fprintf(outfile, "%s", 
                            cmap[ppm_lookupcolor(cht, 
                                                 &pixels[row][col])].cixel);
            }
            fprintf(outfile, "\"%s\n", (row == (rows - 1) ? "" : ","));
        }
    }
    /* And close up */
    fprintf(outfile, "};\n");
}
Esempio n. 4
0
static ICON_bmp 
create4Bitmap (pixel ** const pa, int const cols, int const rows,
               colorhash_table const cht) {
   /*
    * How wide should the u1 string for each row be?
    * each byte is 8 pixels, but must be a multiple of 4 bytes.
    */
   ICON_bmp icBitmap;
   int xBytes,y,x;
   int wt = cols;
   u1 ** rowData;

   MALLOCVAR_NOFAIL(icBitmap);

   wt >>= 1;
   if (wt & 3) {
      wt = (wt & ~3) + 4;
   }
   xBytes = wt;
   MALLOCARRAY_NOFAIL(rowData, rows);
   icBitmap->xBytes = xBytes;
   icBitmap->data   = rowData;
   overflow2(xBytes, rows);
   icBitmap->size   = xBytes * rows;

   for (y=0;y<rows;y++) {
      u1 * row;
      int byteOn = 0;
      int nibble = 1;   /* high nibble = 1, low nibble = 0; */
      int value;

      MALLOCARRAY_NOFAIL(row, xBytes);

      memset (row, 0, xBytes);
      rowData[rows-y-1] = row;
      /* 
       * Check there's a pixel array, otherwise we're just faking this...
       */
      if (pa) {
     for (x=0;x<cols;x++) {
        value = ppm_lookupcolor(cht, &pa[y][x]);
        /*
         * Shift it, if we're putting it in the high nibble.
         */
        if (nibble) {
           value <<= 4;
        }
        row[byteOn] |= value;
        if (nibble) {
           nibble = 0;
        } else {
           nibble = 1;
           byteOn++;
        }
     }
      }
   }
   return icBitmap;
}
Esempio n. 5
0
static int
GetPixel(int const x,
         int const y) {

    int color;
    
    color = ppm_lookupcolor(cht, &pixels[y][x]);
    
    return color;
}
Esempio n. 6
0
void
fill_png_row(CONVERT_IMG_ROW inputrgb, png_bytep outputindex, int16 width,colorhash_table cht)
{
    int i;
    XP_ASSERT(inputrgb);
    XP_ASSERT(outputindex);
    XP_ASSERT(cht);
    for (i=0; i<width; i++)
    {
        outputindex[i]=(BYTE)ppm_lookupcolor( cht, &((pixel*)inputrgb)[i] );
    }
}
Esempio n. 7
0
static void
putPcxColorInHash(colorhash_table const cht,
                  pixel           const newPcxColor,
                  unsigned int    const newColorIndex,
                  pixval          const maxval) {

    pixel ppmColor;
        /* Same color as 'newPcxColor', but at the PPM image's color
           resolution: 'maxval'
        */
    int rc;

    PPM_DEPTH(ppmColor, newPcxColor, PCX_MAXVAL, maxval);
        
    rc = ppm_lookupcolor(cht, &ppmColor);

    if (rc == -1)
        /* This color is not in the hash yet, so we just add it */
        ppm_addtocolorhash(cht, &ppmColor, newColorIndex);
    else {
        /* This color is already in the hash.  That's because the
           subject image has less color resolution than PCX (i.e.
           'maxval' is less than PCX_MAXVAL), and two distinct
           colors in the standard palette are indistinguishable at
           subject image color resolution.
           
           So we have to figure out wether color 'newPcxColor' or
           'existingPcxColor' is a better match for 'ppmColor'.
        */

        unsigned int const existingColorIndex = rc;

        pixel idealPcxColor;
        pixel existingPcxColor;

        PPM_DEPTH(idealPcxColor, ppmColor, maxval, PCX_MAXVAL);
        
        PPM_ASSIGN(existingPcxColor, 
                   stdPalette[existingColorIndex].r,
                   stdPalette[existingColorIndex].g,
                   stdPalette[existingColorIndex].b);

        if (PPM_DISTANCE(newPcxColor, idealPcxColor) <
            PPM_DISTANCE(existingPcxColor, idealPcxColor)) {
            /* The new PCX color is a better match.  Make it the new
               translation of image color 'ppmColor'.
            */
            ppm_delfromcolorhash(cht, &ppmColor);
            ppm_addtocolorhash(cht, &ppmColor, newColorIndex);
        }
    }
}
Esempio n. 8
0
static void
computecolorhash(pixel **          const pixels,
                 gray **           const alpha,
                 int               const cols,
                 int               const rows,
                 gray              const alphaMaxval,
                 colorhash_table * const chtP,
                 unsigned int *    const ncolorsP,
                 bool *            const transparentSomewhereP) {
/*----------------------------------------------------------------------------
   Compute a colorhash_table with one entry for each color in 'pixels' that
   is not mostly transparent according to alpha mask 'alpha' (which has
   maxval 'alphaMaxval').  alpha == NULL means all pixels are opaque.

   The value associated with the color in the hash we build is meaningless.

   Return the colorhash_table as *chtP, and the number of colors in it
   as *ncolorsP.  Return *transparentSomewhereP == TRUE iff the image has
   at least one pixel that is mostly transparent.
-----------------------------------------------------------------------------*/
    colorhash_table cht;
    int row;
    
    cht = ppm_alloccolorhash( );
    *ncolorsP = 0;   /* initial value */
    *transparentSomewhereP = FALSE;  /* initial assumption */

    /* Go through the entire image, building a hash table of colors. */
    for (row = 0; row < rows; ++row) {
        int col;

        for (col = 0; col < cols; ++col) {
            if (!alpha || alpha[row][col] > alphaMaxval/2) {
                /* It's mostly opaque, so add this color to the hash
                   if it's not already there.  
                */
                pixel const color = pixels[row][col];
                int const lookupRc = ppm_lookupcolor(cht, &color);
 
                if (lookupRc < 0) {
                    /* It's not in the hash yet, so add it */
                    ppm_addtocolorhash(cht, &color, 0);
                    ++(*ncolorsP);
                }
            } else
                *transparentSomewhereP = TRUE;
        }
    }
    *chtP = cht;
}
Esempio n. 9
0
static int
colorIndexAtPosition(unsigned int    const x,
                     unsigned int    const y,
                     pixel **        const pixels,
                     colorhash_table const cht) {

    int rc;

    rc = ppm_lookupcolor(cht, &pixels[y][x]);

    /* Every color in the image is in the palette */
    assert(rc >= 0);

    return rc;
}
Esempio n. 10
0
static unsigned int
indexOfColor(colorhash_table const cht,
             pixel           const color) {
/*----------------------------------------------------------------------------
   Return the index in the palette described by 'cht' of the color 'color'.

   Abort program with error message if the color is not in the palette.
-----------------------------------------------------------------------------*/

    int const rc = ppm_lookupcolor(cht, &color);
            
    if (rc < 0)
        pm_error("Image contains color which is not "
                 "in the palette: %u/%u/%u", 
                 PPM_GETR(color), PPM_GETG(color), PPM_GETB(color));

    return rc;
}
Esempio n. 11
0
static ICON_bmp 
create8Bitmap (pixel ** const pa, int const cols, int const rows,
               colorhash_table const cht) {
   /*
    * How wide should the u1 string for each row be?
    * each byte is 8 pixels, but must be a multiple of 4 bytes.
    */
   ICON_bmp icBitmap;
   int xBytes,y,x;
   int wt = cols;
   u1 ** rowData;

   MALLOCVAR_NOFAIL(icBitmap);

   if (wt & 3) {
      wt = (wt & ~3) + 4;
   }
   xBytes = wt;
   MALLOCARRAY_NOFAIL(rowData, rows);
   icBitmap->xBytes = xBytes;
   icBitmap->data   = rowData;
   overflow2(xBytes, rows);
   icBitmap->size   = xBytes * rows;

   for (y=0;y<rows;y++) {
      u1 * row;

      MALLOCARRAY_NOFAIL(row, xBytes);
      memset (row, 0, xBytes);
      rowData[rows-y-1] = row;
      /* 
       * Check there's a pixel array, otherwise we're just faking this...
       */
      if (pa) {
     for (x=0;x<cols;x++) {
        row[x] = ppm_lookupcolor(cht, &pa[y][x]);
     }
      }
   }
   return icBitmap;
}
Esempio n. 12
0
static void
genCmap(colorhist_vector const chv, 
        int              const ncolors, 
        pixval           const maxval, 
        colorhash_table  const colornameHash,
        const char *     const colornames[],
        bool             const includeTransparent,
        cixel_map **     const cmapP, 
        unsigned int *   const transIndexP,
        unsigned int *   const cmapSizeP,
        unsigned int *   const charsPerPixelP) {
/*----------------------------------------------------------------------------
   Generate the XPM color map in cixel_map format (which is just a step
   away from the actual text that needs to be written the XPM file).  The
   color map is defined by 'chv', which contains 'ncolors' colors which
   have maxval 'maxval'.

   Output is in newly malloc'ed storage, with its address returned as
   *cmapP.  We return the number of entries in it as *cmapSizeP.

   This map includes an entry for transparency, whether the raster uses
   it or not.  We return its index as *transIndexP.

   In the map, identify colors by the names given by 'colornameHash' and
   colornames[].  'colornameHash' maps a color in 'pixel' form to an
   index into colornames[]; colornames[] contains the text to identify the
   color in the XPM format.  The colors in 'colornameHash' have maxval 255.
   If a color is not in 'colornameHash', use hexadecimal notation in the
   output colormap.

   But if 'colornameHash' is null, don't use color names at all.  Just use
   hexadecimal notation.

   Return as *charsPerPixel the number of characters, or digits, that
   will be needed in the XPM raster to form an index into this color map.
-----------------------------------------------------------------------------*/
    unsigned int const cmapSize = ncolors + (includeTransparent ? 1 : 0);

    cixel_map * cmap;  /* malloc'ed */
    unsigned int cmapIndex;
    unsigned int charsPerPixel;
    unsigned int xpmMaxval;
    
    MALLOCARRAY(cmap, cmapSize);
    if (cmapP == NULL)
        pm_error("Out of memory allocating %u bytes for a color map.",
                 (unsigned)sizeof(cixel_map) * (ncolors+1));

    xpmMaxval = xpmMaxvalFromMaxval(maxval);

    charsPerPixel = charsPerPixelForSize(cmapSize);

    /*
     * Generate the character-pixel string and the rgb name for each
     * colormap entry. 
     */
    for (cmapIndex = 0; cmapIndex < ncolors; ++cmapIndex) {
        pixel const color = chv[cmapIndex].color;

        pixel color255;
            /* The color, scaled to maxval 255 */
        const char * colorname;  /* malloc'ed */
        /*
         * The character-pixel string is simply a printed number in base
         * MAXPRINTABLE where the digits of the number range from
         * printable[0] .. printable[MAXPRINTABLE-1] and the printed length
         * of the number is 'charsPerPixel'. 
         */
        cmap[cmapIndex].cixel = genNumstr(cmapIndex, charsPerPixel);
        
        PPM_DEPTH(color255, color, maxval, 255);

        if (colornameHash == NULL)
            colorname = NULL;
        else {
            int colornameIndex;
            colornameIndex = ppm_lookupcolor(colornameHash, &color255);
            if (colornameIndex >= 0)
                colorname = strdup(colornames[colornameIndex]);
            else
                colorname = NULL;
        }
        if (colorname)
            cmap[cmapIndex].rgbname = colorname;
        else {
            /* Color has no name; represent it in hexadecimal */

            pixel scaledColor;
            const char * hexString;  /* malloc'ed */

            PPM_DEPTH(scaledColor, color, maxval, xpmMaxval);

            pm_asprintf(&hexString, xpmMaxval == 0x000F ? "#%X%X%X" :
                        xpmMaxval == 0x00FF ? "#%02X%02X%02X" :
                        xpmMaxval == 0x0FFF ? "#%03X%03X%03X" :
                        "#%04X%04X%04X", 
                        PPM_GETR(scaledColor),
                        PPM_GETG(scaledColor),
                        PPM_GETB(scaledColor)
                );

            if (hexString == NULL)
                pm_error("Unable to allocate storage for hex string");
            cmap[cmapIndex].rgbname = hexString;
        }
    }

    if (includeTransparent) {
        /* Add the special transparency entry to the colormap */
        unsigned int const transIndex = ncolors;
        cmap[transIndex].rgbname = strdup("None");
        cmap[transIndex].cixel = genNumstr(transIndex, charsPerPixel);
        *transIndexP = transIndex;
    }
    *cmapP          = cmap;
    *cmapSizeP      = cmapSize;
    *charsPerPixelP = charsPerPixel;
}