]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/resize.c
make bind(2) error handling consistent
[plan9front.git] / sys / src / cmd / resize.c
1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 #include <memdraw.h>
5
6 int nflag;
7
8 static void
9 resample(Memimage *dst, Rectangle r, Memimage *src, Rectangle sr)
10 {
11         Point sp, dp;
12         Point _sp, qp;
13         Point ssize, dsize;
14         uchar *pdst0, *pdst, *psrc0, *psrc;
15         ulong s00, s01, s10, s11;
16         int tx, ty, bpp, bpl;
17
18         ssize = subpt(subpt(sr.max, sr.min), Pt(1,1));
19         dsize = subpt(subpt(r.max, r.min), Pt(1,1));
20         pdst0 = byteaddr(dst, r.min);
21         bpp = src->depth/8;
22         bpl = src->width*sizeof(int);
23
24         qp = Pt(0, 0);
25         if(dsize.x > 0)
26                 qp.x = (ssize.x<<12)/dsize.x;
27         if(dsize.y > 0)
28                 qp.y = (ssize.y<<12)/dsize.y;
29
30         _sp.y = sr.min.y<<12;
31         for(dp.y=0; dp.y<=dsize.y; dp.y++){
32                 sp.y = _sp.y>>12;
33                 ty = _sp.y&0xFFF;
34                 if(nflag)
35                         ty = ty << 1 & 0x1000;
36                 pdst = pdst0;
37                 sp.x = sr.min.x;
38                 psrc0 = byteaddr(src, sp);
39                 _sp.x = 0;
40                 for(dp.x=0; dp.x<=dsize.x; dp.x++){
41                         sp.x = _sp.x>>12;
42                         tx = _sp.x&0xFFF;
43                         if(nflag)
44                                 tx = tx << 1 & 0x1000;
45                         psrc = psrc0 + sp.x*bpp;
46                         s00 = (0x1000-tx)*(0x1000-ty);
47                         s01 = tx*(0x1000-ty);
48                         s10 = (0x1000-tx)*ty;
49                         s11 = tx*ty;
50                         switch(bpp){
51                         case 4:
52                                 pdst[3] = (s11*psrc[bpl+bpp+3] + 
53                                            s10*psrc[bpl+3] + 
54                                            s01*psrc[bpp+3] +
55                                            s00*psrc[3]) >>24;
56                         case 3:
57                                 pdst[2] = (s11*psrc[bpl+bpp+2] + 
58                                            s10*psrc[bpl+2] + 
59                                            s01*psrc[bpp+2] +
60                                            s00*psrc[2]) >>24;
61                                 pdst[1] = (s11*psrc[bpl+bpp+1] + 
62                                            s10*psrc[bpl+1] + 
63                                            s01*psrc[bpp+1] +
64                                            s00*psrc[1]) >>24;
65                         case 1:
66                                 pdst[0] = (s11*psrc[bpl+bpp] + 
67                                            s10*psrc[bpl] + 
68                                            s01*psrc[bpp] +
69                                            s00*psrc[0]) >>24;
70                         }
71                         pdst += bpp;
72                         _sp.x += qp.x;
73                 }
74                 pdst0 += dst->width*sizeof(int);
75                 _sp.y += qp.y;
76         }
77 }
78
79 enum {
80         PERCENT = 0x80000000,
81 };
82
83 static int
84 getsize(char *s)
85 {
86         int v;
87
88         v = strtol(s, &s, 10) & ~PERCENT;
89         if(*s == '%')
90                 v |= PERCENT;
91         return v;
92 }
93
94 void
95 usage(void)
96 {
97         sysfatal("Usage: %s [ -x width ] [ -y height ] [ file ]\n", argv0);
98 }
99
100 void
101 main(int argc, char **argv)
102 {
103         int fd, xsize, ysize;
104         Memimage *im, *nim;
105         ulong ochan, tchan;
106
107         xsize = ysize = 0;
108         ARGBEGIN{
109         case 'a':
110                 xsize = ysize = getsize(EARGF(usage()));
111                 break;
112         case 'x':
113                 xsize = getsize(EARGF(usage()));
114                 break;
115         case 'y':
116                 ysize = getsize(EARGF(usage()));
117                 break;
118         case 'n':
119                 nflag++;
120                 break;
121         default:
122                 usage();
123         }ARGEND
124         fd = 0;
125         if(*argv){
126                 fd = open(*argv, OREAD);
127                 if(fd < 0)
128                         sysfatal("open: %r");
129         }
130         memimageinit();
131         if((im = readmemimage(fd)) == nil)
132                 sysfatal("readmemimage: %r");
133         if(xsize & PERCENT)
134                 xsize = ((xsize & ~PERCENT) * Dx(im->r)) / 100;
135         if(ysize & PERCENT)
136                 ysize = ((ysize & ~PERCENT) * Dy(im->r)) / 100;
137         if(xsize || ysize){
138                 if(ysize == 0)
139                         ysize = (xsize * Dy(im->r)) / Dx(im->r);
140                 if(xsize == 0)
141                         xsize = (ysize * Dx(im->r)) / Dy(im->r);
142                 ochan = im->chan;
143                 switch(ochan){
144                 default:
145                         for(tchan = ochan; tchan; tchan >>= 8)
146                                 if(TYPE(tchan) == CAlpha){
147                                         tchan = RGBA32;
148                                         break;
149                                 }
150                         if(tchan == 0)
151                                 tchan = RGB24;
152                         break;
153                 case GREY8:
154                 case RGB24:
155                 case RGBA32:
156                 case ARGB32:
157                 case XRGB32:
158                         tchan = ochan;
159                         break;
160                 case GREY1:
161                 case GREY2:
162                 case GREY4:
163                         tchan = GREY8;
164                         break;
165                 }
166                 if(tchan != ochan){
167                         if((nim = allocmemimage(im->r, tchan)) == nil)
168                                 sysfatal("allocimage: %r");
169                         memimagedraw(nim, nim->r, im, im->r.min, nil, ZP, S);
170                         freememimage(im);
171                         im = nim;
172                 }
173                 if((nim = allocmemimage(
174                         Rect(im->r.min.x, im->r.min.y, im->r.min.x+xsize, im->r.min.y+ysize), 
175                         tchan)) == nil)
176                         sysfatal("allocmemimage: %r");
177                 resample(nim, nim->r, im, im->r);
178                 freememimage(im);
179                 im = nim;
180                 if(tchan != ochan){
181                         if((im = allocmemimage(nim->r, ochan)) == nil)
182                                 sysfatal("allocimage: %r");
183                         memimagedraw(im, im->r, nim, nim->r.min, nil, ZP, S);
184                         freememimage(nim);
185                 }
186         }
187         if(writememimage(1, im) < 0)
188                 sysfatal("writememimage: %r");
189         exits(0);
190 }