Subversion Repositories ipe_artfile_utils

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 daniel-mar 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