]> git.imager.perl.org - imager.git/blobdiff - image.c
- add samples/tk-photo.pl
[imager.git] / image.c
diff --git a/image.c b/image.c
index 244f128902da15e41beb5d76152b2055a1a322b1..eba037c5d0c1a1bcb55e8bff032b1cc6da519a7d 100644 (file)
--- a/image.c
+++ b/image.c
@@ -1,6 +1,5 @@
 #include "image.h"
 #include "imagei.h"
-#include "io.h"
 
 /*
 =head1 NAME
@@ -349,7 +348,25 @@ Re-new image reference
 
 i_img *
 i_img_empty_ch(i_img *im,int x,int y,int ch) {
+  int bytes;
+
   mm_log((1,"i_img_empty_ch(*im %p, x %d, y %d, ch %d)\n", im, x, y, ch));
+
+  if (x < 1 || y < 1) {
+    i_push_error(0, "Image sizes must be positive");
+    return NULL;
+  }
+  if (ch < 1 || ch > MAXCHANNELS) {
+    i_push_errorf(0, "channels must be between 1 and %d", MAXCHANNELS);
+    return NULL;
+  }
+  /* check this multiplication doesn't overflow */
+  bytes = x*y*ch;
+  if (bytes / y / ch != x) {
+    i_push_errorf(0, "integer overflow calculating image allocation");
+    return NULL;
+  }
+
   if (im == NULL)
     if ( (im=mymalloc(sizeof(i_img))) == NULL)
       m_fatal(2,"malloc() error\n");
@@ -360,8 +377,9 @@ i_img_empty_ch(i_img *im,int x,int y,int ch) {
   im->ysize    = y;
   im->channels = ch;
   im->ch_mask  = MAXINT;
-  im->bytes=x*y*im->channels;
-  if ( (im->idata=mymalloc(im->bytes)) == NULL) m_fatal(2,"malloc() error\n"); 
+  im->bytes=bytes;
+  if ( (im->idata=mymalloc(im->bytes)) == NULL) 
+    m_fatal(2,"malloc() error\n"); 
   memset(im->idata,0,(size_t)im->bytes);
   
   im->ext_data = NULL;
@@ -649,9 +667,10 @@ i_copy(i_img *im, i_img *src) {
 
 
 /*
-=item i_rubthru(im, src, tx, ty)
+=item i_rubthru(im, src, tx, ty, src_minx, src_miny, src_maxx, src_maxy )
 
-Takes the image I<src> and applies it at an original (I<tx>,I<ty>) in I<im>.
+Takes the sub image I<src[src_minx, src_maxx)[src_miny, src_maxy)> and
+overlays it at (I<tx>,I<ty>) on the image object.
 
 The alpha channel of each pixel in I<src> is used to control how much
 the existing colour in I<im> is replaced, if it is 255 then the colour
@@ -662,14 +681,17 @@ unmodified.
 */
 
 int
-i_rubthru(i_img *im,i_img *src,int tx,int ty) {
+i_rubthru(i_img *im, i_img *src, int tx, int ty, int src_minx, int src_miny,
+         int src_maxx, int src_maxy) {
   int x, y, ttx, tty;
   int chancount;
   int chans[3];
   int alphachan;
   int ch;
 
-  mm_log((1,"i_rubthru(im %p, src %p, tx %d, ty %d)\n", im, src, tx, ty));
+  mm_log((1,"i_rubthru(im %p, src %p, tx %d, ty %d, src_minx %d, "
+         "src_miny %d, src_maxx %d, src_maxy %d)\n",
+         im, src, tx, ty, src_minx, src_miny, src_maxx, src_maxy));
   i_clear_error();
 
   if (im->channels == 3 && src->channels == 4) {
@@ -697,11 +719,10 @@ i_rubthru(i_img *im,i_img *src,int tx,int ty) {
        changed in a similar fashion - TC */
     int alpha;
     i_color pv, orig, dest;
-    ttx = tx;
-    for(x=0; x<src->xsize; x++) {
-      tty=ty;
-      for(y=0;y<src->ysize;y++) {
-        /* fprintf(stderr,"reading (%d,%d) writing (%d,%d).\n",x,y,ttx,tty); */
+    tty = ty;
+    for(y = src_miny; y < src_maxy; y++) {
+      ttx = tx;
+      for(x = src_minx; x < src_maxx; x++) {
         i_gpix(src, x,   y,   &pv);
         i_gpix(im,  ttx, tty, &orig);
         alpha = pv.channel[alphachan];
@@ -710,31 +731,30 @@ i_rubthru(i_img *im,i_img *src,int tx,int ty) {
                               + (255 - alpha) * orig.channel[ch])/255;
         }
         i_ppix(im, ttx, tty, &dest);
-        tty++;
+       ttx++;
       }
-      ttx++;
+      tty++;
     }
   }
   else {
     double alpha;
     i_fcolor pv, orig, dest;
 
-    ttx = tx;
-    for(x=0; x<src->xsize; x++) {
-      tty=ty;
-      for(y=0;y<src->ysize;y++) {
-        /* fprintf(stderr,"reading (%d,%d) writing (%d,%d).\n",x,y,ttx,tty); */
+    tty = ty;
+    for(y = src_miny; y < src_maxy; y++) {
+      ttx = tx;
+      for(x = src_minx; x < src_maxx; x++) {
         i_gpixf(src, x,   y,   &pv);
         i_gpixf(im,  ttx, tty, &orig);
         alpha = pv.channel[alphachan];
         for (ch = 0; ch < chancount; ++ch) {
           dest.channel[ch] = alpha * pv.channel[chans[ch]]
-                              + (1 - alpha) * orig.channel[ch];
+           + (1 - alpha) * orig.channel[ch];
         }
         i_ppixf(im, ttx, tty, &dest);
-        tty++;
+        ttx++;
       }
-      ttx++;
+      tty++;
     }
   }
 
@@ -868,98 +888,6 @@ Lanczos(float x) {
 }
 
 
-
-
-
-
-
-
-
-i_img*
-i_scaleaxis_3ch_8bit(i_img *im, int size, int Axis) {
-
-  int i, j;
-  int iEnd, jEnd;
-
-  int hsize, vsize;
-
-  short psave;
-  unsigned long *pixels;
-  i_color val;
-  i_img *new_img;
-
-  mm_log((1,"i_scaleaxis_3ch_8bit(im %p, size %d,Axis %d)\n",im, size, Axis));
-
-  if (Axis == XAXIS) {
-    hsize = size;
-    vsize = im->ysize;
-    
-    jEnd = hsize;
-    iEnd = vsize;
-    pixels = mymalloc(sizeof(*pixels) * im->xsize);
-  } else {
-    hsize = im->xsize;
-    vsize = size;
-    
-    jEnd = vsize;
-    iEnd = hsize;
-    pixels = mymalloc(sizeof(*pixels) * im->ysize);
-  }
-  
-  new_img = i_img_empty_ch(NULL, hsize, vsize, im->channels);
-
-
-  if (Axis == XAXIS) {
-    
-    for (i=0; i<iEnd; i++) {
-      int end = im->xsize;
-
-      for(j=0; j<im->xsize; j++) {
-       i_gpix(im, j, i, &val);
-       pixels[j] = (val.rgba.r<<24) | (val.rgba.g<<16) | (val.rgba.b<<8) | (val.rgba.a<<0);
-      }
-      
-      /* printf("jEnd = %d, end = %d\n", jEnd, end); */
-      while ((end+1)/2>=size) {
-       int lend = end/2;
-       end = (end+1) / 2;
-       
-       for(j=0; j<lend; j++) {
-         unsigned long a = pixels[2*j];
-         unsigned long b = pixels[2*j+1];
-         pixels[j] = (((a ^ b) & 0xfefefefeUL) >> 1) + (a & b);
-       }
-       if (end>lend) {
-         pixels[j] = pixels[2*j];
-         j++;
-       }
-      }
-
-      printf("end = %d size = %d\n", end, size);
-
-      /* Replace this with Bresenham later */
-      for(j=0; j<size; j++) {
-       float f = i;
-         /*    if ((i*size)/end <)  */
-         unsigned long t = pixels[j];
-       val.rgba.r = (t >> 24) & 0xff;
-       val.rgba.g = (t >> 16) & 0xff;
-       val.rgba.b = (t >> 8) & 0xff;
-       val.rgba.a = t & 0xff;
-       i_ppix(new_img, j, i, &val);
-      }
-    }
-  }
-  
-  return new_img;
-}
-
-
-
-
-
-
-
 /*
 =item i_scaleaxis(im, value, axis)
 
@@ -985,9 +913,11 @@ i_scaleaxis(i_img *im, float Value, int Axis) {
 
 
   if (Axis == XAXIS) {
-    return i_scaleaxis_3ch_8bit(im, (int)(0.5+im->xsize*Value), Axis);
-
     hsize = (int)(0.5 + im->xsize * Value);
+    if (hsize < 1) {
+      hsize = 1;
+      Value = 1.0 / im->xsize;
+    }
     vsize = im->ysize;
     
     jEnd = hsize;
@@ -996,6 +926,11 @@ i_scaleaxis(i_img *im, float Value, int Axis) {
     hsize = im->xsize;
     vsize = (int)(0.5 + im->ysize * Value);
 
+    if (vsize < 1) {
+      vsize = 1;
+      Value = 1.0 / im->ysize;
+    }
+
     jEnd = vsize;
     iEnd = hsize;
   }
@@ -1113,7 +1048,15 @@ i_scale_nn(i_img *im, float scx, float scy) {
   mm_log((1,"i_scale_nn(im 0x%x,scx %.2f,scy %.2f)\n",im,scx,scy));
 
   nxsize = (int) ((float) im->xsize * scx);
+  if (nxsize < 1) {
+    nxsize = 1;
+    scx = 1 / im->xsize;
+  }
   nysize = (int) ((float) im->ysize * scy);
+  if (nysize < 1) {
+    nysize = 1;
+    scy = 1 / im->ysize;
+  }
     
   new_img=i_img_empty_ch(NULL,nxsize,nysize,im->channels);
   
@@ -2134,14 +2077,7 @@ int i_free_gen_write_data(i_gen_write_data *info, int flush)
 /*
 =item i_test_format_probe(io_glue *data, int length)
 
-Cleans up the write buffer.
-
-Will flush any left-over data if I<flush> is non-zero.
-
-Returns non-zero if flush is zero or if info->cb() returns non-zero.
-
-Return zero only if flush is non-zero and info->cb() returns zero.
-ie. if it fails.
+Check the beginning of the supplied file for a 'magic number'
 
 =cut
 */
@@ -2189,7 +2125,17 @@ i_test_format_probe(io_glue *data, int length) {
     }
   }
 
-
+  /*
+    if (match && !strcmp(match, "jpeg")) {
+    unsigned int x0, x1;
+    rc = data->readcb(data, head, 18);
+    if (rc == -1) return NULL;
+    x0 = (unsigned char)head[0];
+    x1 = (unsigned char)head[1];
+    data->seekcb(data, -rc, SEEK_CUR);
+    printf("Jpeg reread: %x %x\n", x0, x1);
+    }
+  */
 
   if (!match && 
       (rc == 18) &&