]> git.imager.perl.org - imager.git/blobdiff - image.c
new samples
[imager.git] / image.c
diff --git a/image.c b/image.c
index d327fec1df3d5455aad852ccb5ea0f3057264030..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);
   
@@ -2131,6 +2074,13 @@ int i_free_gen_write_data(i_gen_write_data *info, int flush)
 
 
 
+/*
+=item i_test_format_probe(io_glue *data, int length)
+
+Check the beginning of the supplied file for a 'magic number'
+
+=cut
+*/
 
 
 char *
@@ -2143,33 +2093,53 @@ i_test_format_probe(io_glue *data, int length) {
     {"\xFF\xD8", "jpeg"},
     {"GIF87a", "gif"},
     {"GIF89a", "gif"},
+    {"MM\0*", "tiff"},
+    {"II*\0", "tiff"},
+    {"BM", "bmp"},
+    {"\x89PNG\x0d\x0a\x1a\x0a", "png"},
     {"P1", "pnm"},
     {"P2", "pnm"},
     {"P3", "pnm"},
     {"P4", "pnm"},
     {"P5", "pnm"},
     {"P6", "pnm"},
-    {"MM\0*", "tiff"},
-    {"II*\0", "tiff"},
-    {"BM", "bmp"},
-    {"\x89PNG\x0d\x0a\x1a\x0a", "png"}
   };
   unsigned int i;
-  char head[8];
+  char head[18];
   char *match = NULL;
+  ssize_t rc;
 
   io_glue_commit_types(data);
-  data->readcb(data, head, 8);
+  rc = data->readcb(data, head, 18);
+  if (rc == -1) return NULL;
+  data->seekcb(data, -rc, SEEK_CUR);
 
   for(i=0; i<sizeof(formats)/sizeof(formats[0]); i++) { 
-    int c = !strncmp(formats[i].magic, head, strlen(formats[i].magic));
+    int c;
+    ssize_t len = strlen(formats[i].magic);
+    if (rc<len) continue;
+    c = !strncmp(formats[i].magic, head, len);
     if (c) {
       match = formats[i].name;
       break;
     }
   }
 
-  data->seekcb(data, -8, SEEK_CUR);
+  /*
+    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) &&
+      tga_header_verify(head)) return "tga";
   return match;
 }