URI:
       tonechan.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tonechan.c (3731B)
       ---
            1 #include <u.h>
            2 #include <libc.h>
            3 #include <draw.h>
            4 #include <memdraw.h>
            5 #include <bio.h>
            6 #include "imagefile.h"
            7 
            8 /* Convert image to a single channel, one byte per pixel */
            9 
           10 static
           11 int
           12 notrans(ulong chan)
           13 {
           14         switch(chan){
           15         case GREY1:
           16         case GREY2:
           17         case GREY4:
           18         case        CMAP8:
           19         case GREY8:
           20                 return 1;
           21         }
           22         return 0;
           23 }
           24 
           25 static
           26 int
           27 easycase(ulong chan)
           28 {
           29         switch(chan){
           30         case RGB16:
           31         case RGB24:
           32         case RGBA32:
           33         case ARGB32:
           34                 return 1;
           35         }
           36         return 0;
           37 }
           38 
           39 /*
           40  * Convert to one byte per pixel, RGBV or grey, depending
           41  */
           42 
           43 static
           44 uchar*
           45 load(Image *image, Memimage *memimage)
           46 {
           47         uchar *data, *p, *q0, *q1, *q2;
           48         uchar *rgbv;
           49         int depth, ndata, dx, dy, i, v;
           50         ulong chan, pixel;
           51         Rectangle r;
           52         Rawimage ri, *nri;
           53 
           54         if(memimage == nil){
           55                 r = image->r;
           56                 depth = image->depth;
           57                 chan = image->chan;
           58         }else{
           59                 r = memimage->r;
           60                 depth = memimage->depth;
           61                 chan = memimage->chan;
           62         }
           63         dx = Dx(r);
           64         dy = Dy(r);
           65 
           66         /*
           67          * Read image data into memory
           68          * potentially one extra byte on each end of each scan line.
           69          */
           70         ndata = dy*(2+bytesperline(r, depth));
           71         data = malloc(ndata);
           72         if(data == nil)
           73                 return nil;
           74         if(memimage != nil)
           75                 ndata = unloadmemimage(memimage, r, data, ndata);
           76         else
           77                 ndata = unloadimage(image, r, data, ndata);
           78         if(ndata < 0){
           79                 werrstr("onechan: %r");
           80                 free(data);
           81                 return nil;
           82         }
           83 
           84         /*
           85          * Repack
           86          */
           87         memset(&ri, 0, sizeof(ri));
           88         ri.r = r;
           89         ri.cmap = nil;
           90         ri.cmaplen = 0;
           91         ri.nchans = 3;
           92         ri.chanlen = dx*dy;
           93         ri.chans[0] = malloc(ri.chanlen);
           94         ri.chans[1] = malloc(ri.chanlen);
           95         ri.chans[2] = malloc(ri.chanlen);
           96         if(ri.chans[0]==nil || ri.chans[1]==nil || ri.chans[2]==nil){
           97     Err:
           98                 free(ri.chans[0]);
           99                 free(ri.chans[1]);
          100                 free(ri.chans[2]);
          101                 free(data);
          102                 return nil;
          103         }
          104         ri.chandesc = CRGB;
          105 
          106         p = data;
          107         q0 = ri.chans[0];
          108         q1 = ri.chans[1];
          109         q2 = ri.chans[2];
          110 
          111         switch(chan){
          112         default:
          113                 werrstr("can't handle image type 0x%lux", chan);
          114                 goto Err;
          115         case RGB16:
          116                 for(i=0; i<ri.chanlen; i++, p+=2){
          117                         pixel = (p[1]<<8)|p[0];        /* rrrrrggg gggbbbbb */
          118                         v = (pixel & 0xF800) >> 8;
          119                         *q0++ = v | (v>>5);
          120                         v = (pixel & 0x07E0) >> 3;
          121                         *q1++ = v | (v>>6);
          122                         v = (pixel & 0x001F) << 3;
          123                         *q2++ = v | (v>>5);
          124                 }
          125                 break;
          126         case RGB24:
          127                 for(i=0; i<ri.chanlen; i++){
          128                         *q2++ = *p++;
          129                         *q1++ = *p++;
          130                         *q0++ = *p++;
          131                 }
          132                 break;
          133         case RGBA32:
          134                 for(i=0; i<ri.chanlen; i++){
          135                         *q2++ = *p++;
          136                         *q1++ = *p++;
          137                         *q0++ = *p++;
          138                         p++;
          139                 }
          140                 break;
          141         case ARGB32:
          142                 for(i=0; i<ri.chanlen; i++){
          143                         p++;
          144                         *q2++ = *p++;
          145                         *q1++ = *p++;
          146                         *q0++ = *p++;
          147                 }
          148                 break;
          149         }
          150 
          151         rgbv = nil;
          152         nri = torgbv(&ri, 1);
          153         if(nri != nil){
          154                 rgbv = nri->chans[0];
          155                 free(nri);
          156         }
          157 
          158         free(ri.chans[0]);
          159         free(ri.chans[1]);
          160         free(ri.chans[2]);
          161         free(data);
          162         return rgbv;
          163 }
          164 
          165 Image*
          166 onechan(Image *i)
          167 {
          168         uchar *data;
          169         Image *ni;
          170 
          171         if(notrans(i->chan))
          172                 return i;
          173 
          174         if(easycase(i->chan))
          175                 data = load(i, nil);
          176         else{
          177                 ni = allocimage(display, i->r, RGB24, 0, DNofill);
          178                 if(ni == nil)
          179                         return ni;
          180                 draw(ni, ni->r, i, nil, i->r.min);
          181                 data = load(ni, nil);
          182                 freeimage(ni);
          183         }
          184 
          185         if(data == nil)
          186                 return nil;
          187 
          188         ni = allocimage(display, i->r, CMAP8, 0, DNofill);
          189         if(ni != nil)
          190                 if(loadimage(ni, ni->r, data, Dx(ni->r)*Dy(ni->r)) < 0){
          191                         freeimage(ni);
          192                         ni = nil;
          193                 }
          194         free(data);
          195         return ni;
          196 }
          197 
          198 Memimage*
          199 memonechan(Memimage *i)
          200 {
          201         uchar *data;
          202         Memimage *ni;
          203 
          204         if(notrans(i->chan))
          205                 return i;
          206 
          207         if(easycase(i->chan))
          208                 data = load(nil, i);
          209         else{
          210                 ni = allocmemimage(i->r, RGB24);
          211                 if(ni == nil)
          212                         return ni;
          213                 memimagedraw(ni, ni->r, i, i->r.min, nil, ZP, S);
          214                 data = load(nil, ni);
          215                 freememimage(ni);
          216         }
          217 
          218         if(data == nil)
          219                 return nil;
          220 
          221         ni = allocmemimage(i->r, CMAP8);
          222         if(ni != nil)
          223                 if(loadmemimage(ni, ni->r, data, Dx(ni->r)*Dy(ni->r)) < 0){
          224                         freememimage(ni);
          225                         ni = nil;
          226                 }
          227         free(data);
          228         return ni;
          229 }