xref: /plan9/sys/src/cmd/aux/antiword/png2eps.c (revision f5736e95f14e1485b3a0291fa82d86cca323ab61)
1 /*
2  * png2eps.c
3  * Copyright (C) 2000-2002 A.J. van Os; Released under GPL
4  *
5  * Description:
6  * Functions to translate png images into eps
7  *
8  */
9 
10 #include <stdio.h>
11 #include <ctype.h>
12 #include "antiword.h"
13 
14 #if defined(DEBUG)
15 static int	iPicCounter = 0;
16 #endif /* DEBUG */
17 
18 
19 /*
20  * tSkipToData - skip until a IDAT chunk is found
21  *
22  * returns the length of the pixeldata or -1 in case of error
23  */
24 static size_t
tSkipToData(FILE * pFile,size_t tMaxBytes,size_t * ptSkipped)25 tSkipToData(FILE *pFile, size_t tMaxBytes, size_t *ptSkipped)
26 {
27 	ULONG	ulName, ulTmp;
28 	size_t	tDataLength, tToSkip;
29 	int	iCounter;
30 
31 	fail(pFile == NULL);
32 	fail(ptSkipped == NULL);
33 
34 	/* Examine chunks */
35 	while (*ptSkipped + 8 < tMaxBytes) {
36 		tDataLength = (size_t)ulNextLongBE(pFile);
37 		DBG_DEC(tDataLength);
38 		*ptSkipped += 4;
39 
40 		ulName = 0x00;
41 		for (iCounter = 0; iCounter < 4; iCounter++) {
42 			ulTmp = (ULONG)iNextByte(pFile);
43 			if (!isalpha((int)ulTmp)) {
44 				DBG_HEX(ulTmp);
45 				return (size_t)-1;
46 			}
47 			ulName <<= 8;
48 			ulName |= ulTmp;
49 		}
50 		DBG_HEX(ulName);
51 		*ptSkipped += 4;
52 
53 		if (ulName == PNG_CN_IEND) {
54 			break;
55 		}
56 		if (ulName == PNG_CN_IDAT) {
57 			return tDataLength;
58 		}
59 
60 		tToSkip = tDataLength + 4;
61 		if (tToSkip >= tMaxBytes - *ptSkipped) {
62 			DBG_DEC(tToSkip);
63 			DBG_DEC(tMaxBytes - *ptSkipped);
64 			return (size_t)-1;
65 		}
66 		(void)tSkipBytes(pFile, tToSkip);
67 		*ptSkipped += tToSkip;
68 	}
69 
70 	return (size_t)-1;
71 } /* end of iSkipToData */
72 
73 /*
74  * iFindFirstPixelData - find the first pixeldata if a PNG image
75  *
76  * returns the length of the pixeldata or -1 in case of error
77  */
78 static size_t
tFindFirstPixelData(FILE * pFile,size_t tMaxBytes,size_t * ptSkipped)79 tFindFirstPixelData(FILE *pFile, size_t tMaxBytes, size_t *ptSkipped)
80 {
81 	fail(pFile == NULL);
82 	fail(tMaxBytes == 0);
83 	fail(ptSkipped == NULL);
84 
85 	if (tMaxBytes < 8) {
86 		DBG_DEC(tMaxBytes);
87 		return (size_t)-1;
88 	}
89 
90 	/* Skip over the PNG signature */
91 	(void)tSkipBytes(pFile, 8);
92 	*ptSkipped = 8;
93 
94 	return tSkipToData(pFile, tMaxBytes, ptSkipped);
95 } /* end of iFindFirstPixelData */
96 
97 /*
98  * tFindNextPixelData - find the next pixeldata if a PNG image
99  *
100  * returns the length of the pixeldata or -1 in case of error
101  */
102 static size_t
tFindNextPixelData(FILE * pFile,size_t tMaxBytes,size_t * ptSkipped)103 tFindNextPixelData(FILE *pFile, size_t tMaxBytes, size_t *ptSkipped)
104 {
105 	fail(pFile == NULL);
106 	fail(tMaxBytes == 0);
107 	fail(ptSkipped == NULL);
108 
109 	if (tMaxBytes < 4) {
110 		DBG_DEC(tMaxBytes);
111 		return (size_t)-1;
112 	}
113 
114 	/* Skip over the crc */
115 	(void)tSkipBytes(pFile, 4);
116 	*ptSkipped = 4;
117 
118 	return tSkipToData(pFile, tMaxBytes, ptSkipped);
119 } /* end of tFindNextPixelData */
120 
121 #if defined(DEBUG)
122 /*
123  * vCopy2File
124  */
125 static void
vCopy2File(FILE * pFile,ULONG ulFileOffset,size_t tPictureLen)126 vCopy2File(FILE *pFile, ULONG ulFileOffset, size_t tPictureLen)
127 {
128 	FILE	*pOutFile;
129 	size_t	tIndex;
130 	int	iTmp;
131 	char	szFilename[30];
132 
133 	if (!bSetDataOffset(pFile, ulFileOffset)) {
134 		return;
135 	}
136 
137 	sprintf(szFilename, "/tmp/pic/pic%04d.png", ++iPicCounter);
138 	pOutFile = fopen(szFilename, "wb");
139 	if (pOutFile == NULL) {
140 		return;
141 	}
142 	for (tIndex = 0; tIndex < tPictureLen; tIndex++) {
143 		iTmp = iNextByte(pFile);
144 		if (putc(iTmp, pOutFile) == EOF) {
145 			break;
146 		}
147 	}
148 	(void)fclose(pOutFile);
149 } /* end of vCopy2File */
150 #endif /* DEBUG */
151 
152 /*
153  * bTranslatePNG - translate a PNG image
154  *
155  * This function translates an image from png to eps
156  *
157  * return TRUE when sucessful, otherwise FALSE
158  */
159 BOOL
bTranslatePNG(diagram_type * pDiag,FILE * pFile,ULONG ulFileOffset,size_t tPictureLen,const imagedata_type * pImg)160 bTranslatePNG(diagram_type *pDiag, FILE *pFile,
161 	ULONG ulFileOffset, size_t tPictureLen, const imagedata_type *pImg)
162 {
163 	size_t	tMaxBytes, tDataLength, tSkipped;
164 
165 #if defined(DEBUG)
166 	vCopy2File(pFile, ulFileOffset, tPictureLen);
167 #endif /* DEBUG */
168 
169 	/* Seek to start position of PNG data */
170 	if (!bSetDataOffset(pFile, ulFileOffset)) {
171 		return FALSE;
172 	}
173 
174 	tMaxBytes = tPictureLen;
175 	tDataLength = tFindFirstPixelData(pFile, tMaxBytes, &tSkipped);
176 	if (tDataLength == (size_t)-1) {
177 		return FALSE;
178 	}
179 
180 	vImagePrologue(pDiag, pImg);
181 	do {
182 		tMaxBytes -= tSkipped;
183 		vASCII85EncodeArray(pFile, pDiag->pOutFile, tDataLength);
184 		tMaxBytes -= tDataLength;
185 		tDataLength = tFindNextPixelData(pFile, tMaxBytes, &tSkipped);
186 	} while (tDataLength != (size_t)-1);
187 	vASCII85EncodeByte(pDiag->pOutFile, EOF);
188 	vImageEpilogue(pDiag);
189 
190 	return TRUE;
191 } /* end of bTranslatePNG */
192