17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <draw.h>
47dd7cddfSDavid du Colombier #include <memdraw.h>
57dd7cddfSDavid du Colombier #include <bio.h>
67dd7cddfSDavid du Colombier #include "imagefile.h"
77dd7cddfSDavid du Colombier
87dd7cddfSDavid du Colombier /* Convert image to a single channel, one byte per pixel */
97dd7cddfSDavid du Colombier
107dd7cddfSDavid du Colombier static
117dd7cddfSDavid du Colombier int
notrans(ulong chan)127dd7cddfSDavid du Colombier notrans(ulong chan)
137dd7cddfSDavid du Colombier {
147dd7cddfSDavid du Colombier switch(chan){
157dd7cddfSDavid du Colombier case GREY1:
167dd7cddfSDavid du Colombier case GREY2:
177dd7cddfSDavid du Colombier case GREY4:
187dd7cddfSDavid du Colombier case CMAP8:
197dd7cddfSDavid du Colombier case GREY8:
207dd7cddfSDavid du Colombier return 1;
217dd7cddfSDavid du Colombier }
227dd7cddfSDavid du Colombier return 0;
237dd7cddfSDavid du Colombier }
247dd7cddfSDavid du Colombier
257dd7cddfSDavid du Colombier static
267dd7cddfSDavid du Colombier int
easycase(ulong chan)277dd7cddfSDavid du Colombier easycase(ulong chan)
287dd7cddfSDavid du Colombier {
297dd7cddfSDavid du Colombier switch(chan){
307dd7cddfSDavid du Colombier case RGB16:
317dd7cddfSDavid du Colombier case RGB24:
327dd7cddfSDavid du Colombier case RGBA32:
337dd7cddfSDavid du Colombier case ARGB32:
347dd7cddfSDavid du Colombier return 1;
357dd7cddfSDavid du Colombier }
367dd7cddfSDavid du Colombier return 0;
377dd7cddfSDavid du Colombier }
387dd7cddfSDavid du Colombier
397dd7cddfSDavid du Colombier /*
407dd7cddfSDavid du Colombier * Convert to one byte per pixel, RGBV or grey, depending
417dd7cddfSDavid du Colombier */
427dd7cddfSDavid du Colombier
437dd7cddfSDavid du Colombier static
447dd7cddfSDavid du Colombier uchar*
load(Image * image,Memimage * memimage)457dd7cddfSDavid du Colombier load(Image *image, Memimage *memimage)
467dd7cddfSDavid du Colombier {
477dd7cddfSDavid du Colombier uchar *data, *p, *q0, *q1, *q2;
487dd7cddfSDavid du Colombier uchar *rgbv;
497dd7cddfSDavid du Colombier int depth, ndata, dx, dy, i, v;
507dd7cddfSDavid du Colombier ulong chan, pixel;
517dd7cddfSDavid du Colombier Rectangle r;
527dd7cddfSDavid du Colombier Rawimage ri, *nri;
537dd7cddfSDavid du Colombier
547dd7cddfSDavid du Colombier if(memimage == nil){
557dd7cddfSDavid du Colombier r = image->r;
567dd7cddfSDavid du Colombier depth = image->depth;
577dd7cddfSDavid du Colombier chan = image->chan;
587dd7cddfSDavid du Colombier }else{
597dd7cddfSDavid du Colombier r = memimage->r;
607dd7cddfSDavid du Colombier depth = memimage->depth;
617dd7cddfSDavid du Colombier chan = memimage->chan;
627dd7cddfSDavid du Colombier }
637dd7cddfSDavid du Colombier dx = Dx(r);
647dd7cddfSDavid du Colombier dy = Dy(r);
657dd7cddfSDavid du Colombier
667dd7cddfSDavid du Colombier /*
677dd7cddfSDavid du Colombier * Read image data into memory
687dd7cddfSDavid du Colombier * potentially one extra byte on each end of each scan line.
697dd7cddfSDavid du Colombier */
707dd7cddfSDavid du Colombier ndata = dy*(2+bytesperline(r, depth));
717dd7cddfSDavid du Colombier data = malloc(ndata);
727dd7cddfSDavid du Colombier if(data == nil)
737dd7cddfSDavid du Colombier return nil;
747dd7cddfSDavid du Colombier if(memimage != nil)
757dd7cddfSDavid du Colombier ndata = unloadmemimage(memimage, r, data, ndata);
767dd7cddfSDavid du Colombier else
777dd7cddfSDavid du Colombier ndata = unloadimage(image, r, data, ndata);
787dd7cddfSDavid du Colombier if(ndata < 0){
797dd7cddfSDavid du Colombier werrstr("onechan: %r");
807dd7cddfSDavid du Colombier free(data);
817dd7cddfSDavid du Colombier return nil;
827dd7cddfSDavid du Colombier }
837dd7cddfSDavid du Colombier
847dd7cddfSDavid du Colombier /*
857dd7cddfSDavid du Colombier * Repack
867dd7cddfSDavid du Colombier */
877dd7cddfSDavid du Colombier memset(&ri, 0, sizeof(ri));
887dd7cddfSDavid du Colombier ri.r = r;
897dd7cddfSDavid du Colombier ri.cmap = nil;
907dd7cddfSDavid du Colombier ri.cmaplen = 0;
917dd7cddfSDavid du Colombier ri.nchans = 3;
927dd7cddfSDavid du Colombier ri.chanlen = dx*dy;
937dd7cddfSDavid du Colombier ri.chans[0] = malloc(ri.chanlen);
947dd7cddfSDavid du Colombier ri.chans[1] = malloc(ri.chanlen);
957dd7cddfSDavid du Colombier ri.chans[2] = malloc(ri.chanlen);
967dd7cddfSDavid du Colombier if(ri.chans[0]==nil || ri.chans[1]==nil || ri.chans[2]==nil){
977dd7cddfSDavid du Colombier Err:
987dd7cddfSDavid du Colombier free(ri.chans[0]);
997dd7cddfSDavid du Colombier free(ri.chans[1]);
1007dd7cddfSDavid du Colombier free(ri.chans[2]);
1017dd7cddfSDavid du Colombier free(data);
1027dd7cddfSDavid du Colombier return nil;
1037dd7cddfSDavid du Colombier }
1047dd7cddfSDavid du Colombier ri.chandesc = CRGB;
1057dd7cddfSDavid du Colombier
1067dd7cddfSDavid du Colombier p = data;
1077dd7cddfSDavid du Colombier q0 = ri.chans[0];
1087dd7cddfSDavid du Colombier q1 = ri.chans[1];
1097dd7cddfSDavid du Colombier q2 = ri.chans[2];
1107dd7cddfSDavid du Colombier
1117dd7cddfSDavid du Colombier switch(chan){
1127dd7cddfSDavid du Colombier default:
1137dd7cddfSDavid du Colombier werrstr("can't handle image type 0x%lux", chan);
1147dd7cddfSDavid du Colombier goto Err;
1157dd7cddfSDavid du Colombier case RGB16:
1167dd7cddfSDavid du Colombier for(i=0; i<ri.chanlen; i++, p+=2){
1177dd7cddfSDavid du Colombier pixel = (p[1]<<8)|p[0]; /* rrrrrggg gggbbbbb */
1187dd7cddfSDavid du Colombier v = (pixel & 0xF800) >> 8;
1197dd7cddfSDavid du Colombier *q0++ = v | (v>>5);
1207dd7cddfSDavid du Colombier v = (pixel & 0x07E0) >> 3;
1217dd7cddfSDavid du Colombier *q1++ = v | (v>>6);
1227dd7cddfSDavid du Colombier v = (pixel & 0x001F) << 3;
1237dd7cddfSDavid du Colombier *q2++ = v | (v>>5);
1247dd7cddfSDavid du Colombier }
1257dd7cddfSDavid du Colombier break;
1267dd7cddfSDavid du Colombier case RGB24:
1277dd7cddfSDavid du Colombier for(i=0; i<ri.chanlen; i++){
1287dd7cddfSDavid du Colombier *q2++ = *p++;
1297dd7cddfSDavid du Colombier *q1++ = *p++;
1307dd7cddfSDavid du Colombier *q0++ = *p++;
1317dd7cddfSDavid du Colombier }
1327dd7cddfSDavid du Colombier break;
1337dd7cddfSDavid du Colombier case RGBA32:
1347dd7cddfSDavid du Colombier for(i=0; i<ri.chanlen; i++){
1357dd7cddfSDavid du Colombier *q2++ = *p++;
1367dd7cddfSDavid du Colombier *q1++ = *p++;
1377dd7cddfSDavid du Colombier *q0++ = *p++;
1387dd7cddfSDavid du Colombier p++;
1397dd7cddfSDavid du Colombier }
1407dd7cddfSDavid du Colombier break;
1417dd7cddfSDavid du Colombier case ARGB32:
1427dd7cddfSDavid du Colombier for(i=0; i<ri.chanlen; i++){
1437dd7cddfSDavid du Colombier p++;
1447dd7cddfSDavid du Colombier *q2++ = *p++;
1457dd7cddfSDavid du Colombier *q1++ = *p++;
1467dd7cddfSDavid du Colombier *q0++ = *p++;
1477dd7cddfSDavid du Colombier }
1487dd7cddfSDavid du Colombier break;
1497dd7cddfSDavid du Colombier }
1507dd7cddfSDavid du Colombier
1517dd7cddfSDavid du Colombier rgbv = nil;
1527dd7cddfSDavid du Colombier nri = torgbv(&ri, 1);
1537dd7cddfSDavid du Colombier if(nri != nil){
1547dd7cddfSDavid du Colombier rgbv = nri->chans[0];
1557dd7cddfSDavid du Colombier free(nri);
1567dd7cddfSDavid du Colombier }
1577dd7cddfSDavid du Colombier
1587dd7cddfSDavid du Colombier free(ri.chans[0]);
1597dd7cddfSDavid du Colombier free(ri.chans[1]);
1607dd7cddfSDavid du Colombier free(ri.chans[2]);
1617dd7cddfSDavid du Colombier free(data);
1627dd7cddfSDavid du Colombier return rgbv;
1637dd7cddfSDavid du Colombier }
1647dd7cddfSDavid du Colombier
1657dd7cddfSDavid du Colombier Image*
onechan(Image * i)1667dd7cddfSDavid du Colombier onechan(Image *i)
1677dd7cddfSDavid du Colombier {
1687dd7cddfSDavid du Colombier uchar *data;
1697dd7cddfSDavid du Colombier Image *ni;
1707dd7cddfSDavid du Colombier
1717dd7cddfSDavid du Colombier if(notrans(i->chan))
1727dd7cddfSDavid du Colombier return i;
1737dd7cddfSDavid du Colombier
1747dd7cddfSDavid du Colombier if(easycase(i->chan))
1757dd7cddfSDavid du Colombier data = load(i, nil);
1767dd7cddfSDavid du Colombier else{
1777dd7cddfSDavid du Colombier ni = allocimage(display, i->r, RGB24, 0, DNofill);
1787dd7cddfSDavid du Colombier if(ni == nil)
1797dd7cddfSDavid du Colombier return ni;
1807dd7cddfSDavid du Colombier draw(ni, ni->r, i, nil, i->r.min);
1817dd7cddfSDavid du Colombier data = load(ni, nil);
1827dd7cddfSDavid du Colombier freeimage(ni);
1837dd7cddfSDavid du Colombier }
1847dd7cddfSDavid du Colombier
1857dd7cddfSDavid du Colombier if(data == nil)
1867dd7cddfSDavid du Colombier return nil;
1877dd7cddfSDavid du Colombier
1887dd7cddfSDavid du Colombier ni = allocimage(display, i->r, CMAP8, 0, DNofill);
1897dd7cddfSDavid du Colombier if(ni != nil)
1907dd7cddfSDavid du Colombier if(loadimage(ni, ni->r, data, Dx(ni->r)*Dy(ni->r)) < 0){
1917dd7cddfSDavid du Colombier freeimage(ni);
1927dd7cddfSDavid du Colombier ni = nil;
1937dd7cddfSDavid du Colombier }
1947dd7cddfSDavid du Colombier free(data);
1957dd7cddfSDavid du Colombier return ni;
1967dd7cddfSDavid du Colombier }
1977dd7cddfSDavid du Colombier
1987dd7cddfSDavid du Colombier Memimage*
memonechan(Memimage * i)1997dd7cddfSDavid du Colombier memonechan(Memimage *i)
2007dd7cddfSDavid du Colombier {
2017dd7cddfSDavid du Colombier uchar *data;
2027dd7cddfSDavid du Colombier Memimage *ni;
2037dd7cddfSDavid du Colombier
2047dd7cddfSDavid du Colombier if(notrans(i->chan))
2057dd7cddfSDavid du Colombier return i;
2067dd7cddfSDavid du Colombier
2077dd7cddfSDavid du Colombier if(easycase(i->chan))
2087dd7cddfSDavid du Colombier data = load(nil, i);
2097dd7cddfSDavid du Colombier else{
2107dd7cddfSDavid du Colombier ni = allocmemimage(i->r, RGB24);
2117dd7cddfSDavid du Colombier if(ni == nil)
2127dd7cddfSDavid du Colombier return ni;
213*6a9fc400SDavid du Colombier memimagedraw(ni, ni->r, i, i->r.min, nil, ZP, S);
2147dd7cddfSDavid du Colombier data = load(nil, ni);
2157dd7cddfSDavid du Colombier freememimage(ni);
2167dd7cddfSDavid du Colombier }
2177dd7cddfSDavid du Colombier
2187dd7cddfSDavid du Colombier if(data == nil)
2197dd7cddfSDavid du Colombier return nil;
2207dd7cddfSDavid du Colombier
2217dd7cddfSDavid du Colombier ni = allocmemimage(i->r, CMAP8);
2227dd7cddfSDavid du Colombier if(ni != nil)
2237dd7cddfSDavid du Colombier if(loadmemimage(ni, ni->r, data, Dx(ni->r)*Dy(ni->r)) < 0){
2247dd7cddfSDavid du Colombier freememimage(ni);
2257dd7cddfSDavid du Colombier ni = nil;
2267dd7cddfSDavid du Colombier }
2277dd7cddfSDavid du Colombier free(data);
2287dd7cddfSDavid du Colombier return ni;
2297dd7cddfSDavid du Colombier }
230