Plan 9 from Bell Labs’s /usr/web/sources/contrib/maht/imgfs/import_ppm.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


#include <u.h>
#include <libc.h>
#include <draw.h>
#include <bio.h>
#include <ctype.h>
#include <thread.h>
#include <fcall.h>
#include <9p.h>

#include "mapbook.h"
#include "imgfs.h"
#include "ifslib.h"
#include "import_ppm.h"

int ppm_fd, red_fd, green_fd, blue_fd;
int magic, width, height, maxval;
float scalar;

enum
{
	/* Channel descriptors */
	CRGB	= 0,	/* three channels, no map */
	CYCbCr	= 1,	/* three channels, no map, level-shifted 601 color space */
	CY	= 2,	/* one channel, luminance */
	CRGB1	= 3,	/* one channel, map present */
	CRGBV	= 4,	/* one channel, map is RGBV, understood */
	CRGB24	= 5,	/* one channel in correct data order for loadimage(RGB24) */
	CRGBA32	= 6,	/* one channel in correct data order for loadimage(RGBA32) */
	CYA16	= 7,	/* one channel in correct data order for loadimage(Grey8+Alpha8) */
	CRGBVA16= 8,	/* one channel in correct data order for loadimage(CMAP8+Alpha8) */

	/* GIF flags */
	TRANSP	= 1,
	INPUT	= 2,
	DISPMASK = 7<<2
};

static int bitc, nbit;
/*
 * fetch a non-comment character.
 */
static
int
Bgetch(Biobufhdr *b)
{
	int c;

	for(;;) {
		c = Bgetc(b);
		if(c == '#') {
			while((c = Bgetc(b)) != Beof && c != '\n')
				;
		}
		return c;
	}		
}

/*
 * fetch a nonnegative decimal integer.
 */
static
int
Bgetint(Biobufhdr *b)
{
	int c;
	int i;

	while((c = Bgetch(b)) != Beof && !isdigit(c))
		;
	if(c == Beof)
		return -1;

	i = 0;
	do { 
		i = i*10 + (c-'0');
	} while((c = Bgetch(b)) != Beof && isdigit(c));

	return i;
}


static
int
Bgetdecimalbit(Biobufhdr *b)
{
	int c;
	while((c = Bgetch(b)) != Beof && c != '0' && c != '1')
		;
	if(c == Beof)
		return -1;
	return c == '1';
}

static
int
Bgetbit(Biobufhdr *b)
{
	if(nbit == 0) {
		nbit = 8;
		bitc = Bgetc(b);
		if(bitc == -1)
			return -1;
	}
	nbit--;
	return (bitc >> (nbit-1)) & 0x1;
}

static
void
Bflushbit(Biobufhdr*)
{
	nbit = 0;
}

typedef struct Pix	Pix;
struct Pix {
	char magic;
	int	maxcol;
	int	(*fetch)(Biobufhdr*);
	int	nchan;
	int	chandesc;
	int	invert;
	void	(*flush)(Biobufhdr*);
};
static Pix pix[] = {
	{ '1', 1, Bgetdecimalbit, 1, CY, 1, nil },	/* portable bitmap */
	{ '4', 1, Bgetbit, 1, CY, 1, Bflushbit },	/* raw portable bitmap */
	{ '2', 0, Bgetint, 1, CY, 0, nil },	/* portable greymap */
	{ '5', 0, Bgetc, 1, CY, 0, nil },	/* raw portable greymap */
	{ '3', 0, Bgetint, 3, CRGB, 0, nil },	/* portable pixmap */
	{ '6', 0, Bgetc, 3, CRGB, 0, nil },	/* raw portable pixmap */
	{ 0 },
};

RGBint *
free_rgb(RGBint *rgb) {
	if(rgb) {
		free(rgb->r);
		free(rgb->g);
		free(rgb->b);
	}
	return nil;
}
		

RGBint * 
readppm(Biobuf *b)
{
	RGBint *rgb;
	int i, c;
	int (*fetch)(Biobufhdr*);
	Pix *p;
	int pixels;

	if(Bgetc(b) != 'P') {
		fprint(2, "Doubt it's a ppm");
		return nil;
	}

	c = Bgetc(b);

	for(p=pix; p->magic; p++)
		if(p->magic == c)
			break;
	if(p->magic == 0) {
		fprint(2, "Bad magic");
		return nil;
	}
		
	if(c != '3' && c != '6') {
		fprint(2, "sorry, RGB only");
		return nil;
	}

	rgb = (RGBint*)mallocz(sizeof(RGBint), 1);

	rgb->width = Bgetint(b);
	rgb->height = Bgetint(b);
	if(rgb->width <= 0 || rgb->height <= 0){
		fprint(2, "width or height < 0");
		free_rgb(rgb);
		return nil;
	}
	rgb->maxcol = p->maxcol;
	if(rgb->maxcol == 0) {
		rgb->maxcol = Bgetint(b);
		if(rgb->maxcol <= 0) {
			fprint(2, "rgb->maxcol <= 0");
			free_rgb(rgb);
			return nil;
		}
	}
	pixels = rgb->width * rgb->height;
	rgb->r = (int*)mallocz(sizeof(int)*pixels, 1);
	rgb->g = (int*)mallocz(sizeof(int)*pixels, 1);
	rgb->b = (int*)mallocz(sizeof(int)*pixels, 1);
	fetch = p->fetch;

	for(i=0; rgb && i < pixels; i++)
		if(((rgb->r[i] = (*fetch)(b)) < 0) || ((rgb->g[i] = (*fetch)(b)) < 0) || ((rgb->b[i] = (*fetch)(b)) < 0))
			rgb = free_rgb(rgb);

	return rgb;
}

char *
import_ppm(Aux *aux, char *fname) {
	RGBint *rgb;
	Biobuf b;
	int pixels;
	int i;
	Bitmap *target;

	int fd = open(fname, OREAD);
	if(fd == -1)
		return nil;

	if(Binit(&b, fd, OREAD) != -1) {
		rgb = readppm(&b);
		Bterm(&b);
		if(rgb) {
			clear_mapbook(aux->mapbook);
			aux->mapbook->width = rgb->width;
			aux->mapbook->height = rgb->height;

			pixels = rgb->width * rgb->height;

			target = get_or_create_bitmap(aux->mapbook, id_red);
			for(i = 0; i < pixels; i++)
				target->data[i] = 255 * rgb->r[i] / rgb->maxcol;
			target = get_or_create_bitmap(aux->mapbook, id_green);
			for(i = 0; i < pixels; i++)
				target->data[i] = 255 * rgb->g[i] / rgb->maxcol;
			target = get_or_create_bitmap(aux->mapbook, id_blue);
			for(i = 0; i < pixels; i++)
				target->data[i] = 255 * rgb->b[i] / rgb->maxcol;
			free_rgb(rgb);
		}

	}
	close(fd);

	return nil;
}

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.