]> git.imager.perl.org - imager.git/blobdiff - convert.c
fixed incorrect filename for t/t93podcover.t in MANIFEST
[imager.git] / convert.c
index 8302b20771b5abbb97fdcc25b7c3690bf9ee19bc..60144ee4aee0b28714086b239f928128fcf1f562 100644 (file)
--- a/convert.c
+++ b/convert.c
@@ -17,7 +17,7 @@ converting from RGBA to greyscale and back.
 =cut
 */
 
-#include "image.h"
+#include "imager.h"
 
 
 /*
@@ -35,13 +35,13 @@ each output pixel:
 If im has the wrong number of channels or is the wrong size then
 i_convert() will re-create it.
 
+Now handles images with more than 8-bits/sample.
+
 =cut
 */
 
 int
-i_convert(i_img *im, i_img *src, float *coeff, int outchan, int inchan)
-{
-  i_color *vals;
+i_convert(i_img *im, i_img *src, const float *coeff, int outchan, int inchan) {
   int x, y;
   int i, j;
   int ilimit;
@@ -59,36 +59,134 @@ i_convert(i_img *im, i_img *src, float *coeff, int outchan, int inchan)
     return 0;
   }
 
-  /* first check the output image */
-  if (im->channels != outchan || im->xsize != src->xsize 
-      || im->ysize != src->ysize) {
-    i_img_empty_ch(im, src->xsize, src->ysize, outchan);
+  if (im->type == i_direct_type || src->type == i_direct_type) {
+    /* first check the output image */
+    if (im->channels != outchan || im->xsize != src->xsize 
+        || im->ysize != src->ysize) {
+      i_img_exorcise(im);
+      i_img_empty_ch(im, src->xsize, src->ysize, outchan);
+    }
+    if (im->bits == i_8_bits && src->bits == i_8_bits) {
+      i_color *vals;
+
+      /* we can always allocate a single scanline of i_color */
+      vals = mymalloc(sizeof(i_color) * src->xsize); /* checked 04Jul05 tonyc */
+      for (y = 0; y < src->ysize; ++y) {
+        i_glin(src, 0, src->xsize, y, vals);
+        for (x = 0; x < src->xsize; ++x) {
+          for (j = 0; j < outchan; ++j) {
+            work[j] = 0;
+            for (i = 0; i < ilimit; ++i) {
+              work[j] += coeff[i+inchan*j] * vals[x].channel[i];
+            }
+            if (i < inchan) {
+              work[j] += coeff[i+inchan*j] * 255.9;
+            }
+          }
+          for (j = 0; j < outchan; ++j) {
+            if (work[j] < 0)
+              vals[x].channel[j] = 0;
+            else if (work[j] >= 256)
+              vals[x].channel[j] = 255;
+            else
+              vals[x].channel[j] = work[j];
+          }
+        }
+        i_plin(im, 0, src->xsize, y, vals);
+      }
+      myfree(vals);
+    }
+    else {
+      i_fcolor *vals;
+
+      /* we can always allocate a single scanline of i_fcolor 
+         for a >8 image */
+      vals = mymalloc(sizeof(i_fcolor) * src->xsize); /* checked 4Jul05 tonyc */
+      for (y = 0; y < src->ysize; ++y) {
+        i_glinf(src, 0, src->xsize, y, vals);
+        for (x = 0; x < src->xsize; ++x) {
+          for (j = 0; j < outchan; ++j) {
+            work[j] = 0;
+            for (i = 0; i < ilimit; ++i) {
+              work[j] += coeff[i+inchan*j] * vals[x].channel[i];
+            }
+            if (i < inchan) {
+              work[j] += coeff[i+inchan*j];
+            }
+          }
+          for (j = 0; j < outchan; ++j) {
+            if (work[j] < 0)
+              vals[x].channel[j] = 0;
+            else if (work[j] >= 1)
+              vals[x].channel[j] = 1;
+            else
+              vals[x].channel[j] = work[j];
+          }
+        }
+        i_plinf(im, 0, src->xsize, y, vals);
+      }
+      myfree(vals);
+    }
   }
-  vals = mymalloc(sizeof(i_color) * src->xsize);
-  for (y = 0; y < src->ysize; ++y) {
-    i_glin(src, 0, src->xsize, y, vals);
-    for (x = 0; x < src->xsize; ++x) {
+  else {
+    int count;
+    int outcount;
+    int index;
+    i_color *colors;
+    i_palidx *vals;
+
+    if (im->channels != outchan || im->xsize != src->xsize 
+        || im->ysize != src->ysize
+        || i_maxcolors(im) < i_colorcount(src)) {
+      i_img_exorcise(im);
+      i_img_pal_new_low(im, src->xsize, src->ysize, outchan, 
+                        i_maxcolors(src));
+    }
+    /* just translate the color table */
+    count = i_colorcount(src);
+    outcount = i_colorcount(im);
+    /* color table allocated for image, so it must fit */
+    colors = mymalloc(count * sizeof(i_color)); /* check 04Jul05 tonyc */
+    i_getcolors(src, 0, colors, count);
+    for (index = 0; index < count; ++index) {
       for (j = 0; j < outchan; ++j) {
-       work[j] = 0;
-       for (i = 0; i < ilimit; ++i) {
-         work[j] += coeff[i+inchan*j] * vals[x].channel[i];
-       }
-       if (i < inchan) {
-         work[j] += coeff[i+inchan*j] * 255.9;
-       }
+        work[j] = 0;
+        for (i = 0; i < ilimit; ++i) {
+          work[j] += coeff[i+inchan*j] * colors[index].channel[i];
+        }
+        if (i < inchan) {
+          work[j] += coeff[i+inchan*j] * 255.9;
+        }
       }
       for (j = 0; j < outchan; ++j) {
-       if (work[j] < 0)
-         vals[x].channel[j] = 0;
-       else if (work[j] >= 256)
-         vals[x].channel[j] = 255;
-       else
-         vals[x].channel[j] = work[j];
+        if (work[j] < 0)
+          colors[index].channel[j] = 0;
+        else if (work[j] >= 255)
+          colors[index].channel[j] = 255;
+        else
+          colors[index].channel[j] = work[j];
       }
     }
-    i_plin(im, 0, src->xsize, y, vals);
+    if (count < outcount) {
+      i_setcolors(im, 0, colors, count);
+    }
+    else {
+      i_setcolors(im, 0, colors, outcount);
+      i_addcolors(im, colors, count-outcount);
+    }
+    /* and copy the indicies */
+    /* i_palidx is always unsigned char and will never be bigger than short
+       and since a line of 4-byte i_colors can fit then a line of i_palidx
+       will fit */
+    vals = mymalloc(sizeof(i_palidx) * im->xsize); /* checked 4jul05 tonyc */
+    for (y = 0; y < im->ysize; ++y) {
+      i_gpal(src, 0, im->xsize, y, vals);
+      i_ppal(im, 0, im->xsize, y, vals);
+    }
+    myfree(vals);
+    myfree(colors);
   }
-  myfree(vals);
+
   return 1;
 }