shithub: riscv

ref: 28f3a3aad8d2d73010f1c81080e92f71903f4556
dir: /sys/src/cmd/aux/antiword/png2eps.c/

View raw version
/*
 * png2eps.c
 * Copyright (C) 2000-2002 A.J. van Os; Released under GPL
 *
 * Description:
 * Functions to translate png images into eps
 *
 */

#include <stdio.h>
#include <ctype.h>
#include "antiword.h"

#if defined(DEBUG)
static int	iPicCounter = 0;
#endif /* DEBUG */


/*
 * tSkipToData - skip until a IDAT chunk is found
 *
 * returns the length of the pixeldata or -1 in case of error
 */
static size_t
tSkipToData(FILE *pFile, size_t tMaxBytes, size_t *ptSkipped)
{
	ULONG	ulName, ulTmp;
	size_t	tDataLength, tToSkip;
	int	iCounter;

	fail(pFile == NULL);
	fail(ptSkipped == NULL);

	/* Examine chunks */
	while (*ptSkipped + 8 < tMaxBytes) {
		tDataLength = (size_t)ulNextLongBE(pFile);
		DBG_DEC(tDataLength);
		*ptSkipped += 4;

		ulName = 0x00;
		for (iCounter = 0; iCounter < 4; iCounter++) {
			ulTmp = (ULONG)iNextByte(pFile);
			if (!isalpha((int)ulTmp)) {
				DBG_HEX(ulTmp);
				return (size_t)-1;
			}
			ulName <<= 8;
			ulName |= ulTmp;
		}
		DBG_HEX(ulName);
		*ptSkipped += 4;

		if (ulName == PNG_CN_IEND) {
			break;
		}
		if (ulName == PNG_CN_IDAT) {
			return tDataLength;
		}

		tToSkip = tDataLength + 4;
		if (tToSkip >= tMaxBytes - *ptSkipped) {
			DBG_DEC(tToSkip);
			DBG_DEC(tMaxBytes - *ptSkipped);
			return (size_t)-1;
		}
		(void)tSkipBytes(pFile, tToSkip);
		*ptSkipped += tToSkip;
	}

	return (size_t)-1;
} /* end of iSkipToData */

/*
 * iFindFirstPixelData - find the first pixeldata if a PNG image
 *
 * returns the length of the pixeldata or -1 in case of error
 */
static size_t
tFindFirstPixelData(FILE *pFile, size_t tMaxBytes, size_t *ptSkipped)
{
	fail(pFile == NULL);
	fail(tMaxBytes == 0);
	fail(ptSkipped == NULL);

	if (tMaxBytes < 8) {
		DBG_DEC(tMaxBytes);
		return (size_t)-1;
	}

	/* Skip over the PNG signature */
	(void)tSkipBytes(pFile, 8);
	*ptSkipped = 8;

	return tSkipToData(pFile, tMaxBytes, ptSkipped);
} /* end of iFindFirstPixelData */

/*
 * tFindNextPixelData - find the next pixeldata if a PNG image
 *
 * returns the length of the pixeldata or -1 in case of error
 */
static size_t
tFindNextPixelData(FILE *pFile, size_t tMaxBytes, size_t *ptSkipped)
{
	fail(pFile == NULL);
	fail(tMaxBytes == 0);
	fail(ptSkipped == NULL);

	if (tMaxBytes < 4) {
		DBG_DEC(tMaxBytes);
		return (size_t)-1;
	}

	/* Skip over the crc */
	(void)tSkipBytes(pFile, 4);
	*ptSkipped = 4;

	return tSkipToData(pFile, tMaxBytes, ptSkipped);
} /* end of tFindNextPixelData */

#if defined(DEBUG)
/*
 * vCopy2File
 */
static void
vCopy2File(FILE *pFile, ULONG ulFileOffset, size_t tPictureLen)
{
	FILE	*pOutFile;
	size_t	tIndex;
	int	iTmp;
	char	szFilename[30];

	if (!bSetDataOffset(pFile, ulFileOffset)) {
		return;
	}

	sprintf(szFilename, "/tmp/pic/pic%04d.png", ++iPicCounter);
	pOutFile = fopen(szFilename, "wb");
	if (pOutFile == NULL) {
		return;
	}
	for (tIndex = 0; tIndex < tPictureLen; tIndex++) {
		iTmp = iNextByte(pFile);
		if (putc(iTmp, pOutFile) == EOF) {
			break;
		}
	}
	(void)fclose(pOutFile);
} /* end of vCopy2File */
#endif /* DEBUG */

/*
 * bTranslatePNG - translate a PNG image
 *
 * This function translates an image from png to eps
 *
 * return TRUE when sucessful, otherwise FALSE
 */
BOOL
bTranslatePNG(diagram_type *pDiag, FILE *pFile,
	ULONG ulFileOffset, size_t tPictureLen, const imagedata_type *pImg)
{
	size_t	tMaxBytes, tDataLength, tSkipped;

#if defined(DEBUG)
	vCopy2File(pFile, ulFileOffset, tPictureLen);
#endif /* DEBUG */

	/* Seek to start position of PNG data */
	if (!bSetDataOffset(pFile, ulFileOffset)) {
		return FALSE;
	}

	tMaxBytes = tPictureLen;
	tDataLength = tFindFirstPixelData(pFile, tMaxBytes, &tSkipped);
	if (tDataLength == (size_t)-1) {
		return FALSE;
	}

	vImagePrologue(pDiag, pImg);
	do {
		tMaxBytes -= tSkipped;
		vASCII85EncodeArray(pFile, pDiag->pOutFile, tDataLength);
		tMaxBytes -= tDataLength;
		tDataLength = tFindNextPixelData(pFile, tMaxBytes, &tSkipped);
	} while (tDataLength != (size_t)-1);
	vASCII85EncodeByte(pDiag->pOutFile, EOF);
	vImageEpilogue(pDiag);

	return TRUE;
} /* end of bTranslatePNG */