aboutsummaryrefslogtreecommitdiffstats
path: root/src/netpbm.c
blob: e6f685135caf885d30609c1c240d10dda033cc59 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#include <stdio.h>
#include <stdlib.h>

#include "meh.h"

struct netpbm_t{
	struct image img;
	FILE *f;
  char format;
	unsigned int maxval;
};

void skipspace(FILE *f){
	int c;
	for(;;){
		c = fgetc(f);
		while(isspace(c))
			c = fgetc(f);
		if(c == '#')
			while(fgetc(f) != '\n');
		else
			break;
	}
	ungetc(c, f);
}

struct image *netpbm_open(FILE *f){
	struct netpbm_t *b;
	rewind(f);

	char format;
	if(fgetc(f) != 'P')
		return NULL;
	format = fgetc(f);
	if(format > '6' || format < '1')
		return NULL;

	b = malloc(sizeof(struct netpbm_t));
	b->format = format;

	skipspace(f);
	fscanf(f, "%u", &b->img.bufwidth);
	skipspace(f);
	fscanf(f, "%u", &b->img.bufheight);
	if(format == '1' || format == '4'){
		b->maxval = 1;
	}else{
		skipspace(f);
		fscanf(f, "%u", &b->maxval);
	}

	/* whitespace character */
	fgetc(f);

	b->f = f;

	return (struct image *)b;
}

int netpbm_read(struct image *img){
	struct netpbm_t *b = (struct netpbm_t *)img;
	FILE *f = b->f;
	int a = 0;

	int left = img->bufwidth * img->bufheight;
	int j, c;

	if(b->format == '4'){
		while(left){
			c = fgetc(f);
			for(j = 0; j < 8 && left; j++){
				int val = (c & 1) ? 0 : 255;
				img->buf[a++] = val;
				img->buf[a++] = val;
				img->buf[a++] = val;
				c >>= 1;
				left--;
			}
		}
	}else if(b->format == '6'){
		while(left){
			img->buf[a++] = fgetc(f);
			img->buf[a++] = fgetc(f);
			img->buf[a++] = fgetc(f);
			left--;
		}
	}

	img->state = LOADED;
	return 0;
}

void netpbm_close(struct image *img){
	struct netpbm_t *b = (struct netpbm_t *)img;
	fclose(b->f);
}

struct imageformat netpbm = {
	netpbm_open,
	NULL,
	netpbm_read,
	netpbm_close
};