cvs: gd /playground/gdbmp bmp.h gd_bmp.c
[email protected] ("Scott MacVicar") Thu, 03 Jan 2008 02:15:19 -0000
| Newsgroups | php.gd.cvs |
|---|---|
| Message-ID | <cvsscottmac1199326519@cvsserver> |
scottmac Thu Jan 3 02:15:19 2008 UTC
Modified files:
/gd/playground/gdbmp bmp.h gd_bmp.c
Log:
Add RLE compression
http://cvs.php.net/viewvc.cgi/gd/playground/gdbmp/bmp.h?r1=1.2&r2=1.3&diff_format=u
Index: gd/playground/gdbmp/bmp.h
diff -u gd/playground/gdbmp/bmp.h:1.2 gd/playground/gdbmp/bmp.h:1.3
--- gd/playground/gdbmp/bmp.h:1.2 Sat Oct 13 18:18:30 2007
+++ gd/playground/gdbmp/bmp.h Thu Jan 3 02:15:19 2008
@@ -37,6 +37,11 @@
#define BMP_BI_JPEG 4
#define BMP_BI_PNG 5
+#define BMP_RLE_COMMAND 0
+#define BMP_RLE_ENDOFLINE 0
+#define BMP_RLE_ENDOFBITMAP 1
+#define BMP_RLE_DELTA 2
+
/* BMP header. */
typedef struct
{
http://cvs.php.net/viewvc.cgi/gd/playground/gdbmp/gd_bmp.c?r1=1.2&r2=1.3&diff_format=u
Index: gd/playground/gdbmp/gd_bmp.c
diff -u gd/playground/gdbmp/gd_bmp.c:1.2 gd/playground/gdbmp/gd_bmp.c:1.3
--- gd/playground/gdbmp/gd_bmp.c:1.2 Sat Oct 13 18:18:30 2007
+++ gd/playground/gdbmp/gd_bmp.c Thu Jan 3 02:15:19 2008
@@ -8,7 +8,7 @@
Todo:
- RLE4, RLE8 and Bitfield encoding
+ Bitfield encoding
Add full support for Windows v4 and Windows v5 header formats
Add write support
@@ -36,8 +36,9 @@
static int bmp_read_1bit(gdImagePtr im, gdIOCtxPtr infile, bmp_info_t *info, bmp_hdr_t *header);
static int bmp_read_4bit(gdImagePtr im, gdIOCtxPtr infile, bmp_info_t *info, bmp_hdr_t *header);
static int bmp_read_8bit(gdImagePtr im, gdIOCtxPtr infile, bmp_info_t *info, bmp_hdr_t *header);
+static int bmp_read_rle(gdImagePtr im, gdIOCtxPtr infile, bmp_info_t *info);
-/* Byte helper functions */
+/* Byte helper functions, since added to GD 2.1 */
static int gdBMPGetInt(signed int *result, gdIOCtx * ctx);
static int gdBMPGetWord(signed short int *result, gdIOCtx * ctx);
@@ -339,7 +340,7 @@
BMP_DEBUG(printf("Bitfield compression isn't supported for 24-bit\n"));
return 1;
}
- BMP_DEBUG(printf("No bitfield support atm\n"));
+ BMP_DEBUG(printf("Currently no bitfield support\n"));
return 1;
break;
@@ -541,7 +542,7 @@
int ypos = 0, xpos = 0, row = 0, index = 0;
int padding = 0, current_byte = 0;
- if (info->enctype != BMP_BI_RGB /*&& info->enctype != BMP_BI_RLE4*/)
+ if (info->enctype != BMP_BI_RGB && info->enctype != BMP_BI_RLE4)
{
return 1;
}
@@ -575,48 +576,63 @@
padding = 4 - padding;
}
- for (ypos = 0; ypos < info->height; ++ypos)
+ switch (info->enctype)
{
- if (info->topdown)
- {
- row = ypos;
- }
- else
- {
- row = info->height - ypos - 1;
- }
- for (xpos = 0; xpos < info->width; xpos+=2)
+ case BMP_BI_RGB:
+ for (ypos = 0; ypos < info->height; ++ypos)
{
- if (!gdGetByte(¤t_byte, infile))
+ if (info->topdown)
{
- return 1;
+ row = ypos;
}
- index = (current_byte >> 4) & 0x0f;
- if (im->open[index])
+ else
{
- im->open[index] = 0;
+ row = info->height - ypos - 1;
}
- gdImageSetPixel(im, xpos, row, index);
- /* This condition may get called often, potential optimsations */
- if (xpos >= info->width)
+ for (xpos = 0; xpos < info->width; xpos+=2)
{
- break;
+ if (!gdGetByte(¤t_byte, infile))
+ {
+ return 1;
+ }
+ index = (current_byte >> 4) & 0x0f;
+ if (im->open[index])
+ {
+ im->open[index] = 0;
+ }
+ gdImageSetPixel(im, xpos, row, index);
+ /* This condition may get called often, potential optimsations */
+ if (xpos >= info->width)
+ {
+ break;
+ }
+
+ index = current_byte & 0x0f;
+ if (im->open[index])
+ {
+ im->open[index] = 0;
+ }
+ gdImageSetPixel(im, xpos + 1, row, index);
}
-
- index = current_byte & 0x0f;
- if (im->open[index])
+ for (xpos = padding; xpos > 0; --xpos)
{
- im->open[index] = 0;
+ if (!gdGetByte(&index, infile))
+ {
+ return 1;
+ }
}
- gdImageSetPixel(im, xpos + 1, row, index);
}
- for (xpos = padding; xpos > 0; --xpos)
+ break;
+
+ case BMP_BI_RLE4:
+ if (bmp_read_rle(im, infile, info))
{
- if (!gdGetByte(&index, infile))
- {
- return 1;
- }
+ return 1;
}
+ break;
+
+ default:
+ return 1;
}
return 0;
}
@@ -625,7 +641,8 @@
{
int ypos = 0, xpos = 0, row = 0, index = 0;
int padding = 0;
- if (info->enctype != BMP_BI_RGB/* && info->enctype != BMP_BI_RLE8*/)
+
+ if (info->enctype != BMP_BI_RGB && info->enctype != BMP_BI_RLE8)
{
return 1;
}
@@ -696,15 +713,117 @@
}
}
break;
+
case BMP_BI_RLE8:
- BMP_DEBUG(printf("Run-length Encoding 8bits / pixel isn't supported\n"));
+ if (bmp_read_rle(im, infile, info))
+ {
+ return 1;
+ }
break;
+
default:
return 1;
}
return 0;
}
+static int bmp_read_rle(gdImagePtr im, gdIOCtxPtr infile, bmp_info_t *info)
+{
+ int ypos = 0, xpos = 0, row = 0, index = 0;
+ int rle_length = 0, rle_data = 0;
+ int padding = 0;
+ int i = 0, j = 0;
+ int pixels_per_byte = 8 / info->depth;
+
+ for (ypos = 0; ypos < info->height && xpos <= info->width;)
+ {
+ if (!gdGetByte(&rle_length, infile) || !gdGetByte(&rle_data, infile))
+ {
+ return 1;
+ }
+ row = info->height - ypos - 1;
+
+ if (rle_length != BMP_RLE_COMMAND)
+ {
+ if (im->open[rle_data])
+ {
+ im->open[rle_data] = 0;
+ }
+
+ for (i = 0; (i < rle_length) && (xpos < info->width);)
+ {
+ for (j = 1; (j <= pixels_per_byte) && (xpos < info->width) && (i < rle_length); j++, xpos++, i++)
+ {
+ index = (rle_data & (((1 << info->depth) - 1) << (8 - (j * info->depth)))) >> (8 - (j * info->depth));
+ if (im->open[index])
+ {
+ im->open[index] = 0;
+ }
+ gdImageSetPixel(im, xpos, row, index);
+ }
+ }
+ }
+ else if (rle_length == BMP_RLE_COMMAND && rle_data > 2)
+ {
+ /* Uncompressed RLE needs to be even */
+ padding = 0;
+ for (i = 0; (i < rle_data) && (xpos < info->width); i += pixels_per_byte)
+ {
+ int max_pixels = pixels_per_byte;
+
+ if (!gdGetByte(&index, infile))
+ {
+ return 1;
+ }
+ padding++;
+
+ if (rle_data - i < max_pixels)
+ {
+ max_pixels = rle_data - i;
+ }
+
+ for (j = 1; (j <= max_pixels) && (xpos < info->width); j++, xpos++)
+ {
+ int temp = (index >> (8 - (j * info->depth))) & ((1 << info->depth) - 1);
+ if (im->open[temp])
+ {
+ im->open[temp] = 0;
+ }
+ gdImageSetPixel(im, xpos, row, temp);
+ }
+ }
+
+ /* Make sure the bytes read are even */
+ if (padding % 2 && !gdGetByte(&index, infile))
+ {
+ return 1;
+ }
+ }
+ else if (rle_length == BMP_RLE_COMMAND && rle_data == BMP_RLE_ENDOFLINE)
+ {
+ /* Next Line */
+ xpos = 0;
+ ypos++;
+ }
+ else if (rle_length == BMP_RLE_COMMAND && rle_data == BMP_RLE_DELTA)
+ {
+ /* Delta Record, used for bmp files that contain other data*/
+ if (!gdGetByte(&rle_length, infile) || !gdGetByte(&rle_data, infile))
+ {
+ return 1;
+ }
+ xpos += rle_length;
+ ypos += rle_data;
+ }
+ else if (rle_length == BMP_RLE_COMMAND && rle_data == BMP_RLE_ENDOFBITMAP)
+ {
+ /* End of bitmap */
+ break;
+ }
+ }
+ return 0;
+}
+
static int gdBMPGetWord(signed short int *result, gdIOCtx * ctx)
{
int high = 0, low = 0;