File mgp-bilinear-zoom.diff of Package mgp

---
 image/zoom.c |  159 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 mgp.c        |    9 ++-
 mgp.man      |    2 
 3 files changed, 168 insertions(+), 2 deletions(-)

--- a/image/zoom.c
+++ b/image/zoom.c
@@ -11,6 +11,8 @@
 #include "copyright.h"
 #include "image.h"
 
+int smooth_scaling = 1;
+
 static unsigned int *buildIndex(width, zoom, rwidth)
      unsigned int  width;
      float         zoom;
@@ -36,6 +38,144 @@ static unsigned int *buildIndex(width, z
   return(index);
 }
 
+static Pixel rgb8_to_true(r, g, b)
+     byte r;
+     byte g;
+     byte b;
+{
+  return (Pixel)r << 16 | (Pixel)g << 8 | (Pixel)b;
+}
+
+/* simple bilinear resampling */
+static void resize_image(oimage, image)
+     Image *oimage;
+     Image *image;
+{
+  double cx, cy, xoff, yoff;
+  double xstep, ystep;
+  int maxx, maxy;
+  int x1, x2, y1, y2;
+  int i, j;
+  byte *line1, *line2;
+  byte *destptr;
+  unsigned int srclinelen;
+  unsigned int pixlen;
+  Pixel v[4];
+  unsigned int r, g, b;
+
+  maxx = oimage->width - 1;
+  maxy = oimage->height - 1;
+  pixlen= oimage->pixlen;
+  srclinelen= oimage->width * pixlen;
+  destptr = image->data;
+  cy = 0;
+  xstep = (double)oimage->width / (double)image->width;
+  ystep = (double)oimage->height / (double)image->height;
+  for (j = image->height; j > 0; j--) {
+    y1 = cy;
+    if (y1 >= maxy) {
+      y1 = y2 = maxy;
+      yoff = 0;
+    } else {
+      y2 = y1 + 1;
+      yoff = cy - y1;
+    }
+    line1 = oimage->data + srclinelen * y1;
+    line2 = oimage->data + srclinelen * y2;
+    cx = 0;
+    for (i = image->width; i > 0; i--) {
+      x1 = cx;
+      if (x1 >= maxx) {
+	x1 = x2 = maxx;
+	xoff = 0;
+      } else {
+	x2 = x1 + 1;
+	xoff = cx - x1;
+      }
+      v[0] = memToVal(line1 + pixlen * x1, pixlen);
+      v[1] = memToVal(line1 + pixlen * x2, pixlen);
+      v[2] = memToVal(line2 + pixlen * x1, pixlen);
+      v[3] = memToVal(line2 + pixlen * x2, pixlen);
+      r = (TRUE_RED(v[0]) * (1 - xoff) +
+	   TRUE_RED(v[1]) * xoff) * (1 - yoff) +
+	(TRUE_RED(v[2]) * (1 - xoff) +
+	 TRUE_RED(v[3]) * xoff) * yoff;
+      g = (TRUE_GREEN(v[0]) * (1 - xoff) +
+	   TRUE_GREEN(v[1]) * xoff) * (1 - yoff) +
+	(TRUE_GREEN(v[2]) * (1 - xoff) +
+	 TRUE_GREEN(v[3]) * xoff) * yoff;
+      b = (TRUE_BLUE(v[0]) * (1 - xoff) +
+	   TRUE_BLUE(v[1]) * xoff) * (1 - yoff) +
+	(TRUE_BLUE(v[2]) * (1 - xoff) +
+	 TRUE_BLUE(v[3]) * xoff) * yoff;
+      v[0] = rgb8_to_true(r, g, b);
+      valToMem(v[0], destptr, pixlen);
+      destptr += pixlen;
+      cx += xstep;
+    }
+    cy += ystep;
+  }
+}
+
+/* reduce the given image in integer factor */
+static Image *reduced_image(oimage, width, height)
+     Image *oimage;
+     unsigned int width;
+     unsigned int height;
+{
+  Image *dest;
+  byte *destptr;
+  unsigned int srclinelen;
+  unsigned int i, j;
+  unsigned int factorx = oimage->width / width;
+  unsigned int factory = oimage->height / height;
+  unsigned int pixlen= oimage->pixlen;
+
+  if (factorx < 1)
+    factorx = 1;
+  if (factory < 1)
+    factory = 1;
+
+  width = oimage->width / factorx;
+  if (oimage->width % factorx)
+    width++;
+  height = oimage->height / factory;
+  if (oimage->height % factory)
+    height++;
+
+  dest = newTrueImage(width, height);
+  destptr = dest->data;
+
+  srclinelen = oimage->width * oimage->pixlen;
+
+  for (j = 0; j < oimage->height; j += factory) {
+    for (i = 0; i < oimage->width; i += factorx) {
+      unsigned int r, g, b, div, x, y;
+      Pixel v;
+
+      r = g = b= 0;
+      div = 0;
+      for (y = 0; y < factory && j + y < oimage->height; y++) {
+	byte *src = oimage->data + srclinelen * (j + y);
+	for (x = 0; x < factorx && i + x < oimage->width; x++) {
+	  v = memToVal(src + pixlen * (i + x), pixlen);
+	  r += TRUE_RED(v);
+	  g += TRUE_GREEN(v);
+	  b += TRUE_BLUE(v);
+	  div++;
+	}
+      }
+      r /= div;
+      g /= div;
+      b /= div;
+      v = rgb8_to_true(r, g, b);
+      valToMem(v, destptr, pixlen);
+      destptr += pixlen;
+    }
+  }
+  return dest;
+}
+
 Image *zoom(oimage, xzoom, yzoom, verbose)
      Image        *oimage;
      float        xzoom, yzoom;
@@ -145,8 +285,25 @@ Image *zoom(oimage, xzoom, yzoom, verbos
     /* FALLTHRU */
 
   case ITRUE:
-    if (!RGBP(oimage))
+    if (!RGBP(oimage)) {
+      Image *tmpimage = NULL;
+      if (smooth_scaling &&
+	  (oimage->width / xwidth > 1 || oimage->height / ywidth > 1)) {
+	tmpimage = reduced_image(oimage, xwidth, ywidth);
+	if (tmpimage->width == xwidth && tmpimage->height == ywidth) {
+	  image = tmpimage;
+	  break;
+	}
+      }
       image= newTrueImage(xwidth, ywidth);
+      if (smooth_scaling) {
+	resize_image(tmpimage ? tmpimage : oimage, image);
+	if (tmpimage)
+	  freeImage(tmpimage);
+	break;
+      }
+    }
+
     pixlen= oimage->pixlen;
     destptr= image->data;
     srcline= oimage->data;
--- a/mgp.c
+++ b/mgp.c
@@ -113,6 +113,8 @@ static int wantreload __P((void));
 /*image*/
 extern char *expandPath __P((char *));
 
+extern int smooth_scaling; /* in image/zoom.c */
+
 #ifdef TTY_KEYINPUT
 static void
 susp(int sig)
@@ -261,7 +263,7 @@ main(argc, argv)
 	argv=tmp_argv;
 	argc=tmp_argc;
 
-#define ACCEPTOPTS	"Bd:vVob:c:eg:f:hlGp:qt:Q:PSUT:D:CORw:X:x:nF:E:"
+#define ACCEPTOPTS	"Bd:vVob:c:eg:f:hlGp:qt:Q:PsSUT:D:CORw:X:x:nF:E:"
 	while ((opt = getopt(argc, argv, ACCEPTOPTS)) != -1) {
 #undef ACCEPTOPTS
 		switch (opt) {
@@ -342,6 +344,10 @@ main(argc, argv)
 			parse_debug++;
 			break;
 
+		case 's':
+			smooth_scaling = !smooth_scaling;
+			break;
+
 		case 'S':
 			mgp_flag |= FL_NOFORK;
 			break;
@@ -750,6 +756,7 @@ mgp_usage(name)
 	fprintf(stderr, "\t-U: Do process directives that forks process\n\t    or allow to use non-ASCII filenames (unsecure mode)\n");
 	fprintf(stderr, "\t-T <timestampfile>: Update timestampfile on page refresh\n");
 	fprintf(stderr, "\t-P: print stderr from image conversion tools (by default it's discarded)\n");
+	fprintf(stderr, "\t-s: Toggle smooth image scaling\n");
 	fprintf(stderr, "\t-V: Be verbose\n");
 	fprintf(stderr, "\t-X <gsdevice>: ghostscript device to use\n");
 	fprintf(stderr, "\t--title <title>: Set window title\n");
--- a/mgp.man
+++ b/mgp.man
@@ -259,6 +259,8 @@ every time it updates the presentation w
 This option is useful for external process to understand when
 .Nm
 modifies the window.
+.It Fl s
+Toggle the smooth image rendering by bilinear interpolation.
 .It Fl V
 Be verbose.
 Generate debugging output to standard output.
openSUSE Build Service is sponsored by