/[dtapublic]/projs/trunk/shared_source/c_tk_base_7_5_w_mods/tkimgppm.c
ViewVC logotype

Annotation of /projs/trunk/shared_source/c_tk_base_7_5_w_mods/tkimgppm.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 44 - (hide annotations) (download)
Fri Oct 14 02:09:58 2016 UTC (7 years, 5 months ago) by dashley
File MIME type: text/plain
File size: 12401 byte(s)
Rename for reorganization.
1 dashley 25 /* $Header: /cvsroot/esrg/sfesrg/esrgpcpj/shared/tk_base/tkimgppm.c,v 1.1.1.1 2001/06/13 05:03:30 dtashley Exp $ */
2    
3     /*
4     * tkImgPPM.c --
5     *
6     * A photo image file handler for PPM (Portable PixMap) files.
7     *
8     * Copyright (c) 1994 The Australian National University.
9     * Copyright (c) 1994-1997 Sun Microsystems, Inc.
10     *
11     * See the file "license.terms" for information on usage and redistribution
12     * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
13     *
14     * Author: Paul Mackerras (paulus@cs.anu.edu.au),
15     * Department of Computer Science,
16     * Australian National University.
17     *
18     * RCS: @(#) $Id: tkimgppm.c,v 1.1.1.1 2001/06/13 05:03:30 dtashley Exp $
19     */
20    
21     #define USE_OLD_IMAGE
22    
23     #include "tkInt.h"
24     #include "tkPort.h"
25    
26     /*
27     * The maximum amount of memory to allocate for data read from the
28     * file. If we need more than this, we do it in pieces.
29     */
30    
31     #define MAX_MEMORY 10000 /* don't allocate > 10KB */
32    
33     /*
34     * Define PGM and PPM, i.e. gray images and color images.
35     */
36    
37     #define PGM 1
38     #define PPM 2
39    
40     /*
41     * The format record for the PPM file format:
42     */
43    
44     static int FileMatchPPM _ANSI_ARGS_((Tcl_Channel chan,
45     char *fileName, char *formatString,
46     int *widthPtr, int *heightPtr));
47     static int FileReadPPM _ANSI_ARGS_((Tcl_Interp *interp,
48     Tcl_Channel chan, char *fileName,
49     char *formatString, Tk_PhotoHandle imageHandle,
50     int destX, int destY, int width, int height,
51     int srcX, int srcY));
52     static int FileWritePPM _ANSI_ARGS_((Tcl_Interp *interp,
53     char *fileName, char *formatString,
54     Tk_PhotoImageBlock *blockPtr));
55    
56     Tk_PhotoImageFormat tkImgFmtPPM = {
57     "PPM", /* name */
58     FileMatchPPM, /* fileMatchProc */
59     NULL, /* stringMatchProc */
60     FileReadPPM, /* fileReadProc */
61     NULL, /* stringReadProc */
62     FileWritePPM, /* fileWriteProc */
63     NULL, /* stringWriteProc */
64     };
65    
66     /*
67     * Prototypes for local procedures defined in this file:
68     */
69    
70     static int ReadPPMFileHeader _ANSI_ARGS_((Tcl_Channel chan,
71     int *widthPtr, int *heightPtr,
72     int *maxIntensityPtr));
73    
74     /*
75     *----------------------------------------------------------------------
76     *
77     * FileMatchPPM --
78     *
79     * This procedure is invoked by the photo image type to see if
80     * a file contains image data in PPM format.
81     *
82     * Results:
83     * The return value is >0 if the first characters in file "f" look
84     * like PPM data, and 0 otherwise.
85     *
86     * Side effects:
87     * The access position in f may change.
88     *
89     *----------------------------------------------------------------------
90     */
91    
92     static int
93     FileMatchPPM(chan, fileName, formatString, widthPtr, heightPtr)
94     Tcl_Channel chan; /* The image file, open for reading. */
95     char *fileName; /* The name of the image file. */
96     char *formatString; /* User-specified format string, or NULL. */
97     int *widthPtr, *heightPtr; /* The dimensions of the image are
98     * returned here if the file is a valid
99     * raw PPM file. */
100     {
101     int dummy;
102    
103     return ReadPPMFileHeader(chan, widthPtr, heightPtr, &dummy);
104     }
105    
106     /*
107     *----------------------------------------------------------------------
108     *
109     * FileReadPPM --
110     *
111     * This procedure is called by the photo image type to read
112     * PPM format data from a file and write it into a given
113     * photo image.
114     *
115     * Results:
116     * A standard TCL completion code. If TCL_ERROR is returned
117     * then an error message is left in the interp's result.
118     *
119     * Side effects:
120     * The access position in file f is changed, and new data is
121     * added to the image given by imageHandle.
122     *
123     *----------------------------------------------------------------------
124     */
125    
126     static int
127     FileReadPPM(interp, chan, fileName, formatString, imageHandle, destX, destY,
128     width, height, srcX, srcY)
129     Tcl_Interp *interp; /* Interpreter to use for reporting errors. */
130     Tcl_Channel chan; /* The image file, open for reading. */
131     char *fileName; /* The name of the image file. */
132     char *formatString; /* User-specified format string, or NULL. */
133     Tk_PhotoHandle imageHandle; /* The photo image to write into. */
134     int destX, destY; /* Coordinates of top-left pixel in
135     * photo image to be written to. */
136     int width, height; /* Dimensions of block of photo image to
137     * be written to. */
138     int srcX, srcY; /* Coordinates of top-left pixel to be used
139     * in image being read. */
140     {
141     int fileWidth, fileHeight, maxIntensity;
142     int nLines, nBytes, h, type, count;
143     unsigned char *pixelPtr;
144     Tk_PhotoImageBlock block;
145    
146     type = ReadPPMFileHeader(chan, &fileWidth, &fileHeight, &maxIntensity);
147     if (type == 0) {
148     Tcl_AppendResult(interp, "couldn't read raw PPM header from file \"",
149     fileName, "\"", NULL);
150     return TCL_ERROR;
151     }
152     if ((fileWidth <= 0) || (fileHeight <= 0)) {
153     Tcl_AppendResult(interp, "PPM image file \"", fileName,
154     "\" has dimension(s) <= 0", (char *) NULL);
155     return TCL_ERROR;
156     }
157     if ((maxIntensity <= 0) || (maxIntensity >= 256)) {
158     char buffer[TCL_INTEGER_SPACE];
159    
160     sprintf(buffer, "%d", maxIntensity);
161     Tcl_AppendResult(interp, "PPM image file \"", fileName,
162     "\" has bad maximum intensity value ", buffer,
163     (char *) NULL);
164     return TCL_ERROR;
165     }
166    
167     if ((srcX + width) > fileWidth) {
168     width = fileWidth - srcX;
169     }
170     if ((srcY + height) > fileHeight) {
171     height = fileHeight - srcY;
172     }
173     if ((width <= 0) || (height <= 0)
174     || (srcX >= fileWidth) || (srcY >= fileHeight)) {
175     return TCL_OK;
176     }
177    
178     if (type == PGM) {
179     block.pixelSize = 1;
180     block.offset[0] = 0;
181     block.offset[1] = 0;
182     block.offset[2] = 0;
183     }
184     else {
185     block.pixelSize = 3;
186     block.offset[0] = 0;
187     block.offset[1] = 1;
188     block.offset[2] = 2;
189     }
190     block.offset[3] = 0;
191     block.width = width;
192     block.pitch = block.pixelSize * fileWidth;
193    
194     Tk_PhotoExpand(imageHandle, destX + width, destY + height);
195    
196     if (srcY > 0) {
197     Tcl_Seek(chan, (srcY * block.pitch), SEEK_CUR);
198     }
199    
200     nLines = (MAX_MEMORY + block.pitch - 1) / block.pitch;
201     if (nLines > height) {
202     nLines = height;
203     }
204     if (nLines <= 0) {
205     nLines = 1;
206     }
207     nBytes = nLines * block.pitch;
208     pixelPtr = (unsigned char *) ckalloc((unsigned) nBytes);
209     block.pixelPtr = pixelPtr + srcX * block.pixelSize;
210    
211     for (h = height; h > 0; h -= nLines) {
212     if (nLines > h) {
213     nLines = h;
214     nBytes = nLines * block.pitch;
215     }
216     count = Tcl_Read(chan, (char *) pixelPtr, nBytes);
217     if (count != nBytes) {
218     Tcl_AppendResult(interp, "error reading PPM image file \"",
219     fileName, "\": ",
220     Tcl_Eof(chan) ? "not enough data" : Tcl_PosixError(interp),
221     (char *) NULL);
222     ckfree((char *) pixelPtr);
223     return TCL_ERROR;
224     }
225     if (maxIntensity != 255) {
226     unsigned char *p;
227    
228     for (p = pixelPtr; count > 0; count--, p++) {
229     *p = (((int) *p) * 255)/maxIntensity;
230     }
231     }
232     block.height = nLines;
233     Tk_PhotoPutBlock(imageHandle, &block, destX, destY, width, nLines);
234     destY += nLines;
235     }
236    
237     ckfree((char *) pixelPtr);
238     return TCL_OK;
239     }
240    
241     /*
242     *----------------------------------------------------------------------
243     *
244     * FileWritePPM --
245     *
246     * This procedure is invoked to write image data to a file in PPM
247     * format.
248     *
249     * Results:
250     * A standard TCL completion code. If TCL_ERROR is returned
251     * then an error message is left in the interp's result.
252     *
253     * Side effects:
254     * Data is written to the file given by "fileName".
255     *
256     *----------------------------------------------------------------------
257     */
258    
259     static int
260     FileWritePPM(interp, fileName, formatString, blockPtr)
261     Tcl_Interp *interp;
262     char *fileName;
263     char *formatString;
264     Tk_PhotoImageBlock *blockPtr;
265     {
266     Tcl_Channel chan;
267     int w, h;
268     int greenOffset, blueOffset, nBytes;
269     unsigned char *pixelPtr, *pixLinePtr;
270     char header[16 + TCL_INTEGER_SPACE * 2];
271    
272     chan = Tcl_OpenFileChannel(interp, fileName, "w", 0666);
273     if (chan == NULL) {
274     return TCL_ERROR;
275     }
276    
277     if (Tcl_SetChannelOption(interp, chan, "-translation", "binary")
278     != TCL_OK) {
279     return TCL_ERROR;
280     }
281     if (Tcl_SetChannelOption(interp, chan, "-encoding", "binary")
282     != TCL_OK) {
283     return TCL_ERROR;
284     }
285    
286     sprintf(header, "P6\n%d %d\n255\n", blockPtr->width, blockPtr->height);
287     Tcl_Write(chan, header, -1);
288    
289     pixLinePtr = blockPtr->pixelPtr + blockPtr->offset[0];
290     greenOffset = blockPtr->offset[1] - blockPtr->offset[0];
291     blueOffset = blockPtr->offset[2] - blockPtr->offset[0];
292    
293     if ((greenOffset == 1) && (blueOffset == 2) && (blockPtr->pixelSize == 3)
294     && (blockPtr->pitch == (blockPtr->width * 3))) {
295     nBytes = blockPtr->height * blockPtr->pitch;
296     if (Tcl_Write(chan, (char *) pixLinePtr, nBytes) != nBytes) {
297     goto writeerror;
298     }
299     } else {
300     for (h = blockPtr->height; h > 0; h--) {
301     pixelPtr = pixLinePtr;
302     for (w = blockPtr->width; w > 0; w--) {
303     if ((Tcl_Write(chan, (char *) &pixelPtr[0], 1) == -1)
304     || (Tcl_Write(chan, (char *) &pixelPtr[greenOffset], 1) == -1)
305     || (Tcl_Write(chan, (char *) &pixelPtr[blueOffset], 1) == -1)) {
306     goto writeerror;
307     }
308     pixelPtr += blockPtr->pixelSize;
309     }
310     pixLinePtr += blockPtr->pitch;
311     }
312     }
313    
314     if (Tcl_Close(NULL, chan) == 0) {
315     return TCL_OK;
316     }
317     chan = NULL;
318    
319     writeerror:
320     Tcl_AppendResult(interp, "error writing \"", fileName, "\": ",
321     Tcl_PosixError(interp), (char *) NULL);
322     if (chan != NULL) {
323     Tcl_Close(NULL, chan);
324     }
325     return TCL_ERROR;
326     }
327    
328     /*
329     *----------------------------------------------------------------------
330     *
331     * ReadPPMFileHeader --
332     *
333     * This procedure reads the PPM header from the beginning of a
334     * PPM file and returns information from the header.
335     *
336     * Results:
337     * The return value is PGM if file "f" appears to start with
338     * a valid PGM header, PPM if "f" appears to start with a valid
339     * PPM header, and 0 otherwise. If the header is valid,
340     * then *widthPtr and *heightPtr are modified to hold the
341     * dimensions of the image and *maxIntensityPtr is modified to
342     * hold the value of a "fully on" intensity value.
343     *
344     * Side effects:
345     * The access position in f advances.
346     *
347     *----------------------------------------------------------------------
348     */
349    
350     static int
351     ReadPPMFileHeader(chan, widthPtr, heightPtr, maxIntensityPtr)
352     Tcl_Channel chan; /* Image file to read the header from */
353     int *widthPtr, *heightPtr; /* The dimensions of the image are
354     * returned here. */
355     int *maxIntensityPtr; /* The maximum intensity value for
356     * the image is stored here. */
357     {
358     #define BUFFER_SIZE 1000
359     char buffer[BUFFER_SIZE];
360     int i, numFields;
361     int type = 0;
362     char c;
363    
364     /*
365     * Read 4 space-separated fields from the file, ignoring
366     * comments (any line that starts with "#").
367     */
368    
369     if (Tcl_Read(chan, &c, 1) != 1) {
370     return 0;
371     }
372     i = 0;
373     for (numFields = 0; numFields < 4; numFields++) {
374     /*
375     * Skip comments and white space.
376     */
377    
378     while (1) {
379     while (isspace(UCHAR(c))) {
380     if (Tcl_Read(chan, &c, 1) != 1) {
381     return 0;
382     }
383     }
384     if (c != '#') {
385     break;
386     }
387     do {
388     if (Tcl_Read(chan, &c, 1) != 1) {
389     return 0;
390     }
391     } while (c != '\n');
392     }
393    
394     /*
395     * Read a field (everything up to the next white space).
396     */
397    
398     while (!isspace(UCHAR(c))) {
399     if (i < (BUFFER_SIZE-2)) {
400     buffer[i] = c;
401     i++;
402     }
403     if (Tcl_Read(chan, &c, 1) != 1) {
404     goto done;
405     }
406     }
407     if (i < (BUFFER_SIZE-1)) {
408     buffer[i] = ' ';
409     i++;
410     }
411     }
412     done:
413     buffer[i] = 0;
414    
415     /*
416     * Parse the fields, which are: id, width, height, maxIntensity.
417     */
418    
419     if (strncmp(buffer, "P6 ", 3) == 0) {
420     type = PPM;
421     } else if (strncmp(buffer, "P5 ", 3) == 0) {
422     type = PGM;
423     } else {
424     return 0;
425     }
426     if (sscanf(buffer+3, "%d %d %d", widthPtr, heightPtr, maxIntensityPtr)
427     != 3) {
428     return 0;
429     }
430     return type;
431     }
432    
433    
434     /* $History: tkImgPPM.c $
435     *
436     * ***************** Version 1 *****************
437     * User: Dtashley Date: 1/02/01 Time: 2:53a
438     * Created in $/IjuScripter, IjuConsole/Source/Tk Base
439     * Initial check-in.
440     */
441    
442     /* End of TKIMGPPM.C */

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25