-
Notifications
You must be signed in to change notification settings - Fork 1
/
ppmgfx.c
137 lines (117 loc) · 2.33 KB
/
ppmgfx.c
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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/*
* This file is part of the henon project.
*
* Copyright 2016 Urban Wallasch <[email protected]>
* See LICENSE file for more details.
*
*/
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "ppmgfx.h"
#ifdef USE_PNG
#include "pngwrite.h"
#endif
struct ppm_t_struct {
size_t w, h;
ppc_t *b;
};
int ppm_create( ppm_t **pp, size_t w, size_t h )
{
ppm_t *p;
size_t sz = w * h * sizeof *p->b;
if ( !pp || !w || !h )
return errno = EINVAL, -1;
if ( NULL == ( p = malloc( sizeof *p ) ) )
return -1;
if ( NULL == ( p->b = malloc( sz ) ) )
return free( p ), -1;
p->w = w;
p->h = h;
*pp = p;
return 0;
}
int ppm_destroy( ppm_t **pp )
{
if ( !pp )
return errno = EINVAL, -1;
free( (*pp)->b );
free( *pp );
*pp = NULL;
return 0;
}
int ppm_clear( ppm_t *p )
{
if ( !p )
return errno = EINVAL, -1;
memset( p->b, 0, p->w * p->h * sizeof *p->b );
return 0;
}
#define SETPIXEL(P,C) \
do{ ((uint8_t *)(P))[0] = (C) >> 16 & 0xff; /* R */ \
((uint8_t *)(P))[1] = (C) >> 8 & 0xff; /* G */ \
((uint8_t *)(P))[2] = (C) & 0xff; /* B */ \
((uint8_t *)(P))[3] = 0xff; /* A */ \
}while(0);
int ppm_fill( ppm_t *p, ppc_t col )
{
size_t sz = p->w * p->h;
if ( !p )
return errno = EINVAL, -1;
SETPIXEL( &p->b[0], col );
col = p->b[0];
while ( sz-- )
p->b[sz] = col;
return 0;
}
static inline int ppm_drawdot_unsafe( ppm_t *p, size_t x, size_t y, ppc_t col )
{
SETPIXEL( &p->b[ y * p->w + x ], col );
return 0;
}
#undef SETPIXEL
int ppm_drawdot( ppm_t *p, size_t x, size_t y, ppc_t col )
{
if ( !p || x >= p->w || y >= p->h )
return errno = EINVAL, -1;
return ppm_drawdot_unsafe( p, x, y, col );
}
int ppm_write( ppm_t *p, FILE *f, enum ppm_fmt fmt )
{
int r = -1;
int errsav;
size_t sz = p->w * p->h;
uint8_t *b = (uint8_t *)p->b;
if ( !f || !p )
return errno = EINVAL, -1;
switch ( fmt )
{
case PPM_RAW:
errsav = errno;
errno = 0;
fprintf( f, "P6\n# Creator: %s\n%zu %zu\n255\n", __FILE__, p->w, p->h );
while ( sz-- )
{
fputc( *b++, f ); /* R */
fputc( *b++, f ); /* G */
fputc( *b++, f ); /* B */
b++; /* A */
}
if ( 0 == errno )
{
r = 0;
errno = errsav;
}
break;
#ifdef USE_PNG
case PPM_PNG:
r = png_write( f, (uint8_t *)p->b, p->w, p->h );
break;
#endif
default:
errno = EINVAL;
break;
}
return r;
}
/* EOF */