Simple test for asyncio.library.
[AROS-Contrib.git] / gfx / povray / ppm.c
blob281d641dd9ea167fe60c5945ff4e3151fba52a8f
1 /****************************************************************************
2 * ppm.c
4 * This module contains the code to read and write the PPM file format.
6 * from Persistence of Vision(tm) Ray Tracer
7 * Copyright 1996,1999 Persistence of Vision Team
8 *---------------------------------------------------------------------------
9 * NOTICE: This source code file is provided so that users may experiment
10 * with enhancements to POV-Ray and to port the software to platforms other
11 * than those supported by the POV-Ray Team. There are strict rules under
12 * which you are permitted to use this file. The rules are in the file
13 * named POVLEGAL.DOC which should be distributed with this file.
14 * If POVLEGAL.DOC is not available or for more info please contact the POV-Ray
15 * Team Coordinator by email to team-coord@povray.org or visit us on the web at
16 * http://www.povray.org. The latest version of POV-Ray may be found at this site.
18 * This program is based on the popular DKB raytracer version 2.12.
19 * DKBTrace was originally written by David K. Buck.
20 * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
22 * Original patch copyright 1994 Tim Rowley
23 * Updated for POV 3.0 by Chris Cason, Jan '95.
25 * Modifications by Hans-Detlev Fink, January 1999, used with permission.
27 *****************************************************************************/
29 /****************************************************************************
30 * The format is as follows:
32 * (header:)
33 * P3 - ASCII data OR
34 * P6 - raw binary data
35 * # hello - optional comment(s)
36 * wwww hhhh - Width, Height (ASCII text)
37 * # world - optional comment(s)
38 * nnn - maximum color (nnn = bright, 0 = black)
40 * (each pixel: one of the following)
41 * rr gg bb - Red, green, blue of intensity 0-nnn (binary byte)
42 * RRR GGG BBB - Red, green, blue of intensity 0-nnn (ASCII number)
44 *****************************************************************************/
46 #include "frame.h"
47 #include "povproto.h"
48 #include "povray.h"
49 #include "optout.h"
50 #include "pgm.h"
51 #include "ppm.h"
53 /*****************************************************************************
54 * Local preprocessor defines
55 ******************************************************************************/
57 /*****************************************************************************
58 * Local typedefs
59 ******************************************************************************/
61 /*****************************************************************************
62 * Local variables
63 ******************************************************************************/
65 static int PPM_Line_Number;
67 /*****************************************************************************
68 * Static functions
69 ******************************************************************************/
71 static int Open_PPM_File (FILE_HANDLE *handle, char *name, int *width, int *height, int buffer_size, int mode);
72 static void Write_PPM_Line (FILE_HANDLE *handle, COLOUR *line_data, int line_number);
73 static int Read_PPM_Line (FILE_HANDLE *handle, COLOUR *line_data, int *line_number);
74 static void Close_PPM_File (FILE_HANDLE *handle);
76 /*****************************************************************************
78 * FUNCTION
80 * INPUT
82 * OUTPUT
84 * RETURNS
86 * AUTHOR
88 * DESCRIPTION
90 * CHANGES
92 ******************************************************************************/
94 FILE_HANDLE *Get_PPM_File_Handle()
96 FILE_HANDLE *handle;
98 handle = (FILE_HANDLE *) POV_MALLOC(sizeof(FILE_HANDLE), "PPM file handle") ;
100 handle->Open_File_p = Open_PPM_File;
101 handle->Write_Line_p = Write_PPM_Line;
102 handle->Read_Line_p = Read_PPM_Line;
103 handle->Read_Image_p = Read_PPM_Image;
104 handle->Close_File_p = Close_PPM_File;
106 handle->file = NULL;
107 handle->buffer = NULL;
108 handle->buffer_size = 0;
110 return (handle);
113 /*****************************************************************************
115 * FUNCTION
117 * INPUT
119 * OUTPUT
121 * RETURNS
123 * AUTHOR
125 * DESCRIPTION
127 * CHANGES
129 ******************************************************************************/
131 static int Open_PPM_File(FILE_HANDLE *handle, char *name, int *width, int *height, int buffer_size, int mode)
133 char type;
134 int input;
135 char junk[512];
137 handle->mode = mode;
138 handle->filename = name;
139 PPM_Line_Number = 0;
141 switch (mode)
143 case READ_MODE:
145 /* We can't resume from stdout. */
146 if (opts.Options & TO_STDOUT ||
147 (handle->file = fopen(name, READ_BINFILE_STRING)) == NULL)
149 Status_Info("\n");
150 return(0);
153 if (buffer_size != 0)
155 handle->buffer = (char *)POV_MALLOC((size_t)buffer_size, "PPM file buffer") ;
156 setvbuf(handle->file, handle->buffer, _IOFBF, buffer_size);
159 if (fscanf(handle->file, "P%c\n", &type) != 1 || type != '6')
161 return(0);
164 /* Ignore any comments (if they are written) */
166 while ((input = fgetc(handle->file)) == '#')
168 fgets(junk, 512, handle->file);
171 ungetc(input, handle->file);
173 if (fscanf(handle->file, "%d %d\n255\n", width, height) != 2)
175 return(0);
178 Status_Info("\nResuming interrupted trace from %s",handle->filename);
180 handle->width = *width;
181 handle->height = *height;
182 handle->buffer_size = buffer_size;
184 break;
186 case WRITE_MODE:
188 if (opts.Options & TO_STDOUT)
190 buffer_size = 0;
191 handle->file = stdout;
193 else
195 if ((handle->file = fopen(name, WRITE_BINFILE_STRING)) == NULL)
197 return(0);
201 if (buffer_size != 0)
203 handle->buffer = (char *)POV_MALLOC((size_t)buffer_size, "PPM file buffer") ;
204 setvbuf(handle->file, handle->buffer, _IOFBF, buffer_size);
207 fprintf(handle->file, "P6\n");
209 #ifdef POV_COMMENTS
210 #ifdef TRACER
211 fprintf(handle->file, "# Author: %s\n", TRACER);
212 #endif
214 fprintf(handle->file, "# Source: Persistence of Vision(tm) Ray Tracer v%s%s\n",
215 POV_RAY_VERSION, COMPILER_VER);
217 if (!(opts.Options & TO_STDOUT))
219 fprintf(handle->file, "# Input File: %s\n", opts.Input_File_Name);
222 if (opts.FrameSeq.Clock_Value != 0)
224 fprintf(handle->file, "# POV Clock: %g\n", opts.FrameSeq.Clock_Value);
227 if (opts.Quality != 9)
229 fprintf(handle->file, "# Rendering Quality: %d\n", opts.Quality);
231 #endif /* POV_COMMENTS */
233 fprintf(handle->file, "%d %d\n255\n", *width, *height);
235 handle->width = *width;
236 handle->height = *height;
238 handle->buffer_size = buffer_size;
240 break;
242 case APPEND_MODE:
244 if (opts.Options & TO_STDOUT)
246 buffer_size = 0;
247 handle->file = stdout;
249 else
251 if ((handle->file = fopen(name, APPEND_BINFILE_STRING)) == NULL)
253 return(0);
257 if (buffer_size != 0)
259 handle->buffer = (char *)POV_MALLOC((size_t)buffer_size, "PPM file buffer") ;
260 setvbuf(handle->file, handle->buffer, _IOFBF, buffer_size);
263 handle->buffer_size = buffer_size;
265 break;
268 return(1);
271 /*****************************************************************************
273 * FUNCTION
275 * INPUT
277 * OUTPUT
279 * RETURNS
281 * AUTHOR
283 * DESCRIPTION
285 * CHANGES
287 ******************************************************************************/
289 static void Write_PPM_Line(FILE_HANDLE *handle, COLOUR *line_data, int line_number)
291 unsigned int gray;
292 register int x;
294 for (x = 0 ; x < handle->width ; x++)
296 if (opts.Options & HF_GRAY_16) /* 16 bit grayscale output */
298 gray = ((0.30 * line_data[x][RED]) +
299 (0.59 * line_data[x][GREEN]) +
300 (0.11 * line_data[x][BLUE])) * 65535;
302 if ((putc((gray >> 8) & 0xFF, handle->file) == EOF) ||
303 (putc(gray & 0xFF, handle->file) == EOF) ||
304 (putc(0, handle->file) == EOF))
306 Error("Error writing PPM output data to %s.\n",handle->filename);
309 else /* Normal 24 bit pixel coloring */
311 if ((putc((int)floor(line_data[x][RED] * 255.0), handle->file) == EOF) ||
312 (putc((int)floor(line_data[x][GREEN]*255.0), handle->file) == EOF) ||
313 (putc((int)floor(line_data[x][BLUE]*255.0), handle->file) == EOF))
315 Error("Error writing PPM output data to %s.\n",handle->filename);
320 PPM_Line_Number++;
322 if (handle->buffer_size == 0)
324 /* close and reopen file for integrity in case we crash */
326 fflush(handle->file);
328 if (!(opts.Options & TO_STDOUT))
330 handle->file = freopen(handle->filename,APPEND_BINFILE_STRING,handle->file);
335 /*****************************************************************************
337 * FUNCTION
339 * INPUT
341 * OUTPUT
343 * RETURNS
345 * AUTHOR
347 * DESCRIPTION
349 * CHANGES
351 ******************************************************************************/
353 static int Read_PPM_Line(FILE_HANDLE *handle, COLOUR *line_data, int *line_number)
355 int data, i;
357 if ((data = getc(handle->file)) == EOF)
359 return (0);
362 ungetc(data, handle->file);
364 *line_number = PPM_Line_Number++;
366 for (i = 0 ; i < handle->width ; i++)
368 if ((data = getc(handle->file)) == EOF)
370 return(-1);
373 line_data[i][RED] = (DBL) data / 255.0;
375 if ((data = getc(handle->file)) == EOF)
377 return(-1);
380 line_data[i][GREEN] = (DBL) data / 255.0;
382 if ((data = getc(handle->file)) == EOF)
384 return(-1);
387 line_data[i][BLUE] = (DBL) data / 255.0;
390 return (1);
393 /*****************************************************************************
395 * FUNCTION
397 * INPUT
399 * OUTPUT
401 * RETURNS
403 * AUTHOR
405 * DESCRIPTION
407 * CHANGES
409 ******************************************************************************/
411 static void Close_PPM_File(FILE_HANDLE *handle)
413 if (handle->file)
415 fflush(handle->file);
417 /* Close and reopen file (if not stdout) for integrity in case we crash */
419 if (!(opts.Options & TO_STDOUT))
420 fclose(handle->file);
423 if (handle->buffer != NULL)
425 POV_FREE(handle->buffer);
428 handle->file = NULL;
429 handle->buffer = NULL;
432 /*****************************************************************************
434 * FUNCTION
436 * INPUT
438 * OUTPUT
440 * RETURNS
442 * AUTHOR
444 * DESCRIPTION
446 * CHANGES
448 ******************************************************************************/
450 void Read_PPM_Image(IMAGE *Image, char *name)
452 char type;
453 int width, height;
454 int depth;
455 char input;
456 char junk[512];
457 int x, y;
458 int data;
459 IMAGE_LINE *line_data;
460 FILE *infile;
462 if ((infile = Locate_File(name, READ_BINFILE_STRING, ".ppm", ".PPM",NULL,TRUE)) == NULL)
464 Error("Error opening PPM image %s.\n", name);
465 return; /* -hdf99- */
468 if (fscanf(infile, "P%c\n", &type) != 1 || (type != '3' && type != '6'))
470 Error ("File is not in PPM format.\n", name);
471 return; /* -hdf99- */
474 /* Ignore any comments */
476 while ((input = fgetc(infile)) == '#')
478 fgets(junk, 512, infile);
481 ungetc(input, infile);
483 if (fscanf(infile, "%d %d\n", &width, &height) != 2)
485 Error ("Error reading width or height from PPM image.\n", name);
488 /* Ignore any comments */
489 while ((input = fgetc(infile)) == '#')
491 fgets(junk, 512, infile);
494 ungetc(input, infile);
496 if (fscanf(infile, "%d\n", &depth) != 1 || depth > 255 || depth < 1)
498 Error ("Unsupported number of colors (%d) in PPM image.\n", depth);
501 Image->width = (DBL)(Image->iwidth = width);
502 Image->height = (DBL)(Image->iheight = height);
504 Image->Colour_Map_Size = 0;
506 Image->Colour_Map = NULL;
508 Image->data.rgb_lines = (IMAGE_LINE *) POV_MALLOC(Image->iheight * sizeof (IMAGE_LINE), "PPM image");
510 for (y = 0; y < height; y++)
512 line_data = &Image->data.rgb_lines[y];
514 line_data->red = (unsigned char *)POV_MALLOC(width,"PPM image line");
515 line_data->green = (unsigned char *)POV_MALLOC(width,"PPM image line");
516 line_data->blue = (unsigned char *)POV_MALLOC(width,"PPM image line");
517 line_data->transm = (unsigned char *)NULL;
519 if (type == '3') /* ASCII data to be input */
521 for (x = 0; x < width; x++)
523 if (fscanf(infile,"%d",&data) != 1)
525 Error("Error reading data from PPM image.\n");
528 line_data->red[x] = data*255/depth;
530 if (fscanf(infile,"%d",&data) != 1)
532 Error("Error reading data from PPM image.\n");
535 line_data->green[x] = data*255/depth;
537 if (fscanf(infile,"%d",&data) != 1)
539 Error("Error reading data from PPM image.\n");
542 line_data->blue[x] = data*255/depth;
545 else /* (type == '6') Raw binary data to be input */
547 for (x = 0; x < width; x++)
549 if ((data = getc(infile)) == EOF)
551 Error("Error reading data from PPM image.\n");
554 line_data->red[x] = data*255/depth;
556 if ((data = getc(infile)) == EOF)
558 Error("Error reading data from PPM image.\n");
561 line_data->green[x] = data*255/depth;
563 if ((data = getc(infile)) == EOF)
565 Error("Error reading data from PPM image.\n");
568 line_data->blue[x] = data*255/depth;
573 fclose(infile);