Subversion Repositories ipe_artfile_utils

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 daniel-mar 1
/**
2
 * Bitmap Export 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 <stdlib.h>
13
#include <string.h>
14
#include <assert.h>
15
 
16
#include "ipe16_bmpexport.h"
17
 
18
#define BMP_LINE_PADDING 4
19
 
20
// Windows 98 does not support top-down bitmaps, so we need to flip everything
21
#define USE_BOTTOMUP
22
 
23
RGBQUAD ipe16_rgb_to_rgbquad(Ipe16ColorTableEntry cte) {
24
        RGBQUAD ret;
25
        ret.rgbRed   = cte.r;
26
        ret.rgbGreen = cte.g;
27
        ret.rgbBlue  = cte.b;
28
        ret.rgbReserved = 0;
29
        return ret;
30
}
31
 
32
void ipe16_write_bmp(FILE* output, unsigned int width, unsigned int height, unsigned char* imagedata, size_t imagedata_len, Ipe16ColorTable ct) {
33
 
34
        #ifdef USE_BOTTOMUP
35
        const size_t bmpDataSize = width*height;
36
        unsigned char* bmpData = (unsigned char*)malloc(bmpDataSize);
37
        assert(bmpData != NULL);
38
        int h;
39
        for (h=0; h<height; ++h) {
40
                int idx_dest = (height-1)-h;
41
                int idx_src  = h;
42
                assert(idx_src*width >= 0);
43
                assert(idx_dest*width >= 0);
44
                memcpy(bmpData+idx_dest*width, imagedata+idx_src*width, width);
45
        }
46
        imagedata = bmpData;
47
        #endif
48
 
49
        // Each line must be padded to a multiple of 4
50
        int pad = (BMP_LINE_PADDING - (width % BMP_LINE_PADDING)) % BMP_LINE_PADDING;
51
        int newwidth = width+pad;
52
        int newsize = newwidth * height;
53
        unsigned char* padded_imagedata = (unsigned char*)malloc(newsize);
54
        int i;
55
        for (i=0; i<height; ++i) {
56
                int offset = newwidth*i;
57
                memcpy(&padded_imagedata[offset], imagedata, width);
58
                memset(&padded_imagedata[offset+width], 0, pad);
59
                imagedata += width;
60
        }
61
 
62
        // Color table in a bitmap is BGR0, while Blown Away uses RGB
63
        const unsigned int NUM_COLORS = sizeof(ct.colors)/sizeof(ct.colors[0]);
64
        RGBQUAD rgba_colortable[NUM_COLORS];
65
        for (i=0; i<NUM_COLORS; ++i) {
66
                rgba_colortable[i] = ipe16_rgb_to_rgbquad(ct.colors[i]);
67
        }
68
 
69
        BITMAPFILEHEADER bfh;
70
        bfh.bfType = BI_SIGNATURE;
71
        bfh.bfSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+sizeof(rgba_colortable)+newsize;
72
        bfh.bfReserved1 = 0;
73
        bfh.bfReserved2 = 0;
74
        bfh.bfOffBits = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+sizeof(rgba_colortable);
75
        fwrite(&bfh, sizeof(bfh), 1, output);
76
 
77
        BITMAPINFOHEADER bih;
78
        bih.biSize = sizeof(BITMAPINFOHEADER);
79
        bih.biWidth = width;
80
        #ifdef USE_BOTTOMUP
81
        bih.biHeight = height; // (positive = "bottom-up"-Bitmap)
82
        #else
83
        bih.biHeight = -height; // (negative = "top-down"-Bitmap)
84
        #endif
85
        bih.biPlanes = 1;
86
        bih.biBitCount = 8;
87
        bih.biCompression = BI_RGB;
88
        bih.biSizeImage = 0;
89
        bih.biXPelsPerMeter = 0;
90
        bih.biYPelsPerMeter = 0;
91
        bih.biClrUsed = 0;
92
        bih.biClrImportant = 0;
93
        fwrite(&bih, sizeof(bih), 1, output);
94
 
95
        // Color table
96
        fwrite(rgba_colortable, sizeof(rgba_colortable), 1, output);
97
 
98
        // Image data
99
        fwrite(padded_imagedata, newsize, 1, output);
100
 
101
        free(padded_imagedata);
102
        #ifdef USE_BOTTOMUP
103
        free(bmpData);
104
        #endif
105
}
106