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 |