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