]> git.imager.perl.org - imager.git/blobdiff - image.c
use the font's first character map if we don't find a unicode map (FT1)
[imager.git] / image.c
diff --git a/image.c b/image.c
index 8b5bf760c4ab0d0496f5cc34a2438e7477466eb2..8bad545848dd8e50e406154007b5b97570762419 100644 (file)
--- a/image.c
+++ b/image.c
@@ -26,7 +26,7 @@ color objects for Imager.
 
 Some of these functions are internal.
 
-=over 4
+=over
 
 =cut
 */
@@ -202,7 +202,7 @@ static i_img IIM_base_8bit_direct =
 {
   0, /* channels set */
   0, 0, 0, /* xsize, ysize, bytes */
-  ~0, /* ch_mask */
+  ~0U, /* ch_mask */
   i_8_bits, /* bits */
   i_direct_type, /* type */
   0, /* virtual */
@@ -409,7 +409,7 @@ Destroy image and free data via exorcise.
 
 void
 i_img_destroy(i_img *im) {
-  mm_log((1,"i_img_destroy(im* 0x%x)\n",im));
+  mm_log((1,"i_img_destroy(im %p)\n",im));
   i_img_exorcise(im);
   if (im) { myfree(im); }
 }
@@ -647,9 +647,16 @@ i_copy(i_img *im, i_img *src) {
       myfree(pv);
     }
     else {
-      /* currently the only other depth is 16 */
       i_fcolor *pv;
-      i_img_16_new_low(im, x1, y1, src->channels);
+      if (src->bits == i_16_bits)
+       i_img_16_new_low(im, x1, y1, src->channels);
+      else if (src->bits == i_double_bits)
+       i_img_double_new_low(im, x1, y1, src->channels);
+      else {
+       fprintf(stderr, "i_copy(): Unknown image bit size %d\n", src->bits);
+       return; /* I dunno */
+      }
+
       pv = mymalloc(sizeof(i_fcolor) * x1);
       for (y = 0; y < y1; ++y) {
         i_glinf(src, 0, x1, y, pv);
@@ -916,71 +923,84 @@ i_scaleaxis(i_img *im, float Value, int Axis) {
   int hsize, vsize, i, j, k, l, lMax, iEnd, jEnd;
   int LanczosWidthFactor;
   float *l0, *l1, OldLocation;
-  int T, TempJump1, TempJump2;
+  int T; 
+  float t;
   float F, PictureValue[MAXCHANNELS];
   short psave;
   i_color val,val1,val2;
   i_img *new_img;
 
-  mm_log((1,"i_scaleaxis(im 0x%x,Value %.2f,Axis %d)\n",im,Value,Axis));
+  mm_log((1,"i_scaleaxis(im %p,Value %.2f,Axis %d)\n",im,Value,Axis));
 
   if (Axis == XAXIS) {
-    hsize = (int) ((float) im->xsize * Value);
+    hsize = (int)(0.5 + im->xsize * Value);
     vsize = im->ysize;
     
     jEnd = hsize;
     iEnd = vsize;
-    
-    TempJump1 = (hsize - 1) * 3;
-    TempJump2 = hsize * (vsize - 1) * 3 + TempJump1;
   } else {
     hsize = im->xsize;
-    vsize = (int) ((float) im->ysize * Value);
-    
+    vsize = (int)(0.5 + im->ysize * Value);
+
     jEnd = vsize;
     iEnd = hsize;
-    
-    TempJump1 = 0;
-    TempJump2 = 0;
   }
   
-  new_img=i_img_empty_ch(NULL,hsize,vsize,im->channels);
-  
-  if (Value >=1) LanczosWidthFactor = 1;
-  else LanczosWidthFactor = (int) (1.0/Value);
+  new_img = i_img_empty_ch(NULL, hsize, vsize, im->channels);
   
+  /* 1.4 is a magic number, setting it to 2 will cause rather blurred images */
+  LanczosWidthFactor = (Value >= 1) ? 1 : (int) (1.4/Value); 
   lMax = LanczosWidthFactor << 1;
   
-  l0 = (float *) mymalloc(lMax * sizeof(float));
-  l1 = (float *) mymalloc(lMax * sizeof(float));
+  l0 = mymalloc(lMax * sizeof(float));
+  l1 = mymalloc(lMax * sizeof(float));
   
   for (j=0; j<jEnd; j++) {
     OldLocation = ((float) j) / Value;
     T = (int) (OldLocation);
     F = OldLocation - (float) T;
     
-    for (l = 0; l < lMax; l++) {
+    for (l = 0; l<lMax; l++) {
       l0[lMax-l-1] = Lanczos(((float) (lMax-l-1) + F) / (float) LanczosWidthFactor);
-      l1[l] = Lanczos(((float) (l + 1) - F) / (float) LanczosWidthFactor);
+      l1[l]        = Lanczos(((float) (l+1)      - F) / (float) LanczosWidthFactor);
     }
     
-    if (Axis== XAXIS) {
+    /* Make sure filter is normalized */
+    t = 0.0;
+    for(l=0; l<lMax; l++) {
+      t+=l0[l];
+      t+=l1[l];
+    }
+    t /= (float)LanczosWidthFactor;
+    
+    for(l=0; l<lMax; l++) {
+      l0[l] /= t;
+      l1[l] /= t;
+    }
+
+    if (Axis == XAXIS) {
       
       for (i=0; i<iEnd; i++) {
        for (k=0; k<im->channels; k++) PictureValue[k] = 0.0;
-       for (l=0; l < lMax; l++) {
-         i_gpix(im,T+l+1, i, &val1);
-         i_gpix(im,T-lMax+l+1, i, &val2);
+       for (l=0; l<lMax; l++) {
+         int mx = T-lMax+l+1;
+         int Mx = T+l+1;
+         mx = (mx < 0) ? 0 : mx;
+         Mx = (Mx >= im->xsize) ? im->xsize-1 : Mx;
+         
+         i_gpix(im, Mx, i, &val1);
+         i_gpix(im, mx, i, &val2);
+         
          for (k=0; k<im->channels; k++) {
-           PictureValue[k] += l1[l] * val1.channel[k];
+           PictureValue[k] += l1[l]        * val1.channel[k];
            PictureValue[k] += l0[lMax-l-1] * val2.channel[k];
          }
        }
        for(k=0;k<im->channels;k++) {
-         psave = (short)( PictureValue[k] / LanczosWidthFactor);
+         psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor));
          val.channel[k]=minmax(0,255,psave);
        }
-       i_ppix(new_img,j,i,&val);
+       i_ppix(new_img, j, i, &val);
       }
       
     } else {
@@ -988,18 +1008,23 @@ i_scaleaxis(i_img *im, float Value, int Axis) {
       for (i=0; i<iEnd; i++) {
        for (k=0; k<im->channels; k++) PictureValue[k] = 0.0;
        for (l=0; l < lMax; l++) {
-         i_gpix(im,i, T+l+1, &val1);
-         i_gpix(im,i, T-lMax+l+1, &val2);
+         int mx = T-lMax+l+1;
+         int Mx = T+l+1;
+         mx = (mx < 0) ? 0 : mx;
+         Mx = (Mx >= im->ysize) ? im->ysize-1 : Mx;
+
+         i_gpix(im, i, Mx, &val1);
+         i_gpix(im, i, mx, &val2);
          for (k=0; k<im->channels; k++) {
-           PictureValue[k] += l1[l] * val1.channel[k];
+           PictureValue[k] += l1[l]        * val1.channel[k];
            PictureValue[k] += l0[lMax-l-1] * val2.channel[k]; 
          }
        }
        for (k=0; k<im->channels; k++) {
-         psave = (short)( PictureValue[k] / LanczosWidthFactor);
-         val.channel[k]=minmax(0,255,psave);
+         psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor));
+         val.channel[k] = minmax(0, 255, psave);
        }
-       i_ppix(new_img,i,j,&val);
+       i_ppix(new_img, i, j, &val);
       }
       
     }
@@ -1007,7 +1032,7 @@ i_scaleaxis(i_img *im, float Value, int Axis) {
   myfree(l0);
   myfree(l1);
 
-  mm_log((1,"(0x%x) <- i_scaleaxis\n",new_img));
+  mm_log((1,"(%p) <- i_scaleaxis\n", new_img));
 
   return new_img;
 }
@@ -1063,9 +1088,12 @@ i_img *i_sametype(i_img *src, int xsize, int ysize) {
     if (src->bits == 8) {
       return i_img_empty_ch(NULL, xsize, ysize, src->channels);
     }
-    else if (src->bits == 16) {
+    else if (src->bits == i_16_bits) {
       return i_img_16_new(xsize, ysize, src->channels);
     }
+    else if (src->bits == i_double_bits) {
+      return i_img_double_new(xsize, ysize, src->channels);
+    }
     else {
       i_push_error(0, "Unknown image bits");
       return NULL;
@@ -1282,6 +1310,7 @@ Returns 0 if the pixel could be set, -1 otherwise.
 
 =cut
 */
+static
 int
 i_ppix_d(i_img *im, int x, int y, i_color *val) {
   int ch;
@@ -1307,14 +1336,16 @@ Returns 0 if the pixel could be set, -1 otherwise.
 
 =cut
 */
+static
 int 
 i_gpix_d(i_img *im, int x, int y, i_color *val) {
   int ch;
   if (x>-1 && x<im->xsize && y>-1 && y<im->ysize) {
     for(ch=0;ch<im->channels;ch++) 
-       val->channel[ch]=im->idata[(x+y*im->xsize)*im->channels+ch];
+      val->channel[ch]=im->idata[(x+y*im->xsize)*im->channels+ch];
     return 0;
   }
+  for(ch=0;ch<im->channels;ch++) val->channel[ch] = 0;
   return -1; /* error was cliped */
 }
 
@@ -1334,6 +1365,7 @@ Returns the number of pixels copied (eg. if r, l or y is out of range)
 
 =cut
 */
+static
 int
 i_glin_d(i_img *im, int l, int r, int y, i_color *vals) {
   int ch, count, i;
@@ -1370,6 +1402,7 @@ Returns the number of pixels copied (eg. if r, l or y is out of range)
 
 =cut
 */
+static
 int
 i_plin_d(i_img *im, int l, int r, int y, i_color *vals) {
   int ch, count, i;
@@ -1398,6 +1431,7 @@ i_plin_d(i_img *im, int l, int r, int y, i_color *vals) {
 
 =cut
 */
+static
 int
 i_ppixf_d(i_img *im, int x, int y, i_fcolor *val) {
   int ch;
@@ -1418,6 +1452,7 @@ i_ppixf_d(i_img *im, int x, int y, i_fcolor *val) {
 
 =cut
 */
+static
 int
 i_gpixf_d(i_img *im, int x, int y, i_fcolor *val) {
   int ch;
@@ -1447,6 +1482,7 @@ Returns the number of pixels copied (eg. if r, l or y is out of range)
 
 =cut
 */
+static
 int
 i_glinf_d(i_img *im, int l, int r, int y, i_fcolor *vals) {
   int ch, count, i;
@@ -1483,6 +1519,7 @@ Returns the number of pixels copied (eg. if r, l or y is out of range)
 
 =cut
 */
+static
 int
 i_plinf_d(i_img *im, int l, int r, int y, i_fcolor *vals) {
   int ch, count, i;
@@ -1517,7 +1554,9 @@ Returns the number of samples read (which should be (r-l) * bits_set(chan_mask)
 
 =cut
 */
-int i_gsamp_d(i_img *im, int l, int r, int y, i_sample_t *samps, 
+static
+int
+i_gsamp_d(i_img *im, int l, int r, int y, i_sample_t *samps, 
               int *chans, int chan_count) {
   int ch, count, i, w;
   unsigned char *data;
@@ -1573,7 +1612,9 @@ Returns the number of samples read (which should be (r-l) * bits_set(chan_mask)
 
 =cut
 */
-int i_gsampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps, 
+static
+int
+i_gsampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps, 
                int *chans, int chan_count) {
   int ch, count, i, w;
   unsigned char *data;
@@ -2018,6 +2059,12 @@ int free_gen_write_data(i_gen_write_data *info, int flush)
 /*
 =back
 
+=head1 AUTHOR
+
+Arnar M. Hrafnkelsson <addi@umich.edu>
+
+Tony Cook <tony@develop-help.com>
+
 =head1 SEE ALSO
 
 L<Imager>, L<gif.c>