about summary refs log tree commit diff
path: root/editor/pbmpscale.c
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2006-08-19 03:12:28 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2006-08-19 03:12:28 +0000
commit1fd361a1ea06e44286c213ca1f814f49306fdc43 (patch)
tree64c8c96cf54d8718847339a403e5e67b922e8c3f /editor/pbmpscale.c
downloadnetpbm-mirror-1fd361a1ea06e44286c213ca1f814f49306fdc43.tar.gz
netpbm-mirror-1fd361a1ea06e44286c213ca1f814f49306fdc43.tar.xz
netpbm-mirror-1fd361a1ea06e44286c213ca1f814f49306fdc43.zip
Create Subversion repository
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@1 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'editor/pbmpscale.c')
-rw-r--r--editor/pbmpscale.c199
1 files changed, 199 insertions, 0 deletions
diff --git a/editor/pbmpscale.c b/editor/pbmpscale.c
new file mode 100644
index 00000000..63f203ed
--- /dev/null
+++ b/editor/pbmpscale.c
@@ -0,0 +1,199 @@
+/* pbmpscale.c - pixel scaling with jagged edge smoothing.
+ * AJCD 13/8/90
+ */
+
+#include <stdio.h>
+#include "pbm.h"
+#include "mallocvar.h"
+
+/* prototypes */
+void nextrow_pscale ARGS((FILE *ifd, int row));
+int corner ARGS((int pat));
+
+/* input bitmap size and storage */
+int rows, columns, format ;
+bit *inrow[3] ;
+
+#define thisrow (1)
+
+/* compass directions from west clockwise */
+int xd_pscale[] = { -1, -1,  0,  1, 1, 1, 0, -1 } ;
+int yd_pscale[] = {  0, -1, -1, -1, 0, 1, 1,  1 } ;
+
+/* starting positions for corners */
+#define NE(f) ((f) & 3)
+#define SE(f) (((f) >> 2) & 3)
+#define SW(f) (((f) >> 4) & 3)
+#define NW(f) (((f) >> 6) & 3)
+
+typedef unsigned short sixteenbits ;
+
+/* list of corner patterns; bit 7 is current color, bits 0-6 are squares
+ * around (excluding square behind), going clockwise.
+ * The high byte of the patterns is a mask, which determines which bits are
+ * not ignored.
+ */
+
+sixteenbits patterns[] = { 0x0000, 0xd555,         /* no corner */
+                           0x0001, 0xffc1, 0xd514, /* normal corner */
+                           0x0002, 0xd554, 0xd515, /* reduced corners */
+                           0xbea2, 0xdfc0, 0xfd81,
+                           0xfd80, 0xdf80,
+                           0x0003, 0xbfa1, 0xfec2 /* reduced if > 1 */
+                           };
+
+/* search for corner patterns, return type of corner found:
+ *  0 = no corner,
+ *  1 = normal corner,
+ *  2 = reduced corner,
+ *  3 = reduced if cutoff > 1
+ */
+
+int corner(pat)
+     int pat;
+{
+   register int i, r=0;
+   for (i = 0; i < sizeof(patterns)/sizeof(sixteenbits); i++)
+      if (patterns[i] < 0x100)
+         r = patterns[i];
+      else if ((pat & (patterns[i] >> 8)) ==
+               (patterns[i] & (patterns[i] >> 8)))
+         return r;
+   return 0;
+}
+
+/* get a new row
+ */
+
+void nextrow_pscale(ifd, row)
+     FILE *ifd;
+     int row;
+{
+   bit *shuffle = inrow[0] ;
+   inrow[0] = inrow[1];
+   inrow[1] = inrow[2];
+   inrow[2] = shuffle ;
+   if (row < rows) {
+      if (shuffle == NULL)
+         inrow[2] = shuffle = pbm_allocrow(columns);
+      pbm_readpbmrow(ifd, inrow[2], columns, format) ;
+   } else inrow[2] = NULL; /* discard storage */
+
+}
+
+int
+main(argc, argv)
+     int argc;
+     char *argv[];
+{
+   FILE *ifd;
+   register bit *outrow;
+   register int row, col, i, k;
+   int scale, cutoff, ucutoff ;
+   unsigned char *flags;
+
+   pbm_init( &argc, argv );
+
+   if (argc < 2)
+      pm_usage("scale [pbmfile]");
+
+   scale = atoi(argv[1]);
+   if (scale < 1)
+      pm_perror("bad scale (< 1)");
+
+   if (argc == 3)
+      ifd = pm_openr(argv[2]);
+   else
+      ifd = stdin ;
+
+   inrow[0] = inrow[1] = inrow[2] = NULL;
+   pbm_readpbminit(ifd, &columns, &rows, &format) ;
+
+   outrow = pbm_allocrow(columns*scale) ;
+   MALLOCARRAY(flags, columns);
+   if (flags == NULL) 
+       pm_error("out of memory") ;
+
+   pbm_writepbminit(stdout, columns*scale, rows*scale, 0) ;
+
+   cutoff = scale / 2;
+   ucutoff = scale - 1 - cutoff;
+   nextrow_pscale(ifd, 0);
+   for (row = 0; row < rows; row++) {
+      nextrow_pscale(ifd, row+1);
+      for (col = 0; col < columns; col++) {
+         flags[col] = 0 ;
+         for (i = 0; i != 8; i += 2) {
+            int vec = inrow[thisrow][col] != PBM_WHITE;
+            for (k = 0; k < 7; k++) {
+               int x = col + xd_pscale[(k+i)&7] ;
+               int y = thisrow + yd_pscale[(k+i)&7] ;
+               vec <<= 1;
+               if (x >=0 && x < columns && inrow[y])
+                  vec |= (inrow[y][x] != PBM_WHITE) ;
+            }
+            flags[col] |= corner(vec)<<i ;
+         }
+      }
+      for (i = 0; i < scale; i++) {
+         bit *ptr = outrow ;
+         int zone = (i > ucutoff) - (i < cutoff) ;
+         int cut = (zone < 0) ? (cutoff - i) :
+                   (zone > 0) ? (i - ucutoff) : 0 ;
+
+         for (col = 0; col < columns; col++) {
+            int pix = inrow[thisrow][col] ;
+            int flag = flags[col] ;
+            int cutl, cutr ;
+
+            switch (zone) {
+            case -1:
+               switch (NW(flag)) {
+               case 0: cutl = 0; break;
+               case 1: cutl = cut; break;
+               case 2: cutl = cut ? cut-1 : 0; break;
+               case 3: cutl = (cut && cutoff > 1) ? cut-1 : cut; break;
+               default: cutl = 0;  /* Should never reach here */
+               }
+               switch (NE(flag)) {
+               case 0: cutr = 0; break;
+               case 1: cutr = cut; break;
+               case 2: cutr = cut ? cut-1 : 0; break;
+               case 3: cutr = (cut && cutoff > 1) ? cut-1 : cut; break;
+               default: cutr = 0;  /* Should never reach here */
+              }
+               break;
+            case 0:
+               cutl = cutr = 0;
+               break ;
+            case 1:
+               switch (SW(flag)) {
+               case 0: cutl = 0; break;
+               case 1: cutl = cut; break;
+               case 2: cutl = cut ? cut-1 : 0; break;
+               case 3: cutl = (cut && cutoff > 1) ? cut-1 : cut; break;
+               default: cutl = 0;  /* should never reach here */
+               }
+               switch (SE(flag)) {
+               case 0: cutr = 0; break;
+               case 1: cutr = cut; break;
+               case 2: cutr = cut ? cut-1 : 0; break;
+               case 3: cutr = (cut && cutoff > 1) ? cut-1 : cut; break;
+               default: cutr = 0;  /* should never reach here */
+               }
+               break;
+             default: cutl = 0; cutr = 0;  /* Should never reach here */
+            }
+            for (k = 0; k < cutl; k++) /* left part */
+               *ptr++ = !pix ;
+            for (k = 0; k < scale-cutl-cutr; k++)  /* centre part */
+               *ptr++ = pix ;
+            for (k = 0; k < cutr; k++) /* right part */
+               *ptr++ = !pix ;
+         }
+         pbm_writepbmrow(stdout, outrow, scale*columns, 0) ;
+      }
+   }
+   pm_close(ifd);
+   exit(0);
+}