shithub: riscv

Download patch

ref: 73d4cf72277c2626b6a9e4c9597674a316e58591
parent: 6842f8712508262d0ea27692f13caa686419601e
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);
+}
+