1 #include <stdint.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <stdio.h>
5 #include "shadowdive/error.h"
6 #include "shadowdive/palette.h"
7 
sd_palette_create(sd_palette * pal)8 int sd_palette_create(sd_palette *pal) {
9     if(pal == NULL) {
10         return SD_INVALID_INPUT;
11     }
12     memset(pal, 0, sizeof(sd_palette));
13     return SD_SUCCESS;
14 }
15 
sd_palette_free(sd_palette * pal)16 void sd_palette_free(sd_palette *pal) {}
17 
sd_palette_resolve_color(uint8_t r,uint8_t g,uint8_t b,const sd_palette * pal)18 unsigned char sd_palette_resolve_color(uint8_t r, uint8_t g, uint8_t b, const sd_palette *pal) {
19     for(unsigned int i = 0; i < 256; i++) {
20         uint8_t red = pal->data[i][0] & 0xff;
21         uint8_t green = pal->data[i][1] & 0xff;
22         uint8_t blue = pal->data[i][2] & 0xff;
23         if(red == r && blue == b && green == g) {
24             return i;
25         }
26     }
27     return 0;
28 }
29 
sd_palette_to_gimp_palette(const sd_palette * palette,const char * filename)30 int sd_palette_to_gimp_palette(const sd_palette *palette, const char *filename) {
31     sd_writer *w;
32     const unsigned char *d;
33     unsigned char r,g,b;
34     int i;
35 
36     if(palette == NULL || filename == NULL) {
37         return SD_INVALID_INPUT;
38     }
39 
40     if(!(w = sd_writer_open(filename))) {
41         return SD_FILE_OPEN_ERROR;
42     }
43 
44     sd_write_fprintf(w, "GIMP Palette\n");
45     sd_write_fprintf(w, "Name: %s\n", filename);
46     sd_write_fprintf(w, "#\n");
47     for(i = 0; i < 255; i++) {
48         d = palette->data[i];
49         r = d[0] & 0xff;
50         g = d[1] & 0xff;
51         b = d[2] & 0xff;
52         sd_write_fprintf(w, "%3u %3u %3u\n", r, g, b);
53     }
54 
55     sd_writer_close(w);
56     return SD_SUCCESS;
57 }
58 
sd_palette_from_gimp_palette(sd_palette * palette,const char * filename)59 int sd_palette_from_gimp_palette(sd_palette *palette, const char *filename) {
60     sd_reader *rd;
61     char tmp[128];
62     int i;
63 
64     if(palette == NULL || filename == NULL) {
65         return SD_INVALID_INPUT;
66     }
67 
68     if(!(rd = sd_reader_open(filename))) {
69         return SD_FILE_OPEN_ERROR;
70     }
71 
72     // Read and match header
73     if(!sd_match(rd, "GIMP Palette\n", 13)) {
74         sd_reader_close(rd);
75         return SD_FILE_INVALID_TYPE;
76     }
77     while(1) {
78         sd_read_line(rd, tmp, 128);
79         if(!sd_reader_ok(rd)) {
80             sd_reader_close(rd);
81             return SD_FILE_INVALID_TYPE;
82         }
83         if(tmp[0] == '#') {
84             break;
85         }
86     }
87 
88     // Read data
89     for(i = 0; i < 255; i++) {
90         sd_read_line(rd, tmp, 128);
91         tmp[3] = 0;
92         tmp[7] = 0;
93         tmp[11] = 0;
94         palette->data[i][0] = atoi(tmp + 0);
95         palette->data[i][1] = atoi(tmp + 4);
96         palette->data[i][2] = atoi(tmp + 8);
97     }
98 
99     sd_reader_close(rd);
100     return SD_SUCCESS;
101 }
102 
sd_palette_load_range(sd_reader * reader,sd_palette * palette,int index_start,int index_count)103 int sd_palette_load_range(sd_reader *reader, sd_palette *palette, int index_start, int index_count) {
104     char d[3];
105     for(int i = index_start; i < index_start + index_count; i++) {
106         sd_read_buf(reader, d, 3);
107         palette->data[i][0] = ((d[0] << 2) | ((d[0] & 0x30) >> 4));
108         palette->data[i][1] = ((d[1] << 2) | ((d[1] & 0x30) >> 4));
109         palette->data[i][2] = ((d[2] << 2) | ((d[2] & 0x30) >> 4));
110     }
111     return SD_SUCCESS;
112 }
113 
sd_palette_mload_range(sd_mreader * reader,sd_palette * palette,int index_start,int index_count)114 int sd_palette_mload_range(sd_mreader *reader, sd_palette *palette, int index_start, int index_count) {
115     char d[3];
116     for(int i = index_start; i < index_start + index_count; i++) {
117         sd_mread_buf(reader, d, 3);
118         palette->data[i][0] = ((d[0] << 2) | ((d[0] & 0x30) >> 4));
119         palette->data[i][1] = ((d[1] << 2) | ((d[1] & 0x30) >> 4));
120         palette->data[i][2] = ((d[2] << 2) | ((d[2] & 0x30) >> 4));
121     }
122     return SD_SUCCESS;
123 }
124 
sd_palette_load(sd_reader * reader,sd_palette * palette)125 int sd_palette_load(sd_reader *reader, sd_palette *palette) {
126     sd_palette_load_range(reader, palette, 0, 256);
127     sd_read_buf(reader, (char*)palette->remaps, 19*256);
128     return SD_SUCCESS;
129 }
130 
sd_palette_save_range(sd_writer * writer,const sd_palette * palette,int index_start,int index_count)131 void sd_palette_save_range(sd_writer *writer, const sd_palette *palette, int index_start, int index_count) {
132     const unsigned char *d;
133     for(int i = index_start; i < index_start + index_count; i++) {
134         d = palette->data[i];
135         // for some reason, we need to mask off the high bits or the bitshift doesn't work
136         sd_write_ubyte(writer, (d[0] & 0xff) >> 2);
137         sd_write_ubyte(writer, (d[1] & 0xff) >> 2);
138         sd_write_ubyte(writer, (d[2] & 0xff) >> 2);
139     }
140 }
141 
sd_palette_msave_range(sd_mwriter * writer,const sd_palette * palette,int index_start,int index_count)142 void sd_palette_msave_range(sd_mwriter *writer, const sd_palette *palette, int index_start, int index_count) {
143     const unsigned char *d;
144     for(int i = index_start; i < index_start + index_count; i++) {
145         d = palette->data[i];
146         // for some reason, we need to mask off the high bits or the bitshift doesn't work
147         sd_mwrite_ubyte(writer, (d[0] & 0xff) >> 2);
148         sd_mwrite_ubyte(writer, (d[1] & 0xff) >> 2);
149         sd_mwrite_ubyte(writer, (d[2] & 0xff) >> 2);
150     }
151 }
152 
sd_palette_save(sd_writer * writer,const sd_palette * palette)153 void sd_palette_save(sd_writer *writer, const sd_palette *palette) {
154     sd_palette_save_range(writer, palette, 0, 256);
155     sd_write_buf(writer, (char*)palette->remaps, 19*256);
156 }
157