ref: 19cc5811228e1b06992b8dfe7a2ee26152ed529c
parent: f11c5c9ddcd47ce690210ad354c07f230c407e0e
author: cinap_lenrek <cinap_lenrek@centraldogma>
date: Sun Sep 4 15:17:30 EDT 2011
add resize (from richard miller) and rotate
--- /dev/null
+++ b/sys/src/cmd/resize.c
@@ -1,0 +1,152 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <memdraw.h>
+
+static void
+resample(Memimage *dst, Rectangle r, Memimage *src, Rectangle sr)
+{+ Point sp, dp;
+ Point _sp, qp;
+ Point ssize, dsize;
+ uchar *pdst0, *pdst, *psrc0, *psrc;
+ ulong s00, s01, s10, s11;
+ int tx, ty, bpp, bpl;
+
+ ssize = subpt(subpt(sr.max, sr.min), Pt(1,1));
+ dsize = subpt(subpt(r.max, r.min), Pt(1,1));
+ pdst0 = byteaddr(dst, r.min);
+ bpp = src->depth/8;
+ bpl = src->width*sizeof(int);
+
+ qp.x = (ssize.x<<12)/dsize.x;
+ qp.y = (ssize.y<<12)/dsize.y;
+ _sp.y = sr.min.y<<12;
+ for(dp.y=0; dp.y<=dsize.y; dp.y++){+ sp.y = _sp.y>>12;
+ ty = _sp.y&0xFFF;
+ pdst = pdst0;
+ sp.x = sr.min.x;
+ psrc0 = byteaddr(src, sp);
+ _sp.x = 0;
+ for(dp.x=0; dp.x<=dsize.x; dp.x++){+ sp.x = _sp.x>>12;
+ tx = _sp.x&0xFFF;
+ psrc = psrc0 + sp.x*bpp;
+ s00 = (0x1000-tx)*(0x1000-ty);
+ s01 = tx*(0x1000-ty);
+ s10 = (0x1000-tx)*ty;
+ s11 = tx*ty;
+ switch(bpp){+ case 4:
+ pdst[3] = (s11*psrc[bpl+bpp+3] +
+ s10*psrc[bpl+3] +
+ s01*psrc[bpp+3] +
+ s00*psrc[3]) >>24;
+ case 3:
+ pdst[2] = (s11*psrc[bpl+bpp+2] +
+ s10*psrc[bpl+2] +
+ s01*psrc[bpp+2] +
+ s00*psrc[2]) >>24;
+ pdst[1] = (s11*psrc[bpl+bpp+1] +
+ s10*psrc[bpl+1] +
+ s01*psrc[bpp+1] +
+ s00*psrc[1]) >>24;
+ case 1:
+ pdst[0] = (s11*psrc[bpl+bpp] +
+ s10*psrc[bpl] +
+ s01*psrc[bpp] +
+ s00*psrc[0]) >>24;
+ }
+ pdst += bpp;
+ _sp.x += qp.x;
+ }
+ pdst0 += dst->width*sizeof(int);
+ _sp.y += qp.y;
+ }
+}
+
+void
+usage(void)
+{+ sysfatal("Usage: %s [ -x width ] [ -y height ] [image]\n", argv0);+}
+
+void
+main(int argc, char **argv)
+{+ int fd, xsize, ysize;
+ Memimage *im, *nim;
+ ulong ochan, tchan;
+ char buf[12];
+
+ xsize = ysize = 0;
+ ARGBEGIN{+ case 'x':
+ xsize = atoi(EARGF(usage()));
+ break;
+ case 'y':
+ ysize = atoi(EARGF(usage()));
+ break;
+ default:
+ usage();
+ }ARGEND
+ fd = 0;
+ if(*argv){+ fd = open(*argv, OREAD);
+ if(fd < 0)
+ sysfatal("open: %r");+ }
+ memimageinit();
+ if((im = readmemimage(fd)) == nil)
+ sysfatal("readmemimage: %r");+ if(xsize || ysize){+ if(ysize == 0)
+ ysize = (xsize * Dy(im->r)) / Dx(im->r);
+ if(xsize == 0)
+ xsize = (ysize * Dx(im->r)) / Dy(im->r);
+ ochan = im->chan;
+ switch(ochan){+ default:
+ sysfatal("can't handle channel type %s", chantostr(buf, ochan));+ case GREY8:
+ case RGB24:
+ case RGBA32:
+ case ARGB32:
+ case XRGB32:
+ tchan = ochan;
+ break;
+ case CMAP8:
+ case RGB16:
+ case RGB15:
+ tchan = RGB24;
+ break;
+ case GREY1:
+ case GREY2:
+ case GREY4:
+ tchan = GREY8;
+ break;
+ }
+ if(tchan != ochan){+ if((nim = allocmemimage(im->r, tchan)) == nil)
+ sysfatal("allocimage: %r");+ memimagedraw(nim, nim->r, im, im->r.min, nil, ZP, S);
+ freememimage(im);
+ im = nim;
+ }
+ if((nim = allocmemimage(Rect(im->r.min.x, im->r.min.y, xsize, ysize), tchan)) == nil)
+ sysfatal("addocmemimage: %r");+ resample(nim, nim->r, im, im->r);
+ freememimage(im);
+ im = nim;
+ if(tchan != ochan){+ if((im = allocmemimage(nim->r, ochan)) == nil)
+ sysfatal("allocimage: %r");+ memimagedraw(im, im->r, nim, nim->r.min, nil, ZP, S);
+ freememimage(nim);
+ }
+ }
+ if(writememimage(1, im) < 0)
+ sysfatal("writememimage: %r");+ exits(0);
+}
--- /dev/null
+++ b/sys/src/cmd/rotate.c
@@ -1,0 +1,148 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <memdraw.h>
+
+Memimage*
+rot90(Memimage *m)
+{+ int line, bpp, x, y, dx, dy;
+ ulong chan;
+ uchar *s, *d;
+ Memimage *w;
+ char buf[12];
+
+ bpp = m->depth/8;
+ chan = m->chan;
+ switch(chan){+ default:
+ sysfatal("can't handle channel type %s", chantostr(buf, chan));+ case RGB15:
+ bpp = 2;
+ case CMAP8:
+ case GREY8:
+ case RGB16:
+ case RGB24:
+ case RGBA32:
+ case ARGB32:
+ case XRGB32:
+ break;
+ case GREY1:
+ case GREY2:
+ case GREY4:
+ bpp = 1;
+ if((w = allocmemimage(m->r, GREY8)) == nil)
+ sysfatal("allocmemimage: %r");+ memimagedraw(w, w->r, m, m->r.min, nil, ZP, S);
+ freememimage(m);
+ m = w;
+ break;
+ }
+
+ dx = Dx(m->r);
+ dy = Dy(m->r);
+ if((w = allocmemimage(Rect(m->r.min.x, m->r.min.y, dy, dx), m->chan)) == nil)
+ sysfatal("allocmemimage: %r");+ line = w->width*sizeof(ulong);
+ for(y=0; y<dy; y++){+ s = byteaddr(m, addpt(m->r.min, Pt(0, y)));
+ d = byteaddr(w, addpt(w->r.min, Pt(dy-y-1, 0)));
+ for(x=0; x<dx; x++){+ switch(bpp){+ case 4:
+ d[3] = s[3];
+ case 3:
+ d[2] = s[2];
+ case 2:
+ d[1] = s[1];
+ case 1:
+ d[0] = s[0];
+ }
+ s += bpp;
+ d += line;
+ }
+ }
+ freememimage(m);
+ if(w->chan != chan){+ if((m = allocmemimage(w->r, chan)) == nil)
+ sysfatal("allocmemimage: %r");+ memimagedraw(m, m->r, w, w->r.min, nil, ZP, S);
+ freememimage(w);
+ w = m;
+ }
+ return w;
+}
+
+Memimage*
+rot180(Memimage *m)
+{+ uchar *s, *d, *t;
+ int w, y, dy;
+
+ dy = Dy(m->r);
+ w = m->width * sizeof(ulong);
+ if((t = malloc(w)) == nil)
+ sysfatal("malloc: %r");+ for(y=0; y<dy/2; y++){+ s = byteaddr(m, addpt(m->r.min, Pt(0, y)));
+ d = byteaddr(m, addpt(m->r.min, Pt(0, dy-y-1)));
+ memmove(t, d, w);
+ memmove(d, s, w);
+ memmove(s, t, w);
+ }
+ free(t);
+ return m;
+}
+
+Memimage*
+rot270(Memimage *m)
+{+ return rot90(rot180(m));
+}
+
+void
+usage(void)
+{+ fprint(2, "usage: %s -r degree [ file ]\n", argv0);
+ exits("usage");+}
+
+void
+main(int argc, char *argv[])
+{+ Memimage *m;
+ int fd, r;
+
+ r = 0;
+ fd = 0;
+ ARGBEGIN {+ case 'r':
+ r = atoi(EARGF(usage()));
+ break;
+ default:
+ usage();
+ } ARGEND;
+ if(*argv){+ fd = open(*argv, OREAD);
+ if(fd < 0)
+ sysfatal("open: %r");+ }
+ memimageinit();
+ if((m = readmemimage(fd)) == nil)
+ sysfatal("readmemimage: %r");+ switch(r % 360){+ case 90:
+ m = rot90(m);
+ break;
+ case 180:
+ m = rot180(m);
+ break;
+ case 270:
+ m = rot270(m);
+ break;
+ }
+ if(writememimage(1, m) < 0)
+ sysfatal("writememimage: %r");+ exits(0);
+}
+
--
⑨