Subversion Repositories ipe_artfile_utils

Rev

Blame | Last modification | View Log | RSS feed

  1. /**
  2.  * Bitmap Import for Imagination Pilots Entertainment 16-bit games (IPE16)
  3.  * - Blown Away - The Interactive Game by Imagination Pilots (BA)
  4.  * - Panic in the Park - The Interactive Game by Imagination Pilots (PiP)
  5.  * - Where's Waldo? At the Circus (Waldo1)
  6.  * ART file packer and unpacker by Daniel Marschall, ViaThinkSoft (C) 2014-2018
  7.  * Revision: 2018-02-15
  8.  **/
  9.  
  10. #include <stdio.h>
  11. #include <stdint.h>
  12. #include <stdbool.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <assert.h>
  16.  
  17. #include "bitmap.h"
  18. #include "ipe16_bmpimport.h"
  19.  
  20. Ipe16ColorTableEntry rgbquad_to_ipe16_rgb(RGBQUAD rq) {
  21.         Ipe16ColorTableEntry cte;
  22.         cte.r = rq.rgbRed;
  23.         cte.g = rq.rgbGreen;
  24.         cte.b = rq.rgbBlue;
  25.         return cte;
  26. }
  27.  
  28. bool ipe16_bmp_import(FILE* fibBitmap, Ipe16BmpImportData* result) {
  29.         BITMAPFILEHEADER bitmapFileHeader;
  30.         BITMAPINFOHEADER bitmapInfoHeader;
  31.  
  32.         #define EXIT_ERROR(msg) { sprintf(result->error, msg); return false; }
  33.  
  34.         fseek(fibBitmap, 0, SEEK_SET);
  35.  
  36.         if (!fread(&bitmapFileHeader, sizeof(BITMAPFILEHEADER), 1, fibBitmap) ||
  37.             (bitmapFileHeader.bfType != BI_SIGNATURE) ||
  38.             !fread(&bitmapInfoHeader, sizeof(BITMAPINFOHEADER), 1, fibBitmap)) {
  39.                 EXIT_ERROR("Not a bitmap file");
  40.         }
  41.  
  42.         if (bitmapInfoHeader.biCompression != BI_RGB) {
  43.                 EXIT_ERROR("At the moment, only uncompressed files can be read.");
  44.         }
  45.  
  46.         if (bitmapInfoHeader.biBitCount != 8) {
  47.                 EXIT_ERROR("The color depth has to be 8 bpp.");
  48.         }
  49.  
  50.         Ipe16ColorTable* ct = malloc(sizeof(Ipe16ColorTable));
  51.         #define NUM_COLORS 256
  52.         RGBQUAD rgba_colortable[NUM_COLORS];
  53.         if (!fread(&rgba_colortable, sizeof(rgba_colortable), 1, fibBitmap)) {
  54.                 EXIT_ERROR("Error reading color table.");
  55.         }
  56.         int i;
  57.         for (i=0; i<NUM_COLORS; ++i) {
  58.                 Ipe16ColorTableEntry x;
  59.                 x = rgbquad_to_ipe16_rgb(rgba_colortable[i]);
  60.                 ct->colors[i] = x;
  61.         }
  62.  
  63.         fseek(fibBitmap, bitmapFileHeader.bfOffBits, SEEK_SET);
  64.  
  65.         const uint32_t realwidth = bitmapInfoHeader.biWidth;
  66.         const uint32_t realheight = abs(bitmapInfoHeader.biHeight);
  67.         const size_t bmpDataSize = realwidth*realheight;
  68.         unsigned char* bmpData = (unsigned char*)malloc(bmpDataSize);
  69.         assert(bmpData != NULL);
  70.         const int padded_width = (bitmapInfoHeader.biWidth + 3) & ~0x03; // http://stackoverflow.com/a/2022194/3544341
  71.         unsigned char* bmpLine = (unsigned char*)malloc(padded_width);
  72.         assert(bmpLine != NULL);
  73.         int h;
  74.         for (h=0; h<realheight; ++h) {
  75.                 if (fread(bmpLine, padded_width, 1, fibBitmap) != 1) {
  76.                         free(bmpLine);
  77.                         free(bmpData);
  78.                         free(ct);
  79.                         EXIT_ERROR("Error while reading pixel data.");
  80.                 }
  81.                 int idx;
  82.                 if (bitmapInfoHeader.biHeight > 0) {
  83.                         // "bottom-up" (most usual)
  84.                         // Convert to "top-down":
  85.                         idx = (realheight-1)-h;
  86.                 } else {
  87.                         // "top-down"
  88.                         idx = h;
  89.                 }
  90.                 assert(idx*realwidth >= 0);
  91.                 memcpy(bmpData+idx*realwidth, bmpLine, realwidth);
  92.         }
  93.         free(bmpLine);
  94.  
  95.         result->colorTable = ct;
  96.         result->bmpData = bmpData;
  97.         result->bmpDataSize = bmpDataSize;
  98.         result->width = realwidth;
  99.         result->height = realheight;
  100.         result->error[0] = 0;
  101.         return true;
  102. }
  103.  
  104. void ipe16_free_bmpimport_result(Ipe16BmpImportData *res) {
  105.         if (res->colorTable) free(res->colorTable);
  106.         if (res->bmpData) free(res->bmpData);
  107. }
  108.  
  109.