#include <u.h>#include <libc.h>#include <draw.h>#include <memdraw.h>#define STB_IMAGE_RESIZE_IMPLEMENTATION#define _MSC_VER#define __plan9__static void *STBIR_MALLOC(int x, void *){ return malloc(x);}static voidSTBIR_FREE(void *p, void *){ free(p);}#define STBIR_MALLOC STBIR_MALLOC#define STBIR_FREE STBIR_FREE#define STBIR_ASSERT(x) assert(x)#define NULL niltypedef uintptr size_t;#include "stb_image_resize.h" enum { Stpixels,}; static char *filters[] = { [STBIR_FILTER_BOX] = "box", [STBIR_FILTER_TRIANGLE] = "triangle", [STBIR_FILTER_CUBICBSPLINE] = "cubicbspline", [STBIR_FILTER_CATMULLROM] = "catmullrom", [STBIR_FILTER_MITCHELL] = "mitchell",}; static char *cspaces[] = { [STBIR_COLORSPACE_LINEAR] = "linear", [STBIR_COLORSPACE_SRGB] = "srgb",}; static voidusage(void){ fprint(2, "usage: %s [-P] [-x size] [-y size] [-r x0,y0,x1,y1] [-f filter] [-c colorspace] [file]\n", argv0); exits("usage");} voidmain(int argc, char **argv){ char *flts, *s, *csps, *e; int n, bp, to, stmode; int alphai, flags, fd; int w, h, ow, oh, iw, ih; int wp, hp, f, c; Memimage *a, *b; u8int *in, *out; double st[4]; ow = oh = 0; wp = hp = 0; alphai = STBIR_ALPHA_CHANNEL_NONE; flags = STBIR_FLAG_ALPHA_PREMULTIPLIED; flts = filters[STBIR_FILTER_MITCHELL]; csps = cspaces[STBIR_COLORSPACE_LINEAR]; st[0] = 0; st[1] = 0; st[2] = 1; st[3] = 1; stmode = -1; ARGBEGIN{ case 'x': s = EARGF(usage()); wp = (ow = atoi(s)) > 0 && s[strlen(s)-1] == '%'; break; case 'y': s = EARGF(usage()); hp = (oh = atoi(s)) > 0 && s[strlen(s)-1] == '%'; break; case 'f': flts = EARGF(usage()); break; case 'c': csps = EARGF(usage()); break; case 'P': flags &= ~STBIR_FLAG_ALPHA_PREMULTIPLIED; break; case 'r': s = EARGF(usage()); stmode = Stpixels; e = s; for(n = 0; n < 4; n++, e++){ st[n] = strtod(e, &e); if(*e != ',') break; } if(n != 3 || st[2] <= st[0] || st[3] <= st[1]) sysfatal("invalid rect %s", s); break; default: usage(); }ARGEND if(argc > 1) usage(); for(f = 0; f < nelem(filters) && (filters[f] == nil || strcmp(flts, filters[f]) != 0); f++); if(f >= nelem(filters)) sysfatal("invalid filter %s", flts); for(c = 0; c < nelem(cspaces) && strcmp(csps, cspaces[c]) != 0; c++); if(c >= nelem(cspaces)) sysfatal("invalid colorspace %s", csps); fd = 0; if(argc == 1 && (fd = open(argv[0], OREAD)) < 0) sysfatal("%r"); if(wp && oh == 0){ oh = ow; hp = 1; }else if(hp && ow == 0){ ow = oh; wp = 1; } memimageinit(); if((a = readmemimage(fd)) == nil) sysfatal("memory"); w = Dx(a->r); h = Dy(a->r); if(stmode == Stpixels){ iw = st[2]-st[0]; ih = st[3]-st[1]; st[0] /= (double)w; st[1] /= (double)h; st[2] /= (double)w; st[3] /= (double)h; }else{ iw = w; ih = h; } if(ow == 0 && oh == 0){ ow = iw; oh = ih; } if(wp) ow = iw*ow/100.0; if(hp) oh = ih*oh/100.0; if(oh == 0) oh = ow*ih/iw; if(ow == 0) ow = oh*iw/ih; if(ow < 1 || oh < 1) sysfatal("invalid size: %dx%d", ow, oh); bp = 0;again: switch(a->chan){ case GREY8: bp = 1; break; case RGB24: bp = 3; break; case RGBA32: bp = 4; alphai = 3; break; case ARGB32: case XRGB32: bp = 4; alphai = 0; break; case GREY1: case GREY2: case GREY4: to = GREY8; goto convert; case CMAP8: case RGB15: case RGB16: to = RGB24; goto convert; case BGR24: to = RGB24; goto convert; case ABGR32: to = ARGB32; goto convert; case XBGR32: to = XRGB32;convert: if((b = allocmemimage(a->r, to)) == nil) sysfatal("memory"); memimagedraw(b, a->r, a, ZP, nil, ZP, S); freememimage(a); a = b; goto again; default: sysfatal("invalid chan %#lux", a->chan); } n = w*h*bp; if((in = malloc(w*h*bp)) == nil) sysfatal("%r"); if(unloadmemimage(a, a->r, in, n) < 0) sysfatal("%r"); if((out = malloc(ow*oh*bp)) == nil) sysfatal("memory"); stbir_resize_region( in, w, h, w*bp, out, ow, oh, ow*bp, STBIR_TYPE_UINT8, bp, alphai, flags, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, f, f, c, nil, st[0], st[1], st[2], st[3] ); free(in); if((b = allocmemimage(Rect(0,0,ow,oh), a->chan)) == nil) sysfatal("%r"); loadmemimage(b, b->r, out, ow*oh*bp); writememimage(1, b); exits(nil);}
#include <u.h>
#include <libc.h>
#include <draw.h>
#include <memdraw.h>
#define STB_IMAGE_RESIZE_IMPLEMENTATION
#define _MSC_VER
#define __plan9__
static void *
STBIR_MALLOC(int x, void *)
{
return malloc(x);
}
static void
STBIR_FREE(void *p, void *)
{
free(p);
}
#define STBIR_MALLOC STBIR_MALLOC
#define STBIR_FREE STBIR_FREE
#define STBIR_ASSERT(x) assert(x)
#define NULL nil
typedef uintptr size_t;
#include "stb_image_resize.h"
enum {
Stpixels,
};
static char *filters[] = {
[STBIR_FILTER_BOX] = "box",
[STBIR_FILTER_TRIANGLE] = "triangle",
[STBIR_FILTER_CUBICBSPLINE] = "cubicbspline",
[STBIR_FILTER_CATMULLROM] = "catmullrom",
[STBIR_FILTER_MITCHELL] = "mitchell",
};
static char *cspaces[] = {
[STBIR_COLORSPACE_LINEAR] = "linear",
[STBIR_COLORSPACE_SRGB] = "srgb",
};
static void
usage(void)
{
fprint(2, "usage: %s [-P] [-x size] [-y size] [-r x0,y0,x1,y1] [-f filter] [-c colorspace] [file]\n", argv0);
exits("usage");
}
void
main(int argc, char **argv)
{
char *flts, *s, *csps, *e;
int n, bp, to, stmode;
int alphai, flags, fd;
int w, h, ow, oh, iw, ih;
int wp, hp, f, c;
Memimage *a, *b;
u8int *in, *out;
double st[4];
ow = oh = 0;
wp = hp = 0;
alphai = STBIR_ALPHA_CHANNEL_NONE;
flags = STBIR_FLAG_ALPHA_PREMULTIPLIED;
flts = filters[STBIR_FILTER_MITCHELL];
csps = cspaces[STBIR_COLORSPACE_LINEAR];
st[0] = 0;
st[1] = 0;
st[2] = 1;
st[3] = 1;
stmode = -1;
ARGBEGIN{
case 'x':
s = EARGF(usage());
wp = (ow = atoi(s)) > 0 && s[strlen(s)-1] == '%';
break;
case 'y':
s = EARGF(usage());
hp = (oh = atoi(s)) > 0 && s[strlen(s)-1] == '%';
break;
case 'f':
flts = EARGF(usage());
break;
case 'c':
csps = EARGF(usage());
break;
case 'P':
flags &= ~STBIR_FLAG_ALPHA_PREMULTIPLIED;
break;
case 'r':
s = EARGF(usage());
stmode = Stpixels;
e = s;
for(n = 0; n < 4; n++, e++){
st[n] = strtod(e, &e);
if(*e != ',')
break;
}
if(n != 3 || st[2] <= st[0] || st[3] <= st[1])
sysfatal("invalid rect %s", s);
break;
default:
usage();
}ARGEND
if(argc > 1)
usage();
for(f = 0; f < nelem(filters) && (filters[f] == nil || strcmp(flts, filters[f]) != 0); f++);
if(f >= nelem(filters))
sysfatal("invalid filter %s", flts);
for(c = 0; c < nelem(cspaces) && strcmp(csps, cspaces[c]) != 0; c++);
if(c >= nelem(cspaces))
sysfatal("invalid colorspace %s", csps);
fd = 0;
if(argc == 1 && (fd = open(argv[0], OREAD)) < 0)
sysfatal("%r");
if(wp && oh == 0){
oh = ow;
hp = 1;
}else if(hp && ow == 0){
ow = oh;
wp = 1;
}
memimageinit();
if((a = readmemimage(fd)) == nil)
sysfatal("memory");
w = Dx(a->r);
h = Dy(a->r);
if(stmode == Stpixels){
iw = st[2]-st[0];
ih = st[3]-st[1];
st[0] /= (double)w;
st[1] /= (double)h;
st[2] /= (double)w;
st[3] /= (double)h;
}else{
iw = w;
ih = h;
}
if(ow == 0 && oh == 0){
ow = iw;
oh = ih;
}
if(wp)
ow = iw*ow/100.0;
if(hp)
oh = ih*oh/100.0;
if(oh == 0)
oh = ow*ih/iw;
if(ow == 0)
ow = oh*iw/ih;
if(ow < 1 || oh < 1)
sysfatal("invalid size: %dx%d", ow, oh);
bp = 0;
again:
switch(a->chan){
case GREY8:
bp = 1;
break;
case RGB24:
bp = 3;
break;
case RGBA32:
bp = 4;
alphai = 3;
break;
case ARGB32:
case XRGB32:
bp = 4;
alphai = 0;
break;
case GREY1:
case GREY2:
case GREY4:
to = GREY8;
goto convert;
case CMAP8:
case RGB15:
case RGB16:
to = RGB24;
goto convert;
case BGR24:
to = RGB24;
goto convert;
case ABGR32:
to = ARGB32;
goto convert;
case XBGR32:
to = XRGB32;
convert:
if((b = allocmemimage(a->r, to)) == nil)
sysfatal("memory");
memimagedraw(b, a->r, a, ZP, nil, ZP, S);
freememimage(a);
a = b;
goto again;
default:
sysfatal("invalid chan %#lux", a->chan);
}
n = w*h*bp;
if((in = malloc(w*h*bp)) == nil)
sysfatal("%r");
if(unloadmemimage(a, a->r, in, n) < 0)
sysfatal("%r");
if((out = malloc(ow*oh*bp)) == nil)
sysfatal("memory");
stbir_resize_region(
in, w, h, w*bp,
out, ow, oh, ow*bp,
STBIR_TYPE_UINT8,
bp, alphai, flags,
STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP,
f, f,
c, nil,
st[0], st[1], st[2], st[3]
);
free(in);
if((b = allocmemimage(Rect(0,0,ow,oh), a->chan)) == nil)
sysfatal("%r");
loadmemimage(b, b->r, out, ow*oh*bp);
writememimage(1, b);
exits(nil);
}