plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

writeppm.c (3098B)


      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 #define	MAXLINE	70
      9 
     10 /*
     11  * Write data
     12  */
     13 static
     14 char*
     15 writedata(Biobuf *fd, Image *image, Memimage *memimage)
     16 {
     17 	char *err;
     18 	uchar *data;
     19 	int i, x, y, ndata, depth, col, pix, xmask, pmask;
     20 	ulong chan;
     21 	Rectangle r;
     22 
     23 	if(memimage != nil){
     24 		r = memimage->r;
     25 		depth = memimage->depth;
     26 		chan = memimage->chan;
     27 	}else{
     28 		r = image->r;
     29 		depth = image->depth;
     30 		chan = image->chan;
     31 	}
     32 
     33 	/*
     34 	 * Read image data into memory
     35 	 * potentially one extra byte on each end of each scan line
     36 	 */
     37 	ndata = Dy(r)*(2+Dx(r)*depth/8);
     38 	data = malloc(ndata);
     39 	if(data == nil)
     40 		return "WritePPM: malloc failed";
     41 	if(memimage != nil)
     42 		ndata = unloadmemimage(memimage, r, data, ndata);
     43 	else
     44 		ndata = unloadimage(image, r, data, ndata);
     45 	if(ndata < 0){
     46 		err = malloc(ERRMAX);
     47 		if(err == nil)
     48 			return "WritePPM: malloc failed";
     49 		snprint(err, ERRMAX, "WriteGIF: %r");
     50 		free(data);
     51 		return err;
     52 	}
     53 
     54 	/* Encode and emit the data */
     55 	col = 0;
     56 	switch(chan){
     57 	case GREY1:
     58 	case GREY2:
     59 	case GREY4:
     60 		pmask = (1<<depth)-1;
     61 		xmask = 7>>drawlog2[depth];
     62 		for(y=r.min.y; y<r.max.y; y++){
     63 			i = (y-r.min.y)*bytesperline(r, depth);
     64 			for(x=r.min.x; x<r.max.x; x++){
     65 				pix = (data[i]>>depth*((xmask-x)&xmask))&pmask;
     66 				if(((x+1)&xmask) == 0)
     67 					i++;
     68 				col += Bprint(fd, "%d ", pix);
     69 				if(col >= MAXLINE-(2+1)){
     70 					Bprint(fd, "\n");
     71 					col = 0;
     72 				}else
     73 					col += Bprint(fd, " ");
     74 			}
     75 		}
     76 		break;
     77 	case	GREY8:
     78 		for(i=0; i<ndata; i++){
     79 			col += Bprint(fd, "%d ", data[i]);
     80 			if(col >= MAXLINE-(4+1)){
     81 				Bprint(fd, "\n");
     82 				col = 0;
     83 			}else
     84 				col += Bprint(fd, " ");
     85 		}
     86 		break;
     87 	case RGB24:
     88 		for(i=0; i<ndata; i+=3){
     89 			col += Bprint(fd, "%d %d %d", data[i+2], data[i+1], data[i]);
     90 			if(col >= MAXLINE-(4+4+4+1)){
     91 				Bprint(fd, "\n");
     92 				col = 0;
     93 			}else
     94 				col += Bprint(fd, " ");
     95 		}
     96 		break;
     97 	default:
     98 		return "WritePPM: can't handle channel type";
     99 	}
    100 
    101 	return nil;
    102 }
    103 
    104 static
    105 char*
    106 writeppm0(Biobuf *fd, Image *image, Memimage *memimage, Rectangle r, int chan, char *comment)
    107 {
    108 	char *err;
    109 
    110 	switch(chan){
    111 	case GREY1:
    112 		Bprint(fd, "P1\n");
    113 		break;
    114 	case GREY2:
    115 	case GREY4:
    116 	case	GREY8:
    117 		Bprint(fd, "P2\n");
    118 		break;
    119 	case RGB24:
    120 		Bprint(fd, "P3\n");
    121 		break;
    122 	default:
    123 		return "WritePPM: can't handle channel type";
    124 	}
    125 
    126 	if(comment!=nil && comment[0]!='\0'){
    127 		Bprint(fd, "# %s", comment);
    128 		if(comment[strlen(comment)-1] != '\n')
    129 			Bprint(fd, "\n");
    130 	}
    131 	Bprint(fd, "%d %d\n", Dx(r), Dy(r));
    132 
    133 	/* maximum pixel value */
    134 	switch(chan){
    135 	case GREY2:
    136 		Bprint(fd, "%d\n", 3);
    137 		break;
    138 	case GREY4:
    139 		Bprint(fd, "%d\n", 15);
    140 		break;
    141 	case	GREY8:
    142 	case RGB24:
    143 		Bprint(fd, "%d\n", 255);
    144 		break;
    145 	}
    146 
    147 	err = writedata(fd, image, memimage);
    148 
    149 	Bprint(fd, "\n");
    150 	Bflush(fd);
    151 	return err;
    152 }
    153 
    154 char*
    155 writeppm(Biobuf *fd, Image *image, char *comment)
    156 {
    157 	return writeppm0(fd, image, nil, image->r, image->chan, comment);
    158 }
    159 
    160 char*
    161 memwriteppm(Biobuf *fd, Memimage *memimage, char *comment)
    162 {
    163 	return writeppm0(fd, nil, memimage, memimage->r, memimage->chan, comment);
    164 }