]> git.imager.perl.org - imager.git/blobdiff - bmp.c
- correct documentation of default of raw image interleave read
[imager.git] / bmp.c
diff --git a/bmp.c b/bmp.c
index 7986f26d2fd7a47222da03e1c3ba9c3a852897ec..8f37d32ab48d372b9c4a979fd665e335c1f4b277 100644 (file)
--- a/bmp.c
+++ b/bmp.c
@@ -367,7 +367,7 @@ int write_bmphead(io_glue *ig, i_img *im, int bit_count, int data_size) {
 
   if (!write_packed(ig, "CCVvvVVVVvvVVVVVV", 'B', 'M', data_size+offset, 
                    0, 0, offset, INFOHEAD_SIZE, im->xsize, im->ysize, 1, 
-                   bit_count, BI_RGB, 0, (int)(xres+0.5), (int)(yres+0.5), 
+                   bit_count, BI_RGB, data_size, (int)(xres+0.5), (int)(yres+0.5), 
                    colors_used, colors_used)){
     i_push_error(0, "cannot write bmp header");
     return 0;
@@ -575,9 +575,6 @@ write_8bit_data(io_glue *ig, i_img *im) {
   return 1;
 }
 
-static int bgr_chans[] = { 2, 1, 0, };
-static int grey_chans[] = { 0, 0, 0, };
-
 /*
 =item write_24bit_data(ig, im)
 
@@ -589,10 +586,12 @@ Returns non-zero on success.
 */
 static int
 write_24bit_data(io_glue *ig, i_img *im) {
-  int *chans;
   unsigned char *samples;
   int y;
   int line_size = 3 * im->xsize;
+  i_color bg;
+
+  i_get_file_background(im, &bg);
 
   /* just in case we implement a direct format with 2bytes/pixel
      (unlikely though) */
@@ -605,11 +604,18 @@ write_24bit_data(io_glue *ig, i_img *im) {
   
   if (!write_bmphead(ig, im, 24, line_size * im->ysize))
     return 0;
-  chans = im->channels >= 3 ? bgr_chans : grey_chans;
-  samples = mymalloc(line_size); /* checked 29jun05 tonyc */
+  samples = mymalloc(4 * im->xsize);
   memset(samples, 0, line_size);
   for (y = im->ysize-1; y >= 0; --y) {
-    i_gsamp(im, 0, im->xsize, y, samples, chans, 3);
+    unsigned char *samplep = samples;
+    int x;
+    i_gsamp_bg(im, 0, im->xsize, y, samples, 3, &bg);
+    for (x = 0; x < im->xsize; ++x) {
+      unsigned char tmp = samplep[2];
+      samplep[2] = samplep[0];
+      samplep[0] = tmp;
+      samplep += 3;
+    }
     if (ig->writecb(ig, samples, line_size) < 0) {
       i_push_error(0, "writing image data");
       myfree(samples);
@@ -916,6 +922,14 @@ read_4bit_bmp(io_glue *ig, int xsize, int ysize, int clr_used,
         }
       }
       else if (packed[0]) {
+       if (x + packed[0] > xsize) {
+         /* this file is corrupt */
+         myfree(packed);
+         myfree(line);
+         i_push_error(0, "invalid data during decompression");
+         i_img_destroy(im);
+         return NULL;
+       }
         line[0] = packed[1] >> 4;
         line[1] = packed[1] & 0x0F;
         for (i = 0; i < packed[0]; i += 2) {
@@ -958,6 +972,14 @@ read_4bit_bmp(io_glue *ig, int xsize, int ysize, int clr_used,
 
         default:
           count = packed[1];
+         if (x + count > xsize) {
+           /* this file is corrupt */
+           myfree(packed);
+           myfree(line);
+           i_push_error(0, "invalid data during decompression");
+           i_img_destroy(im);
+           return NULL;
+         }
           size = (count + 1) / 2;
           read_size = (size+1) / 2 * 2;
           if (ig->readcb(ig, packed, read_size) != read_size) {
@@ -1113,6 +1135,13 @@ read_8bit_bmp(io_glue *ig, int xsize, int ysize, int clr_used,
         }
       }
       if (packed[0]) {
+       if (x + packed[0] > xsize) {
+         /* this file isn't incomplete, it's corrupt */
+         myfree(line);
+         i_push_error(0, "invalid data during decompression");
+         i_img_destroy(im);
+         return NULL;
+       }
         memset(line, packed[1], packed[0]);
         i_ppal(im, x, x+packed[0], y, line);
         x += packed[0];
@@ -1147,6 +1176,14 @@ read_8bit_bmp(io_glue *ig, int xsize, int ysize, int clr_used,
 
         default:
           count = packed[1];
+         if (x + count > xsize) {
+           /* runs shouldn't cross a line boundary */
+           /* this file isn't incomplete, it's corrupt */
+           myfree(line);
+           i_push_error(0, "invalid data during decompression");
+           i_img_destroy(im);
+           return NULL;
+         }
           read_size = (count+1) / 2 * 2;
           if (ig->readcb(ig, line, read_size) != read_size) {
             myfree(line);