Subversion Repositories ipe_artfile_utils

Compare Revisions

No changes between revisions

Regard whitespace Rev 1 → Rev 2

/trunk/ipe_artfile_packer_ipe16_pip.c
0,0 → 1,173
/**
* ART file packer by Daniel Marschall, ViaThinkSoft (C) 2014-2018
* Supports:
* - Panic in the Park - The Interactive Game by Imagination Pilots
* - Where's Waldo? At the Circus (Waldo1)
* Revision: 2018-02-15
**/
 
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <math.h>
 
#include "ipe_artfile_packer_ipe16_pip.h"
#include "ipe16_artfile.h"
#include "ipe16_bmpimport.h"
#include "ipe16_lzw_encoder.h"
 
#define MAX_FILE 256
 
bool pip_pack_art(const char* szSrcFolder, FILE* fobArt, const int verbosity) {
bool bEverythingOK = true;
 
char szIndexFilename[MAX_FILE];
sprintf(szIndexFilename, "%s/index.txt", szSrcFolder);
FILE* fitIndex = fopen(szIndexFilename, "rt");
if (!fitIndex) {
fprintf(stderr, "Cannot open %s\n", szIndexFilename);
return false;
}
 
#define MAX_LINE 1024
char line[MAX_LINE];
int cItems = 0;
while (fgets(line, sizeof(line), fitIndex)) {
if (strlen(line) == 0) continue;
++cItems;
}
if (verbosity >= 1) printf("%s contains %d entries\n", szIndexFilename, cItems); // TODO: don't print double /
 
Ipe16FileHeader bfh;
memset(&bfh, 0x00, sizeof(bfh));
strcpy(bfh.magic, IPE16_MAGIC_ART);
bfh.dummy = IPE16_MAGIC_DUMMY;
bfh.numHeaderEntries = cItems+1;
 
Ipe16PictureEntryHeader peh[cItems];
memset(&peh, 0x00, sizeof(peh));
 
PipPictureHeader ph[cItems];
memset(&ph, 0x00, sizeof(ph));
 
// We need to write the (still empty) headers, so we can use ftell() to determine the offsets correctly
// These headers are currently just dummies. They will be rewritten after all pictures are processed
fwrite(&bfh, sizeof(bfh), 1, fobArt);
fwrite(&peh, sizeof(peh), 1, fobArt);
 
fseek(fitIndex, 0, SEEK_SET);
int curItem = 0;
Ipe16LZWEncoder* lzwEncoder = NULL;
while (fgets(line, sizeof(line), fitIndex)) {
// If something fails, we discard the item, but continue in building the file!
#define FAIL_CONTINUE { memset(&peh[curItem], 0x00, sizeof(peh[curItem])); bEverythingOK=false; continue; }
 
const char* szDelimiters = " \t\r\n";
char* szPaletteType = strtok(&line[0], szDelimiters);
char* szCompressionType = strtok(NULL, szDelimiters);
char* szName = strtok(NULL, szDelimiters);
char* szFilename = strtok(NULL, szDelimiters);
char* szOffsetX = strtok(NULL, szDelimiters);
int iOffsetX = (szOffsetX != NULL) ? atoi(szOffsetX) : 0;
char* szOffsetY = strtok(NULL, szDelimiters);
int iOffsetY = (szOffsetY != NULL) ? atoi(szOffsetY) : 0;
 
if (strlen(szPaletteType) != 1) {
fprintf(stderr, "ERROR: Palette type (argument 1) at line %d is not valid (must be 1 char)\n", curItem+1);
FAIL_CONTINUE;
}
const char chPaletteType = *szPaletteType;
 
if ((chPaletteType != IPE16_PALETTETYPE_ATTACHED) && (chPaletteType != IPE16_PALETTETYPE_PARENT)) {
fprintf(stderr, "ERROR: Unknown palette type '%c' at line %d\n", chPaletteType, curItem+1);
FAIL_CONTINUE;
}
 
if (strlen(szCompressionType) != 1) {
fprintf(stderr, "ERROR: Compression type (argument 2) at line %d is not valid (must be 1 char)\n", curItem+1);
FAIL_CONTINUE;
}
const char chCompressionType = *szCompressionType;
 
if (strlen(szName) > IPE16_NAME_SIZE) {
fprintf(stderr, "ERROR: Name %s is too long (max %d chars allowed)\n", szName, IPE16_NAME_SIZE);
FAIL_CONTINUE;
}
 
strcpy(peh[curItem].name, szName);
peh[curItem].paletteType = chPaletteType;
peh[curItem].offset = ftell(fobArt);
peh[curItem].size = 0; // will be increased later
 
if (verbosity >= 1) printf("Process %s at offset %x\n", szName, peh[curItem].offset);
 
// Read bitmap
 
const bool colorTableExisting = (chPaletteType == IPE16_PALETTETYPE_ATTACHED);
 
char szBitmapFilename[MAX_FILE];
sprintf(szBitmapFilename, "%s/%s", szSrcFolder, szFilename);
FILE* fibBitmap = fopen(szBitmapFilename, "rb");
if (!fibBitmap) {
fprintf(stderr, "ERROR: cannot open '%s'\n", szFilename);
FAIL_CONTINUE;
}
 
Ipe16BmpImportData result={0};
if (!ipe16_bmp_import(fibBitmap, &result)) {
fprintf(stderr, "Error at %s: %s\n", szFilename, result.error);
fclose(fibBitmap);
ipe16_free_bmpimport_result(&result);
FAIL_CONTINUE;
}
 
ph[curItem].compressionType = chCompressionType;
ph[curItem].offsetX = iOffsetX;
ph[curItem].offsetY = iOffsetY;
ph[curItem].width = result.width;
ph[curItem].height = result.height;
fwrite(&ph[curItem], sizeof(ph[curItem]), 1, fobArt);
peh[curItem].size += sizeof(ph[curItem]);
 
// Write picture data
 
size_t tmpBefore = ftell(fobArt);
if (chCompressionType == PIP_COMPRESSIONTYPE_LZW) {
if (!lzwEncoder) lzwEncoder = new_ipe16lzw_encoder();
ipe16lzw_encode(fobArt, lzwEncoder, result.bmpData, result.bmpDataSize);
} else if (chCompressionType == PIP_COMPRESSIONTYPE_NONE) {
fwrite(result.bmpData, result.bmpDataSize, 1, fobArt);
} else {
fprintf(stderr, "Unknown compression type '%c' at line %d\n", chCompressionType, curItem+1);
fclose(fibBitmap);
ipe16_free_bmpimport_result(&result);
FAIL_CONTINUE;
}
peh[curItem].size += ftell(fobArt)-tmpBefore;
 
if (colorTableExisting) {
fwrite(result.colorTable, sizeof(*result.colorTable), 1, fobArt);
peh[curItem].size += sizeof(*result.colorTable);
}
 
// Free and continue
 
fclose(fibBitmap);
ipe16_free_bmpimport_result(&result);
 
++curItem;
}
if (lzwEncoder) del_ipe16lzw_encoder(lzwEncoder);
fclose(fitIndex);
 
bfh.totalFileSize = ftell(fobArt);
 
fseek(fobArt, 0, SEEK_SET);
fwrite(&bfh, sizeof(bfh), 1, fobArt);
fwrite(&peh, sizeof(peh), 1, fobArt);
 
fclose(fobArt);
 
return bEverythingOK;
}
Property changes:
Added: svn:mime-type
+text/x-csrc
\ No newline at end of property