/* * Copyright (c) 1997-2006 Motoyuki Kasahara * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include "build-pre.h" #include "eb.h" #include "error.h" #include "font.h" #include "build-post.h" #include /* * Unexported functions. */ static unsigned long png_crc(const char *buf, size_t len); static int png_compress(const char *src, int width, int height, char *dest, size_t *dest_len); /* * Return required buffer size for a narrow font character converted * to XBM image format. */ EB_Error_Code eb_narrow_font_xbm_size(EB_Font_Code height, size_t *size) { EB_Error_Code error_code; LOG(("in: eb_narrow_font_xbm_size(height=%d)", (int)height)); switch (height) { case EB_FONT_16: *size = EB_SIZE_NARROW_FONT_16_XBM; break; case EB_FONT_24: *size = EB_SIZE_NARROW_FONT_24_XBM; break; case EB_FONT_30: *size = EB_SIZE_NARROW_FONT_30_XBM; break; case EB_FONT_48: *size = EB_SIZE_NARROW_FONT_48_XBM; break; default: error_code = EB_ERR_NO_SUCH_FONT; goto failed; } LOG(("out: eb_narrow_font_xbm_size(size=%ld) = %s", (long)*size, eb_error_string(EB_SUCCESS))); return EB_SUCCESS; /* * An error occurs... */ failed: *size = 0; LOG(("out: eb_narrow_font_xbm_size() = %s", eb_error_string(error_code))); return error_code; } /* * Return required buffer size for a narrow font character converted * to XPM image format. */ EB_Error_Code eb_narrow_font_xpm_size(EB_Font_Code height, size_t *size) { EB_Error_Code error_code; LOG(("in: eb_narrow_font_xpm_size(height=%d)", (int)height)); switch (height) { case EB_FONT_16: *size = EB_SIZE_NARROW_FONT_16_XPM; break; case EB_FONT_24: *size = EB_SIZE_NARROW_FONT_24_XPM; break; case EB_FONT_30: *size = EB_SIZE_NARROW_FONT_30_XPM; break; case EB_FONT_48: *size = EB_SIZE_NARROW_FONT_48_XPM; break; default: error_code = EB_ERR_NO_SUCH_FONT; goto failed; } LOG(("out: eb_narrow_font_xpm_size(size=%ld) = %s", (long)*size, eb_error_string(EB_SUCCESS))); return EB_SUCCESS; /* * An error occurs... */ failed: *size = 0; LOG(("out: eb_narrow_font_xpm_size() = %s", eb_error_string(error_code))); return error_code; } /* * Return required buffer size for a narrow font character converted * to GIF image format. */ EB_Error_Code eb_narrow_font_gif_size(EB_Font_Code height, size_t *size) { EB_Error_Code error_code; LOG(("in: eb_narrow_font_gif_size(height=%d)", (int)height)); switch (height) { case EB_FONT_16: *size = EB_SIZE_NARROW_FONT_16_GIF; break; case EB_FONT_24: *size = EB_SIZE_NARROW_FONT_24_GIF; break; case EB_FONT_30: *size = EB_SIZE_NARROW_FONT_30_GIF; break; case EB_FONT_48: *size = EB_SIZE_NARROW_FONT_48_GIF; default: error_code = EB_ERR_NO_SUCH_FONT; goto failed; } LOG(("out: eb_narrow_font_gif_size(size=%ld) = %s", (long)*size, eb_error_string(EB_SUCCESS))); return EB_SUCCESS; /* * An error occurs... */ failed: *size = 0; LOG(("out: eb_narrow_font_gif_size() = %s", eb_error_string(error_code))); return error_code; } /* * Return required buffer size for a narrow font character converted * to BMP image format. */ EB_Error_Code eb_narrow_font_bmp_size(EB_Font_Code height, size_t *size) { EB_Error_Code error_code; LOG(("in: eb_narrow_font_bmp_size(height=%d)", (int)height)); switch (height) { case EB_FONT_16: *size = EB_SIZE_NARROW_FONT_16_BMP; break; case EB_FONT_24: *size = EB_SIZE_NARROW_FONT_24_BMP; break; case EB_FONT_30: *size = EB_SIZE_NARROW_FONT_30_BMP; break; case EB_FONT_48: *size = EB_SIZE_NARROW_FONT_48_BMP; break; default: error_code = EB_ERR_NO_SUCH_FONT; goto failed; } LOG(("out: eb_narrow_font_bmp_size(size=%ld) = %s", (long)*size, eb_error_string(EB_SUCCESS))); return EB_SUCCESS; /* * An error occurs... */ failed: *size = 0; LOG(("out: eb_narrow_font_bmp_size() = %s", eb_error_string(error_code))); return error_code; } /* * Return required buffer size for a narrow font character converted * to PNG image format. */ EB_Error_Code eb_narrow_font_png_size(EB_Font_Code height, size_t *size) { EB_Error_Code error_code; LOG(("in: eb_narrow_font_png_size(height=%d)", (int)height)); switch (height) { case EB_FONT_16: *size = EB_SIZE_NARROW_FONT_16_PNG; break; case EB_FONT_24: *size = EB_SIZE_NARROW_FONT_24_PNG; break; case EB_FONT_30: *size = EB_SIZE_NARROW_FONT_30_PNG; break; case EB_FONT_48: *size = EB_SIZE_NARROW_FONT_48_PNG; default: error_code = EB_ERR_NO_SUCH_FONT; goto failed; } LOG(("out: eb_narrow_font_png_size(size=%ld) = %s", (long)*size, eb_error_string(EB_SUCCESS))); return EB_SUCCESS; /* * An error occurs... */ failed: *size = 0; LOG(("out: eb_narrow_font_png_size() = %s", eb_error_string(error_code))); return error_code; } /* * Return required buffer size for a wide font character converted * to XBM image format. */ EB_Error_Code eb_wide_font_xbm_size(EB_Font_Code height, size_t *size) { EB_Error_Code error_code; LOG(("in: eb_wide_font_xbm_size(height=%d)", (int)height)); switch (height) { case EB_FONT_16: *size = EB_SIZE_WIDE_FONT_16_XBM; break; case EB_FONT_24: *size = EB_SIZE_WIDE_FONT_24_XBM; break; case EB_FONT_30: *size = EB_SIZE_WIDE_FONT_30_XBM; break; case EB_FONT_48: *size = EB_SIZE_WIDE_FONT_48_XBM; break; default: error_code = EB_ERR_NO_SUCH_FONT; goto failed; } LOG(("out: eb_wide_font_xbm_size(size=%ld) = %s", (long)*size, eb_error_string(EB_SUCCESS))); return EB_SUCCESS; /* * An error occurs... */ failed: *size = 0; LOG(("out: eb_wide_font_xbm_size() = %s", eb_error_string(error_code))); return error_code; } /* * Return required buffer size for a wide font character converted * to XPM image format. */ EB_Error_Code eb_wide_font_xpm_size(EB_Font_Code height, size_t *size) { EB_Error_Code error_code; LOG(("in: eb_wide_font_xpm_size(height=%d)", (int)height)); switch (height) { case EB_FONT_16: *size = EB_SIZE_WIDE_FONT_16_XPM; break; case EB_FONT_24: *size = EB_SIZE_WIDE_FONT_24_XPM; break; case EB_FONT_30: *size = EB_SIZE_WIDE_FONT_30_XPM; break; case EB_FONT_48: *size = EB_SIZE_WIDE_FONT_48_XPM; break; default: error_code = EB_ERR_NO_SUCH_FONT; goto failed; } LOG(("out: eb_wide_font_xpm_size(size=%ld) = %s", (long)*size, eb_error_string(EB_SUCCESS))); return EB_SUCCESS; /* * An error occurs... */ failed: *size = 0; LOG(("out: eb_wide_font_xpm_size() = %s", eb_error_string(error_code))); return error_code; } /* * Return required buffer size for a wide font character converted * to GIF image format. */ EB_Error_Code eb_wide_font_gif_size(EB_Font_Code height, size_t *size) { EB_Error_Code error_code; LOG(("in: eb_wide_font_gif_size(height=%d)", (int)height)); switch (height) { case EB_FONT_16: *size = EB_SIZE_WIDE_FONT_16_GIF; break; case EB_FONT_24: *size = EB_SIZE_WIDE_FONT_24_GIF; break; case EB_FONT_30: *size = EB_SIZE_WIDE_FONT_30_GIF; break; case EB_FONT_48: *size = EB_SIZE_WIDE_FONT_48_GIF; break; default: error_code = EB_ERR_NO_SUCH_FONT; goto failed; } LOG(("out: eb_wide_font_gif_size(size=%ld) = %s", (long)*size, eb_error_string(EB_SUCCESS))); return EB_SUCCESS; /* * An error occurs... */ failed: *size = 0; LOG(("out: eb_wide_font_gif_size() = %s", eb_error_string(error_code))); return error_code; } /* * Return required buffer size for a wide font character converted * to BMP image format. */ EB_Error_Code eb_wide_font_bmp_size(EB_Font_Code height, size_t *size) { EB_Error_Code error_code; LOG(("in: eb_wide_font_bmp_size(height=%d)", (int)height)); switch (height) { case EB_FONT_16: *size = EB_SIZE_WIDE_FONT_16_BMP; break; case EB_FONT_24: *size = EB_SIZE_WIDE_FONT_24_BMP; break; case EB_FONT_30: *size = EB_SIZE_WIDE_FONT_30_BMP; break; case EB_FONT_48: *size = EB_SIZE_WIDE_FONT_48_BMP; break; default: error_code = EB_ERR_NO_SUCH_FONT; goto failed; } LOG(("out: eb_wide_font_bmp_size(size=%ld) = %s", (long)*size, eb_error_string(EB_SUCCESS))); return EB_SUCCESS; /* * An error occurs... */ failed: *size = 0; LOG(("out: eb_wide_font_bmp_size() = %s", eb_error_string(error_code))); return error_code; } /* * Return required buffer size for a wide font character converted * to PNG image format. */ EB_Error_Code eb_wide_font_png_size(EB_Font_Code height, size_t *size) { EB_Error_Code error_code; LOG(("in: eb_wide_font_png_size(height=%d)", (int)height)); switch (height) { case EB_FONT_16: *size = EB_SIZE_WIDE_FONT_16_PNG; break; case EB_FONT_24: *size = EB_SIZE_WIDE_FONT_24_PNG; break; case EB_FONT_30: *size = EB_SIZE_WIDE_FONT_30_PNG; break; case EB_FONT_48: *size = EB_SIZE_WIDE_FONT_48_PNG; break; default: error_code = EB_ERR_NO_SUCH_FONT; goto failed; } LOG(("out: eb_wide_font_png_size(size=%ld) = %s", (long)*size, eb_error_string(EB_SUCCESS))); return EB_SUCCESS; /* * An error occurs... */ failed: *size = 0; LOG(("out: eb_wide_font_png_size() = %s", eb_error_string(error_code))); return error_code; } /* * The maximum number of octets in a line in a XBM file. */ #define XBM_MAX_OCTETS_A_LINE 12 /* * The base name of a XBM file. */ #define XBM_BASE_NAME "default" /* * Convert a bitmap image to XBM format. * * It requires four arguements. `xbm' is buffer to store the XBM * image data. `bitmap', `width', and `height' are bitmap data, * width, and height of the bitmap image. */ EB_Error_Code eb_bitmap_to_xbm(const char *bitmap, int width, int height, char *xbm, size_t *xbm_length) { char *xbm_p = xbm; const unsigned char *bitmap_p = (const unsigned char *)bitmap; int bitmap_size = (width + 7) / 8 * height; int hex; int i; LOG(("in: eb_bitmap_to_xbm(width=%d, height=%d)", width, height)); /* * Output a header. */ sprintf(xbm_p, "#define %s_width %4d\n", XBM_BASE_NAME, width); xbm_p = strchr(xbm_p, '\n') + 1; sprintf(xbm_p, "#define %s_height %4d\n", XBM_BASE_NAME, height); xbm_p = strchr(xbm_p, '\n') + 1; sprintf(xbm_p, "static unsigned char %s_bits[] = {\n", XBM_BASE_NAME); xbm_p = strchr(xbm_p, '\n') + 1; /* * Output image data. */ for (i = 0; i < bitmap_size; i++) { hex = 0; hex |= (*bitmap_p & 0x80) ? 0x01 : 0x00; hex |= (*bitmap_p & 0x40) ? 0x02 : 0x00; hex |= (*bitmap_p & 0x20) ? 0x04 : 0x00; hex |= (*bitmap_p & 0x10) ? 0x08 : 0x00; hex |= (*bitmap_p & 0x08) ? 0x10 : 0x00; hex |= (*bitmap_p & 0x04) ? 0x20 : 0x00; hex |= (*bitmap_p & 0x02) ? 0x40 : 0x00; hex |= (*bitmap_p & 0x01) ? 0x80 : 0x00; bitmap_p++; if (i % XBM_MAX_OCTETS_A_LINE != 0) { sprintf(xbm_p, ", 0x%02x", hex); xbm_p += 6; } else if (i == 0) { sprintf(xbm_p, " 0x%02x", hex); xbm_p += 7; } else { sprintf(xbm_p, ",\n 0x%02x", hex); xbm_p += 9; } } /* * Output a footer. */ memcpy(xbm_p, "};\n", 3); xbm_p += 3; *xbm_length = xbm_p - xbm; LOG(("out: eb_bitmap_to_xbm(xbm_length=%ld) = %s", (long)(xbm_p - xbm), eb_error_string(EB_SUCCESS))); return EB_SUCCESS; } /* * The base name of a XPM file. */ #define XPM_BASE_NAME "default" /* * The foreground and background colors of XPM image. */ #define XPM_FOREGROUND_COLOR "Black" #define XPM_BACKGROUND_COLOR "None" /* * Convert a bitmap image to XPM format. * * It requires four arguements. `xpm' is buffer to store the XPM * image data. `bitmap', `width', and `height' are bitmap data, * width, and height of the bitmap image. */ EB_Error_Code eb_bitmap_to_xpm(const char *bitmap, int width, int height, char *xpm, size_t *xpm_length) { char *xpm_p = xpm; const unsigned char *bitmap_p = (const unsigned char *)bitmap; int i, j; LOG(("in: eb_bitmap_to_xpm(width=%d, height=%d)", width, height)); /* * Output a header. */ sprintf(xpm_p, "/* XPM */\n"); xpm_p = strchr(xpm_p, '\n') + 1; sprintf(xpm_p, "static char * %s[] = {\n", XPM_BASE_NAME); xpm_p = strchr(xpm_p, '\n') + 1; sprintf(xpm_p, "\"%d %d 2 1\",\n", width, height); xpm_p = strchr(xpm_p, '\n') + 1; sprintf(xpm_p, "\" c %s\",\n", XPM_BACKGROUND_COLOR); xpm_p = strchr(xpm_p, '\n') + 1; sprintf(xpm_p, "\". c %s\",\n", XPM_FOREGROUND_COLOR); xpm_p = strchr(xpm_p, '\n') + 1; /* * Output image data. */ for (i = 0; i < height; i++) { if (0 < i) { strcpy(xpm_p, "\",\n\""); xpm_p += 4; } else { *xpm_p++ = '\"'; } for (j = 0; j + 7 < width; j += 8, bitmap_p++) { *xpm_p++ = (*bitmap_p & 0x80) ? '.' : ' '; *xpm_p++ = (*bitmap_p & 0x40) ? '.' : ' '; *xpm_p++ = (*bitmap_p & 0x20) ? '.' : ' '; *xpm_p++ = (*bitmap_p & 0x10) ? '.' : ' '; *xpm_p++ = (*bitmap_p & 0x08) ? '.' : ' '; *xpm_p++ = (*bitmap_p & 0x04) ? '.' : ' '; *xpm_p++ = (*bitmap_p & 0x02) ? '.' : ' '; *xpm_p++ = (*bitmap_p & 0x01) ? '.' : ' '; } if (j < width) { if (j++ < width) *xpm_p++ = (*bitmap_p & 0x80) ? '.' : ' '; if (j++ < width) *xpm_p++ = (*bitmap_p & 0x40) ? '.' : ' '; if (j++ < width) *xpm_p++ = (*bitmap_p & 0x20) ? '.' : ' '; if (j++ < width) *xpm_p++ = (*bitmap_p & 0x10) ? '.' : ' '; if (j++ < width) *xpm_p++ = (*bitmap_p & 0x08) ? '.' : ' '; if (j++ < width) *xpm_p++ = (*bitmap_p & 0x04) ? '.' : ' '; if (j++ < width) *xpm_p++ = (*bitmap_p & 0x02) ? '.' : ' '; if (j++ < width) *xpm_p++ = (*bitmap_p & 0x01) ? '.' : ' '; bitmap_p++; } } /* * Output a footer. */ memcpy(xpm_p, "\"};\n", 4); xpm_p += 4; if (xpm_length != NULL) *xpm_length = xpm_p - xpm; LOG(("out: eb_bitmap_to_xpm(xpm_length=%ld) = %s", (long)(xpm_p - xpm), eb_error_string(EB_SUCCESS))); return EB_SUCCESS; } /* * The Foreground and background colors of GIF image. */ #define GIF_FOREGROUND_COLOR 0x000000 #define GIF_BACKGROUND_COLOR 0xffffff /* * The preamble of GIF image. */ #define GIF_PREAMBLE_LENGTH 38 static const unsigned char gif_preamble[GIF_PREAMBLE_LENGTH] = { /* * Header. (6 bytes) */ 'G', 'I', 'F', '8', '9', 'a', /* * Logical Screen Descriptor. (7 bytes) * global color table flag = 1. * color resolution = 1 - 1 = 0. * sort flag = 0. * size of global color table = 1 - 1 = 0. * background color index = 0. * the pixel aspect ratio = 0 (unused) * Logical screen width and height are set at run time. */ 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, /* * Global Color Table. (6 bytes) * These are set at run time. */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* * Graphic Control Extension. (8 bytes) * disposal method = 0. * user input flag = 0. * transparency flag = 1. * delay time = 0. * transparent color index = 0. */ 0x21, 0xf9, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, /* * Image Descriptor. (10 bytes) * image left position = 0. * image top position = 0. * local color table flag = 0. * interlace flag = 0. * sort flag = 0. * size of local color table = 0. * Image width and height are set at run time. */ 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* * Code size. (1byte) */ 0x03 }; /* * Convert a bitmap image to GIF format. * * It requires four arguements. `gif' is buffer to store the GIF * image data. `bitmap', `width', and `height' are bitmap data, * width, and height of the bitmap image. * * Note: This GIF image doesn't use LZW because of patent. */ EB_Error_Code eb_bitmap_to_gif(const char *bitmap, int width, int height, char *gif, size_t *gif_length) { unsigned char *gif_p = (unsigned char *)gif; const unsigned char *bitmap_p = (const unsigned char *)bitmap; int i, j; LOG(("in: eb_bitmap_to_gif(width=%d, height=%d)", width, height)); /* * Copy the default preamble. */ memcpy(gif_p, gif_preamble, GIF_PREAMBLE_LENGTH); /* * Set logical screen width and height. */ gif_p[6] = width & 0xff; gif_p[7] = (width >> 8) & 0xff; gif_p[8] = height & 0xff; gif_p[9] = (height >> 8) & 0xff; /* * Set global colors. */ gif_p[13] = (GIF_BACKGROUND_COLOR >> 16) & 0xff; gif_p[14] = (GIF_BACKGROUND_COLOR >> 8) & 0xff; gif_p[15] = GIF_BACKGROUND_COLOR & 0xff; gif_p[16] = (GIF_FOREGROUND_COLOR >> 16) & 0xff; gif_p[17] = (GIF_FOREGROUND_COLOR >> 8) & 0xff; gif_p[18] = GIF_FOREGROUND_COLOR & 0xff; /* * Set image width and height. */ gif_p[32] = width & 0xff; gif_p[33] = (width >> 8) & 0xff; gif_p[34] = height & 0xff; gif_p[35] = (height >> 8) & 0xff; gif_p += GIF_PREAMBLE_LENGTH; /* * Output image data. */ for (i = 0; i < height; i++) { *gif_p++ = (unsigned char)width; for (j = 0; j + 7 < width; j += 8, bitmap_p++) { *gif_p++ = (*bitmap_p & 0x80) ? 0x81 : 0x80; *gif_p++ = (*bitmap_p & 0x40) ? 0x81 : 0x80; *gif_p++ = (*bitmap_p & 0x20) ? 0x81 : 0x80; *gif_p++ = (*bitmap_p & 0x10) ? 0x81 : 0x80; *gif_p++ = (*bitmap_p & 0x08) ? 0x81 : 0x80; *gif_p++ = (*bitmap_p & 0x04) ? 0x81 : 0x80; *gif_p++ = (*bitmap_p & 0x02) ? 0x81 : 0x80; *gif_p++ = (*bitmap_p & 0x01) ? 0x81 : 0x80; } if (j < width) { if (j++ < width) *gif_p++ = (*bitmap_p & 0x80) ? 0x81 : 0x80; if (j++ < width) *gif_p++ = (*bitmap_p & 0x40) ? 0x81 : 0x80; if (j++ < width) *gif_p++ = (*bitmap_p & 0x20) ? 0x81 : 0x80; if (j++ < width) *gif_p++ = (*bitmap_p & 0x10) ? 0x81 : 0x80; if (j++ < width) *gif_p++ = (*bitmap_p & 0x08) ? 0x81 : 0x80; if (j++ < width) *gif_p++ = (*bitmap_p & 0x04) ? 0x81 : 0x80; if (j++ < width) *gif_p++ = (*bitmap_p & 0x02) ? 0x81 : 0x80; if (j++ < width) *gif_p++ = (*bitmap_p & 0x01) ? 0x81 : 0x80; bitmap_p++; } } /* * Output a trailer. */ memcpy(gif_p, "\001\011\000\073", 4); gif_p += 4; if (gif_length != NULL) *gif_length = ((char *)gif_p - gif); LOG(("out: eb_bitmap_to_gif(gif_length=%ld) = %s", (long)((char *)gif_p - gif), eb_error_string(EB_SUCCESS))); return EB_SUCCESS; } /* * The preamble of BMP image. */ #define BMP_PREAMBLE_LENGTH 62 static const unsigned char bmp_preamble[] = { /* Type. */ 'B', 'M', /* File size. (set at run time) */ 0x00, 0x00, 0x00, 0x00, /* Reserved. */ 0x00, 0x00, 0x00, 0x00, /* Offset of bitmap bits part. */ 0x3e, 0x00, 0x00, 0x00, /* Size of bitmap info part. */ 0x28, 0x00, 0x00, 0x00, /* Width. (set at run time) */ 0x00, 0x00, 0x00, 0x00, /* Height. (set at run time) */ 0x00, 0x00, 0x00, 0x00, /* Planes. */ 0x01, 0x00, /* Bits per pixels. */ 0x01, 0x00, /* Compression mode. */ 0x00, 0x00, 0x00, 0x00, /* Size of bitmap bits part. (set at run time) */ 0x00, 0x00, 0x00, 0x00, /* X Pixels per meter. */ 0x6d, 0x0b, 0x00, 0x00, /* Y Pixels per meter. */ 0x6d, 0x0b, 0x00, 0x00, /* Colors */ 0x02, 0x00, 0x00, 0x00, /* Important colors */ 0x02, 0x00, 0x00, 0x00, /* RGB quad of color 0 RGB quad of color 1 */ 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, }; /* * Convert a bitmap image to BMP format. * * It requires four arguements. `bmp' is buffer to store the BMP * image data. `bitmap', `width', and `height' are bitmap data, * width, and height of the bitmap image. */ EB_Error_Code eb_bitmap_to_bmp(const char *bitmap, int width, int height, char *bmp, size_t *bmp_length) { unsigned char *bmp_p = (unsigned char *)bmp; size_t data_size; size_t file_size; size_t line_pad_length; size_t bitmap_line_length; int i, j; LOG(("in: eb_bitmap_to_bmp(width=%d, height=%d)", width, height)); if (width % 32 == 0) line_pad_length = 0; else if (width % 32 <= 8) line_pad_length = 3; else if (width % 32 <= 16) line_pad_length = 2; else if (width % 32 <= 24) line_pad_length = 1; else line_pad_length = 0; data_size = (width / 2 + line_pad_length) * height; file_size = data_size + BMP_PREAMBLE_LENGTH; /* * Set BMP preamble. */ memcpy(bmp_p, bmp_preamble, BMP_PREAMBLE_LENGTH); bmp_p[2] = file_size & 0xff; bmp_p[3] = (file_size >> 8) & 0xff; bmp_p[4] = (file_size >> 16) & 0xff; bmp_p[5] = (file_size >> 24) & 0xff; bmp_p[18] = width & 0xff; bmp_p[19] = (width >> 8) & 0xff; bmp_p[20] = (width >> 16) & 0xff; bmp_p[21] = (width >> 24) & 0xff; bmp_p[22] = height & 0xff; bmp_p[23] = (height >> 8) & 0xff; bmp_p[24] = (height >> 16) & 0xff; bmp_p[25] = (height >> 24) & 0xff; bmp_p[34] = data_size & 0xff; bmp_p[35] = (data_size >> 8) & 0xff; bmp_p[36] = (data_size >> 16) & 0xff; bmp_p[37] = (data_size >> 24) & 0xff; bmp_p += BMP_PREAMBLE_LENGTH; bitmap_line_length = (width + 7) / 8; for (i = height - 1; 0 <= i; i--) { memcpy(bmp_p, bitmap + bitmap_line_length * i, bitmap_line_length); bmp_p += bitmap_line_length; for (j = 0; j < line_pad_length; j++, bmp_p++) *bmp_p = 0x00; } if (bmp_length != NULL) *bmp_length = ((char *)bmp_p - bmp); LOG(("out: eb_bitmap_to_bmp(bmp_length=%ld) = %s", (long)((char *)bmp_p - bmp), eb_error_string(EB_SUCCESS))); return EB_SUCCESS; } /* * The Foreground and background colors of PNG image. */ #define PNG_FOREGROUND_COLOR 0x000000 #define PNG_BACKGROUND_COLOR 0xffffff /* * The preamble of PNG image. */ static const unsigned char png_preamble[] = { /* * PNG file signature (8 bytes) */ 0x89, 'P', 'N', 'G', '\r', '\n', 0x1a, '\n', /* * IHDR(Image Header) Chunk (25 bytes) */ /* Size of IHDR. */ 0x00, 0x00, 0x00, 0x0d, 'I', 'H', 'D', 'R', /* Width. (set at run time) */ 0x00, 0x00, 0x00, 0x00, /* Height. (set at run time) */ 0x00, 0x00, 0x00, 0x00, /* misc. */ 0x01, 0x03, 0x00, 0x00, 0x00, /* CRC (set at run time) */ 0x00, 0x00, 0x00, 0x00, /* * PLTE(Palette) Chunk (18 bytes) */ /* Size of PLTE */ 0x00, 0x00, 0x00, 0x06, 'P', 'L', 'T', 'E', /* RGB for palette index 0 */ 0xff, 0xff, 0xff, /* RGB for palette index 1 */ 0x00, 0x00, 0x00, /* CRC (set at run time) */ 0x00, 0x00, 0x00, 0x00, /* * tRNS(Transparency) Chunk (13 bytes) */ /* Size of tRNS */ 0x00, 0x00, 0x00, 0x01, 't', 'R', 'N', 'S', /* Alpha for palette index 0 */ 0x00, /* CRC */ 0x40, 0xe6, 0xd8, 0x66, /* * IDAT(Image Data) Chunk (12+ bytes) */ /* Size of IDAT (set at run time) */ 0x00, 0x00, 0x00, 0x00, 'I', 'D', 'A', 'T', }; static const unsigned char png_trailer[] = { /* CRC (set at run time) */ 0x00, 0x00, 0x00, 0x00, /* * IEND(Image End) Chunk (12 bytes) */ /* Size of IEND */ 0x00, 0x00, 0x00, 0x00, 'I', 'E', 'N', 'D', /* CRC */ 0xae, 0x42, 0x60, 0x82, }; /* * Table of CRCs of all 8-bit messages. */ static const unsigned long png_crc_table[256] = { 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, /* 0x00 - 0x03 */ 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, /* 0x04 - 0x07 */ 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, /* 0x08 - 0x0b */ 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, /* 0x0c - 0x0f */ 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, /* 0x10 - 0x13 */ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, /* 0x14 - 0x17 */ 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, /* 0x18 - 0x1b */ 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, /* 0x1c - 0x1f */ 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, /* 0x20 - 0x23 */ 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, /* 0x24 - 0x27 */ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, /* 0x28 - 0x2b */ 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, /* 0x2c - 0x2f */ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, /* 0x30 - 0x33 */ 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, /* 0x34 - 0x37 */ 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, /* 0x38 - 0x3b */ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, /* 0x3c - 0x3f */ 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, /* 0x40 - 0x43 */ 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, /* 0x44 - 0x47 */ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, /* 0x48 - 0x4b */ 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, /* 0x4c - 0x4f */ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, /* 0x50 - 0x53 */ 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, /* 0x54 - 0x57 */ 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, /* 0x58 - 0x5b */ 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, /* 0x5c - 0x5f */ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, /* 0x60 - 0x63 */ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, /* 0x64 - 0x67 */ 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, /* 0x68 - 0x6b */ 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, /* 0x6c - 0x6f */ 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, /* 0x70 - 0x73 */ 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, /* 0x74 - 0x77 */ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, /* 0x78 - 0x7b */ 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, /* 0x7c - 0x7f */ 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, /* 0x80 - 0x83 */ 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, /* 0x84 - 0x87 */ 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, /* 0x88 - 0x8b */ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, /* 0x8c - 0x8f */ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, /* 0x90 - 0x93 */ 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, /* 0x94 - 0x97 */ 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, /* 0x98 - 0x9b */ 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, /* 0x9c - 0x9f */ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, /* 0xa0 - 0xa3 */ 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, /* 0xa4 - 0xa7 */ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, /* 0xa8 - 0xab */ 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, /* 0xac - 0xaf */ 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, /* 0xb0 - 0xb3 */ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, /* 0xb4 - 0xb7 */ 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, /* 0xb8 - 0xbb */ 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, /* 0xbc - 0xbf */ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, /* 0xc0 - 0xc3 */ 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, /* 0xc4 - 0xc7 */ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, /* 0xc8 - 0xcb */ 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, /* 0xcc - 0xcf */ 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, /* 0xd0 - 0xd3 */ 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, /* 0xd4 - 0xd7 */ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, /* 0xd8 - 0xdb */ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, /* 0xdc - 0xdf */ 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, /* 0xe0 - 0xe3 */ 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, /* 0xe4 - 0xe7 */ 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, /* 0xe8 - 0xeb */ 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, /* 0xec - 0xef */ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, /* 0xf0 - 0xf3 */ 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, /* 0xf4 - 0xf7 */ 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, /* 0xf8 - 0xfb */ 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d /* 0xfc - 0xff */ }; static unsigned long png_crc(const char *buf, size_t len) { unsigned long c = 0xffffffffL; int n; for (n = 0; n < len; n++) c = png_crc_table[(c ^ *((unsigned char *)buf + n)) & 0xff] ^ (c >> 8); return c ^ 0xffffffffL; } static int png_compress(const char *src, int width, int height, char *dest, size_t *dest_len) { int line_size = (width + 7) / 8; z_stream z; int z_result; unsigned char byte_zero = 0x00; int i; z.zalloc = Z_NULL; z.zfree = Z_NULL; z.opaque = Z_NULL; z_result = deflateInit(&z, Z_NO_COMPRESSION); if (z_result != Z_OK) return z_result; /* * Exactly to say, `z.avail_out' must be: * avail_out > (sizeof(src) + 12) * 1.001 * but we use an approximation here. */ z.next_out = (unsigned char *)dest; z.avail_out = (line_size + 1) * height + 12 + 256; for (i = 0; i < height - 1; i++) { z.next_in = &byte_zero; z.avail_in = 1; z_result = deflate(&z, Z_NO_FLUSH); if (z_result != Z_OK || z.avail_in != 0) goto failed; z.next_in = (unsigned char *)src + (line_size * i); z.avail_in = line_size; z_result = deflate(&z, Z_NO_FLUSH); if (z_result != Z_OK || z.avail_in != 0) goto failed; } z.next_in = &byte_zero; z.avail_in = 1; z_result = deflate(&z, Z_NO_FLUSH); if (z_result != Z_OK || z.avail_in != 0) goto failed; z.next_in = (unsigned char *)src + (line_size * i); z.avail_in = line_size; if (deflate(&z, Z_FINISH) != Z_STREAM_END) goto failed; z_result = deflateEnd(&z); if (z_result != Z_OK) return z_result; *dest_len = (z.next_out - (unsigned char *)dest); return Z_STREAM_END; /* * An error occurs... */ failed: deflateEnd(&z); return z_result; } #define INT2CHARS(p, i) do { \ *(unsigned char *)(p) = ((i) >> 24) & 0xff; \ *((unsigned char *)(p) + 1) = ((i) >> 16) & 0xff; \ *((unsigned char *)(p) + 2) = ((i) >> 8) & 0xff; \ *((unsigned char *)(p) + 3) = (i) & 0xff; \ } while (0); #define RGB2CHARS(p, i) do { \ *(unsigned char *)(p) = ((i) >> 16) & 0xff; \ *((unsigned char *)(p) + 1) = ((i) >> 8) & 0xff; \ *((unsigned char *)(p) + 2) = (i) & 0xff; \ } while (0); /* * Convert a bitmap image to PNG format. * * It requires four arguements. `png' is buffer to store the PNG * image data. `bitmap', `width', and `height' are bitmap data, * width, and height of the bitmap image. */ EB_Error_Code eb_bitmap_to_png(const char *bitmap, int width, int height, char *png, size_t *png_length) { EB_Error_Code error_code; char *png_p = png; char *idat_start; size_t idat_len; unsigned long crc; int z_result; LOG(("in: eb_bitmap_to_png(width=%d, height=%d)", width, height)); /* * Copy the default preamble. */ memcpy(png_p, png_preamble, sizeof(png_preamble)); /* * Set image width and height. */ INT2CHARS(png_p + 16, width); INT2CHARS(png_p + 20, height); crc = png_crc(png_p + 12, 17); INT2CHARS(png_p + 29, crc); /* * Set global colors. */ RGB2CHARS(png_p + 41, PNG_BACKGROUND_COLOR); RGB2CHARS(png_p + 44, PNG_FOREGROUND_COLOR); crc = png_crc(png_p + 37, 10); INT2CHARS(png_p + 47, crc); /* * Output `bitmap'. * We assume memory allocation error occurs if png_compress() doesn't * return Z_STREAM_END. */ idat_start = png_p + sizeof(png_preamble); z_result = png_compress(bitmap, width, height, idat_start, &idat_len); if (z_result != Z_STREAM_END) { error_code = EB_ERR_MEMORY_EXHAUSTED; goto failed; } INT2CHARS(png_p + 64, idat_len); crc = png_crc(idat_start - 4, idat_len + 4); png_p = idat_start + idat_len; /* * Output a trailer. */ memcpy(png_p, png_trailer, sizeof(png_trailer)); INT2CHARS(png_p, crc); png_p += sizeof(png_trailer); if (png_length != NULL) *png_length = ((char *)png_p - png); LOG(("out: eb_bitmap_to_png(png_length=%ld) = %s", (long)((char *)png_p - png), eb_error_string(EB_SUCCESS))); return EB_SUCCESS; /* * An error occurs... */ failed: LOG(("out: eb_bitmap_to_png(png_length=%ld) = %s", (long)((char *)png_p - png), eb_error_string(error_code))); return error_code; } #undef INT2CHARS #undef RGB2CHARS