178 lines · 3.6 KB · C
RawDownload
/*  * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #include <u.h>#include <libc.h>#include <draw.h>#include <memdraw.h>#include <bio.h> #define	MAXLINE	70 /* imported from libdraw/arith.c to permit an extern log2 function */static int log2[] = {	-1, 0, 1, -1, 2, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, 4,	-1, -1, -1, -1, -1, -1, -1, 4 /* BUG */, -1, -1, -1, -1, -1, -1, -1, 5}; /* * Write data */staticchar*writedata(Biobuf *fd, Image *image, Memimage *memimage){	char *err;	uchar *data;	int i, x, y, ndata, depth, col, pix, xmask, pmask;	ulong chan;	Rectangle r; 	if(memimage != nil){		r = memimage->r;		depth = memimage->depth;		chan = memimage->chan;	}else{		r = image->r;		depth = image->depth;		chan = image->chan;	} 	/* 	 * Read image data into memory	 * potentially one extra byte on each end of each scan line	 */	ndata = Dy(r)*(2+Dx(r)*depth/8);	data = malloc(ndata);	if(data == nil)		return "WritePPM: malloc failed";	if(memimage != nil)		ndata = unloadmemimage(memimage, r, data, ndata);	else		ndata = unloadimage(image, r, data, ndata);	if(ndata < 0){		err = malloc(ERRMAX);		if(err == nil)			return "WritePPM: malloc failed";		snprint(err, ERRMAX, "WriteGIF: %r");		free(data);		return err;	} 	/* Encode and emit the data */	col = 0;	switch(chan){	case GREY1:	case GREY2:	case GREY4:		pmask = (1<<depth)-1;		xmask = 7>>log2[depth];		for(y=r.min.y; y<r.max.y; y++){			i = (y-r.min.y)*bytesperline(r, depth);			for(x=r.min.x; x<r.max.x; x++){				pix = (data[i]>>depth*((xmask-x)&xmask))&pmask;				if(((x+1)&xmask) == 0)					i++;				col += Bprint(fd, "%d ", pix);				if(col >= MAXLINE-(2+1)){					Bprint(fd, "\n");					col = 0;				}else					col += Bprint(fd, " ");			}		}		break;	case	GREY8:		for(i=0; i<ndata; i++){			col += Bprint(fd, "%d ", data[i]);			if(col >= MAXLINE-(4+1)){				Bprint(fd, "\n");				col = 0;			}else				col += Bprint(fd, " ");		}		break;	case RGB24:		for(i=0; i<ndata; i+=3){			col += Bprint(fd, "%d %d %d", data[i+2], data[i+1], data[i]);			if(col >= MAXLINE-(4+4+4+1)){				Bprint(fd, "\n");				col = 0;			}else				col += Bprint(fd, " ");		}		break;	default:		return "WritePPM: can't handle channel type";	} 	return nil;} staticchar*writeppm0(Biobuf *fd, Image *image, Memimage *memimage, Rectangle r, int chan, char *comment){	char *err; 	switch(chan){	case GREY1:		Bprint(fd, "P1\n");		break;	case GREY2:	case GREY4:	case	GREY8:		Bprint(fd, "P2\n");		break;	case RGB24:		Bprint(fd, "P3\n");		break;	default:		return "WritePPM: can't handle channel type";	} 	if(comment!=nil && comment[0]!='\0'){		Bprint(fd, "# %s", comment);		if(comment[strlen(comment)-1] != '\n')			Bprint(fd, "\n");	}	Bprint(fd, "%d %d\n", Dx(r), Dy(r)); 	/* maximum pixel value */	switch(chan){	case GREY2:		Bprint(fd, "%d\n", 3);		break;	case GREY4:		Bprint(fd, "%d\n", 15);		break;	case	GREY8:	case RGB24:		Bprint(fd, "%d\n", 255);		break;	} 	err = writedata(fd, image, memimage); 	Bprint(fd, "\n");	Bflush(fd);	return err;} char*writeppm(Biobuf *fd, Image *image, char *comment){	return writeppm0(fd, image, nil, image->r, image->chan, comment);} char*memwriteppm(Biobuf *fd, Memimage *memimage, char *comment){	return writeppm0(fd, nil, memimage, memimage->r, memimage->chan, comment);}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t