| // ========================================================== |
| // KOALA Loader |
| // |
| // Design and implementation by |
| // - Floris van den Berg (flvdberg@wxs.nl) |
| // |
| // This file is part of FreeImage 3 |
| // |
| // COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY |
| // OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES |
| // THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE |
| // OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED |
| // CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT |
| // THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY |
| // SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL |
| // PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER |
| // THIS DISCLAIMER. |
| // |
| // Use at your own risk! |
| // ========================================================== |
| |
| #include "FreeImage.h" |
| #include "Utilities.h" |
| |
| // ---------------------------------------------------------- |
| // Constants + headers |
| // ---------------------------------------------------------- |
| |
| #ifdef _WIN32 |
| #pragma pack(push, 1) |
| #else |
| #pragma pack(1) |
| #endif |
| |
| typedef struct tagKOALA { |
| BYTE image[8000]; // pixmap image |
| BYTE colour1[1000]; // first colourmap (colour 1 and 2) |
| BYTE colour2[1000]; // second colourmap (colour 3) |
| BYTE background; // background colour |
| } koala_t; |
| |
| struct colour_t { |
| int r; |
| int g; |
| int b; |
| }; |
| |
| #ifdef _WIN32 |
| #pragma pack(pop) |
| #else |
| #pragma pack() |
| #endif |
| |
| // ---------------------------------------------------------- |
| |
| #define CBM_WIDTH 320 |
| #define CBM_HEIGHT 200 |
| |
| // ---------------------------------------------------------- |
| |
| const colour_t c64colours[16] = { |
| { 0, 0, 0 }, // Black |
| { 255, 255, 255 }, // White |
| { 170, 17, 17 }, // Red |
| { 12, 204, 204 }, // Cyan |
| { 221, 51, 221 }, // Purple |
| { 0, 187, 0 }, // Green |
| { 0, 0, 204 }, // Blue |
| { 255, 255, 140 }, // Yellow |
| { 204, 119, 34 }, // Orange |
| { 136, 68, 0 }, // Brown |
| { 255, 153, 136 }, // Light red |
| { 92, 92, 92 }, // Gray 1 |
| { 170, 170, 170 }, // Gray 2 |
| { 140, 255, 178 }, // Light green |
| { 39, 148, 255 }, // Light blue |
| { 196, 196, 196 } // Gray 3 |
| }; |
| |
| // ========================================================== |
| // Plugin Interface |
| // ========================================================== |
| |
| static int s_format_id; |
| |
| // ========================================================== |
| // Plugin Implementation |
| // ========================================================== |
| |
| const char * DLL_CALLCONV |
| Format() { |
| return "KOALA"; |
| } |
| |
| const char * DLL_CALLCONV |
| Description() { |
| return "C64 Koala Graphics"; |
| } |
| |
| const char * DLL_CALLCONV |
| Extension() { |
| return "koa"; |
| } |
| |
| const char * DLL_CALLCONV |
| RegExpr() { |
| return NULL; |
| } |
| |
| static const char * DLL_CALLCONV |
| MimeType() { |
| return "image/x-koala"; |
| } |
| |
| static BOOL DLL_CALLCONV |
| Validate(FreeImageIO *io, fi_handle handle) { |
| BYTE koala_signature[] = { 0x00, 0x60 }; |
| BYTE signature[2] = { 0, 0 }; |
| |
| io->read_proc(signature, 1, sizeof(koala_signature), handle); |
| |
| return (memcmp(koala_signature, signature, sizeof(koala_signature)) == 0); |
| } |
| |
| static BOOL DLL_CALLCONV |
| SupportsExportDepth(int depth) { |
| return FALSE; |
| } |
| |
| static BOOL DLL_CALLCONV |
| SupportsExportType(FREE_IMAGE_TYPE type) { |
| return FALSE; |
| } |
| |
| // ---------------------------------------------------------- |
| |
| FIBITMAP * DLL_CALLCONV |
| Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { |
| if (handle) { |
| koala_t image; |
| |
| // read the load address |
| |
| unsigned char load_address[2]; // highbit, lowbit |
| |
| io->read_proc(&load_address, 1, 2, handle); |
| |
| // if the load address is correct, skip it. otherwise ignore the load address |
| |
| if ((load_address[0] != 0x00) || (load_address[1] != 0x60)) { |
| ((BYTE *)&image)[0] = load_address[0]; |
| ((BYTE *)&image)[1] = load_address[1]; |
| |
| io->read_proc((BYTE *)&image + 2, 1, 10001 - 2, handle); |
| } else { |
| io->read_proc(&image, 1, 10001, handle); |
| } |
| |
| // build DIB in memory |
| |
| FIBITMAP *dib = FreeImage_Allocate(CBM_WIDTH, CBM_HEIGHT, 4); |
| |
| if (dib) { |
| // write out the commodore 64 color palette |
| |
| RGBQUAD *palette = FreeImage_GetPalette(dib); |
| |
| for (int i = 0; i < 16; i++) { |
| palette[i].rgbBlue = (BYTE)c64colours[i].b; |
| palette[i].rgbGreen = (BYTE)c64colours[i].g; |
| palette[i].rgbRed = (BYTE)c64colours[i].r; |
| } |
| |
| // write out bitmap data |
| |
| BYTE pixel_mask[4] = { 0xc0, 0x30, 0x0c, 0x03 }; |
| BYTE pixel_displacement[4] = { 6, 4, 2, 0 }; |
| int pixel, index, colourindex; |
| unsigned char found_color = 0; |
| |
| for (int y = 0; y < 200; y++) { |
| for (int x = 0; x < 160; x++) { |
| // Get value of pixel at (x,y) |
| |
| index = (x / 4) * 8 + (y % 8) + (y / 8) * CBM_WIDTH; |
| colourindex = (x / 4) + (y / 8) * 40; |
| pixel = (image.image[index] & pixel_mask[x % 4]) >> pixel_displacement[x % 4]; |
| |
| // Retrieve RGB values |
| |
| switch (pixel) { |
| case 0: // Background |
| found_color = image.background; |
| break; |
| |
| case 1: // Colour 1 |
| found_color = image.colour1[colourindex] >> 4; |
| break; |
| |
| case 2: // Colour 2 |
| found_color = image.colour1[colourindex] & 0xf; |
| break; |
| |
| case 3: // Colour 3 |
| found_color = image.colour2[colourindex] & 0xf; |
| break; |
| }; |
| |
| *(FreeImage_GetScanLine(dib, CBM_HEIGHT - y - 1) + x) = (found_color << 4) | found_color; |
| } |
| } |
| |
| return dib; |
| } |
| } |
| |
| return NULL; |
| } |
| |
| // ========================================================== |
| // Init |
| // ========================================================== |
| |
| void DLL_CALLCONV |
| InitKOALA(Plugin *plugin, int format_id) { |
| s_format_id = format_id; |
| |
| plugin->format_proc = Format; |
| plugin->description_proc = Description; |
| plugin->extension_proc = Extension; |
| plugin->regexpr_proc = RegExpr; |
| plugin->open_proc = NULL; |
| plugin->close_proc = NULL; |
| plugin->pagecount_proc = NULL; |
| plugin->pagecapability_proc = NULL; |
| plugin->load_proc = Load; |
| plugin->save_proc = NULL; |
| plugin->validate_proc = Validate; |
| plugin->mime_proc = MimeType; |
| plugin->supports_export_bpp_proc = SupportsExportDepth; |
| plugin->supports_export_type_proc = SupportsExportType; |
| plugin->supports_icc_profiles_proc = NULL; |
| } |