1 /**
2  ** to_png.c: Portable Network Graphics (PNG) converter part of project "hp2xx"
3  ** Michael Schmitz, schmitz@simul.biophys.uni-duesseldorf.de
4  ** Derived from: to_gif.c (GIF module; no longer supported due to copyright
5  **                         problems with the GIF-internal LZW compression)
6  ** 94/08/22 V 1.00  MS   started from scratch, using to_pbm.c and Tom Boutells
7  **                       gd.c gifdraw module; simple merge of both modules :-)
8  **                       (see gd.c and gifencod copyright notes below)
9  **                       Bresnham line drawing and fonts: own hp2xx code used
10  **                       already _before_ this routine is called.
11  **
12  ** 95/09/26 V 1.10  MS   Major cleanup; removed unused code portions.
13  **                       Routines used from gifdraw code:
14  **                       gdImageCreate, gdImageColorAllocate, gdImageSetPixel,
15  **                       gdImageBoundsSafe, gdImageGetPixel, gdImageGif,
16  **                       gdImageDestroy.
17  **                       (gdImageGif in turn uses routines from GIFEncode that
18  **                       is part of the pbmplus package.
19  **
20  ** 97/11/26 V 1.0   MS   Rewrite to libpng 0.96 using Tom Boutell's pixel
21  **                       drawing primitives
22  **
23  **/
24 
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include "bresnham.h"
28 #include "hp2xx.h"
29 #include "to_png.h"
30 #include "pendef.h"
31 #define GGE >>=
32 #define MAXOUTPUTROWS 70
33 
34 #define PDNCOL 256
35 
36 int pdImageColorAllocate(pdImagePtr, int, int, int);
37 
PicBuf_to_PNG(const GEN_PAR * pg,const OUT_PAR * po)38 int PicBuf_to_PNG(const GEN_PAR * pg, const OUT_PAR * po)
39 {
40 	FILE *fd;
41 	int row_c, /*byte_c, */ x;
42 	const RowBuf *row;
43 	const PicBuf *pb;
44 	int ppm[][3] = { {255, 255, 255}, {0, 0, 0} };
45 /*, {255,0,0}, {0,255,0},
46 		{0,0,255},{0,255,255},{255,0,255},{255,255,0}};
47 */
48 	int colour;
49 
50 /**
51  ** gifdraw-parts
52  **/
53 	pdImagePtr im;
54 	int pdcol;
55 
56 	if (pg == NULL || po == NULL)
57 		return ERROR;
58 	pb = po->picbuf;
59 	if (pb == NULL)
60 		return ERROR;
61 
62 	if (!pg->quiet)
63 		Eprintf("\nWriting PNG output: %s\n", po->outfile);
64 	if (*po->outfile != '-') {
65 
66 /*
67 #ifdef VAX
68 	if ((fd = fopen(po->outfile, WRITE_BIN, "rfm=var", "mrs=512")) == NULL)
69 #else
70 */
71 		if ((fd = fopen(po->outfile, WRITE_BIN)) == NULL)
72 /*
73 #endif
74 */
75 			goto ERROR_EXIT;
76 	} else
77 		fd = stdout;
78 
79 /**
80  ** create image structure
81  **/
82 	im = pdImageCreate(pb->nc, pb->nr);
83 
84 	if (pb->depth > 1) {
85 /**
86  ** allocate some colors ( ?? eight colors supported by hp2xx ?? )
87  **/
88 		for (colour = 0; colour < PDNCOL; colour++)
89 /*  pdcol = pdImageColorAllocate(im, ppm[colour][0], ppm[colour][1],
90 				    ppm[colour][2]);
91 */
92 			pdcol =
93 			    pdImageColorAllocate(im, pt.clut[colour][0],
94 						 pt.clut[colour][1],
95 						 pt.clut[colour][2]);
96 		for (row_c = 0; row_c < pb->nr; row_c++) {
97 			row = get_RowBuf(pb, pb->nr - row_c - 1);
98 			if (row == NULL)
99 				continue;
100 
101 			for (x = 0; x < pb->nc; x++) {
102 				colour = index_from_RowBuf(row, x, pb);
103 				pdImageSetPixel(im, x, row_c, colour);
104 			}
105 			if ((!pg->quiet) && (row_c % 10 == 0))
106 				/* For the impatients among us ...   */
107 				Eprintf(".");
108 		}
109 	} else {
110 /**
111  ** allocate two colors ( ?? eight colors supported by hp2xx ?? )
112  **/
113 		for (colour = 0; colour < 2; colour++)
114 			pdcol =
115 			    pdImageColorAllocate(im, ppm[colour][0],
116 						 ppm[colour][1],
117 						 ppm[colour][2]);
118 
119 		for (row_c = 0; row_c < pb->nr; row_c++) {
120 			row = get_RowBuf(pb, pb->nr - row_c - 1);
121 			if (row == NULL)
122 				continue;
123 
124 			for (x = 0; x < pb->nc; x++) {
125 				colour = index_from_RowBuf(row, x, pb);
126 				pdImageSetPixel(im, x, row_c, colour);
127 			}
128 
129 			if ((!pg->quiet) && (row_c % 10 == 0))
130 				/* For the impatients among us ...   */
131 				Eprintf(".");
132 		}
133 	}
134 
135 	pdImagePNG(im, fd);
136 
137 	pdImageDestroy(im);
138 
139 	fflush(fd);
140 
141 	if (!pg->quiet)
142 		Eprintf("\n");
143 	if (fd != stdout)
144 		fclose(fd);
145 	return 0;
146 
147       ERROR_EXIT:
148 	PError("write_PNG");
149 	return ERROR;
150 }
151 
152 /**
153  ** PNG image support routines, derived from:
154  **/
155 
156 /* gd.c: implementation of the gifdraw module. Version 0.9.
157 
158         Written by Tom Boutell, 5/94-6/94.
159         Copyright 1994, Cold Spring Harbor Labs.
160         Permission granted to use this code in any fashion provided
161         that this notice is retained and any alterations are
162         labeled as such. It is requested, but not required, that
163         you share extensions to this module with us so that we
164         can incorporate them into new versions. */
165 /**
166  ** PNG: use sy rows of sx pixels (instead of sx columns of sy pixels)
167  **/
168 
pdImageCreate(sx,sy)169 pdImagePtr pdImageCreate(sx, sy)
170 int sx;
171 int sy;
172 {
173 	int i;
174 	pdImagePtr im;
175 	im = (pdImage *) malloc(sizeof(pdImage));
176 	im->pixels =
177 	    (unsigned char **) malloc(sizeof(unsigned char *) * sy);
178 	for (i = 0; (i < sy); i++) {
179 		im->pixels[i] = (unsigned char *) calloc((size_t) sx,
180 							 sizeof(unsigned
181 								char));
182 	}
183 	im->sx = sx;
184 	im->sy = sy;
185 	im->colorsTotal = 0;
186 	im->transparent = (-1);
187 	return im;
188 }
189 
pdImageDestroy(im)190 void pdImageDestroy(im)
191 pdImagePtr im;
192 {
193 	int i;
194 	for (i = 0; (i < im->sy); i++) {
195 		free(im->pixels[i]);
196 	}
197 	free(im->pixels);
198 	free(im);
199 }
200 
pdImageColorAllocate(im,r,g,b)201 int pdImageColorAllocate(im, r, g, b)
202 pdImagePtr im;
203 int r;
204 int g;
205 int b;
206 {
207 	int i;
208 	int ct = (-1);
209 	for (i = 0; (i < (im->colorsTotal)); i++) {
210 		if (im->open[i]) {
211 			ct = i;
212 			break;
213 		}
214 	}
215 	if (ct == (-1)) {
216 		ct = im->colorsTotal;
217 		if (ct == pdMaxColors) {
218 			return -1;
219 		}
220 		im->colorsTotal++;
221 	}
222 	im->red[ct] = r;
223 	im->green[ct] = g;
224 	im->blue[ct] = b;
225 	im->open[ct] = 0;
226 	return ct;
227 }
228 
pdImageColorTransparent(im,color)229 void pdImageColorTransparent(im, color)
230 pdImagePtr im;
231 unsigned char color;
232 {
233 	im->transparent = color;
234 }
235 
pdImageSetPixel(im,x,y,color)236 void pdImageSetPixel(im, x, y, color)
237 pdImagePtr im;
238 int x;
239 int y;
240 unsigned char color;
241 {
242 	if (pdImageBoundsSafe(im, x, y)) {
243 		im->pixels[y][x] = color;
244 	}
245 }
246 
pdImageGetPixel(im,x,y)247 int pdImageGetPixel(im, x, y)
248 pdImagePtr im;
249 int x;
250 int y;
251 {
252 	if (pdImageBoundsSafe(im, x, y)) {
253 		return im->pixels[y][x];
254 	} else {
255 		return 0;
256 	}
257 }
258 
pdImageBoundsSafe(im,x,y)259 int pdImageBoundsSafe(im, x, y)
260 pdImagePtr im;
261 int x;
262 int y;
263 {
264 	return (!(((y < 0) || (y >= im->sy)) ||
265 		  ((x < 0) || (x >= im->sx))));
266 }
267