Library to control a Graphics TFT connected to 4-wire SPI - revised for the Raio RA8875 Display Controller.

Dependents:   FRDM_RA8875_mPaint RA8875_Demo RA8875_KeyPadDemo SignalGenerator ... more

Fork of SPI_TFT by Peter Drescher

See Components - RA8875 Based Display

Enhanced touch-screen support - where it previous supported both the Resistive Touch and Capacitive Touch based on the FT5206 Touch Controller, now it also has support for the GSL1680 Touch Controller.

Offline Help Manual (Windows chm)

/media/uploads/WiredHome/ra8875.zip.bin (download, rename to .zip and unzip)

Committer:
WiredHome
Date:
Tue Feb 11 21:51:42 2020 +0000
Revision:
197:853d08e2fb53
Parent:
196:56820026701b
Child:
198:9b6851107426
General code cleanup.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
WiredHome 197:853d08e2fb53 1
WiredHome 197:853d08e2fb53 2
WiredHome 197:853d08e2fb53 3
WiredHome 197:853d08e2fb53 4 // GIFRender.cpp : Defines the entry point for the console application.
WiredHome 152:a013ac0133e4 5 //
WiredHome 152:a013ac0133e4 6 // The code in this file was initially found online, in a tutorial.
WiredHome 152:a013ac0133e4 7 // It has been revised significantly in this derivative.
WiredHome 152:a013ac0133e4 8 // No copyright claim was found in the code.
WiredHome 152:a013ac0133e4 9 // http://commandlinefanatic.com/cgi-bin/showarticle.cgi?article=art011
WiredHome 152:a013ac0133e4 10 //
WiredHome 152:a013ac0133e4 11
WiredHome 152:a013ac0133e4 12 #include "mbed.h"
WiredHome 152:a013ac0133e4 13
WiredHome 152:a013ac0133e4 14 #include "GraphicsDisplay.h"
WiredHome 152:a013ac0133e4 15
WiredHome 152:a013ac0133e4 16
WiredHome 177:d8e65c0e268a 17 //#define DEBUG "GIF_"
WiredHome 197:853d08e2fb53 18 //
WiredHome 197:853d08e2fb53 19
WiredHome 152:a013ac0133e4 20 // INFO("Stuff to show %d", var); // new-line is automatically appended
WiredHome 152:a013ac0133e4 21 //
WiredHome 152:a013ac0133e4 22 #if (defined(DEBUG) && !defined(TARGET_LPC11U24))
WiredHome 197:853d08e2fb53 23 #define INFO(x, ...) std::printf("[INF %s %4d] " x "\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 197:853d08e2fb53 24 #define WARN(x, ...) std::printf("[WRN %s %4d] " x "\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 197:853d08e2fb53 25 #define ERR(x, ...) std::printf("[ERR %s %4d] " x "\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 152:a013ac0133e4 26 static void HexDump(const char * title, const uint8_t * p, int count) {
WiredHome 152:a013ac0133e4 27 int i;
WiredHome 152:a013ac0133e4 28 char buf[100] = "0000: ";
WiredHome 152:a013ac0133e4 29
WiredHome 152:a013ac0133e4 30 if (*title)
WiredHome 152:a013ac0133e4 31 INFO("%s", title);
WiredHome 152:a013ac0133e4 32 for (i = 0; i<count; ) {
WiredHome 152:a013ac0133e4 33 sprintf(buf + strlen(buf), "%02X ", *(p + i));
WiredHome 152:a013ac0133e4 34 if ((++i & 0x0F) == 0x00) {
WiredHome 152:a013ac0133e4 35 INFO("%s", buf);
WiredHome 152:a013ac0133e4 36 if (i < count)
WiredHome 152:a013ac0133e4 37 sprintf(buf, "%04X: ", i);
WiredHome 152:a013ac0133e4 38 else
WiredHome 152:a013ac0133e4 39 buf[0] = '\0';
WiredHome 152:a013ac0133e4 40 }
WiredHome 152:a013ac0133e4 41 }
WiredHome 152:a013ac0133e4 42 if (strlen(buf))
WiredHome 152:a013ac0133e4 43 INFO("%s", buf);
WiredHome 152:a013ac0133e4 44 }
WiredHome 152:a013ac0133e4 45 #else
WiredHome 152:a013ac0133e4 46 #define INFO(x, ...)
WiredHome 152:a013ac0133e4 47 #define WARN(x, ...)
WiredHome 152:a013ac0133e4 48 #define ERR(x, ...)
WiredHome 152:a013ac0133e4 49 #define HexDump(a, b, c)
WiredHome 152:a013ac0133e4 50 #endif
WiredHome 152:a013ac0133e4 51
WiredHome 152:a013ac0133e4 52
WiredHome 152:a013ac0133e4 53 #define EXTENSION_INTRODUCER 0x21
WiredHome 152:a013ac0133e4 54 #define IMAGE_DESCRIPTOR 0x2C
WiredHome 152:a013ac0133e4 55 #define TRAILER 0x3B
WiredHome 152:a013ac0133e4 56
WiredHome 152:a013ac0133e4 57 #define GRAPHIC_CONTROL 0xF9
WiredHome 152:a013ac0133e4 58 #define APPLICATION_EXTENSION 0xFF
WiredHome 152:a013ac0133e4 59 #define COMMENT_EXTENSION 0xFE
WiredHome 152:a013ac0133e4 60 #define PLAINTEXT_EXTENSION 0x01
WiredHome 152:a013ac0133e4 61
WiredHome 152:a013ac0133e4 62
WiredHome 152:a013ac0133e4 63 typedef struct {
WiredHome 152:a013ac0133e4 64 unsigned char byte;
WiredHome 152:a013ac0133e4 65 int prev;
WiredHome 152:a013ac0133e4 66 int len;
WiredHome 152:a013ac0133e4 67 } dictionary_entry_t;
WiredHome 152:a013ac0133e4 68
WiredHome 152:a013ac0133e4 69 typedef struct {
WiredHome 152:a013ac0133e4 70 unsigned char extension_code;
WiredHome 152:a013ac0133e4 71 unsigned char block_size;
WiredHome 152:a013ac0133e4 72 } extension_t;
WiredHome 152:a013ac0133e4 73 const uint16_t extension_size = 2;
WiredHome 152:a013ac0133e4 74
WiredHome 152:a013ac0133e4 75 typedef struct {
WiredHome 152:a013ac0133e4 76 unsigned char fields;
WiredHome 152:a013ac0133e4 77 unsigned short delay_time;
WiredHome 152:a013ac0133e4 78 unsigned char transparent_color_index;
WiredHome 152:a013ac0133e4 79 } graphic_control_extension_t;
WiredHome 152:a013ac0133e4 80 const uint16_t graphic_control_extension_size = 4;
WiredHome 152:a013ac0133e4 81
WiredHome 152:a013ac0133e4 82 typedef struct {
WiredHome 152:a013ac0133e4 83 unsigned char application_id[8];
WiredHome 152:a013ac0133e4 84 unsigned char version[3];
WiredHome 152:a013ac0133e4 85 } application_extension_t;
WiredHome 152:a013ac0133e4 86 const uint16_t application_extension_size = 11;
WiredHome 152:a013ac0133e4 87
WiredHome 152:a013ac0133e4 88 typedef struct {
WiredHome 152:a013ac0133e4 89 unsigned short left;
WiredHome 152:a013ac0133e4 90 unsigned short top;
WiredHome 152:a013ac0133e4 91 unsigned short width;
WiredHome 152:a013ac0133e4 92 unsigned short height;
WiredHome 152:a013ac0133e4 93 unsigned char cell_width;
WiredHome 152:a013ac0133e4 94 unsigned char cell_height;
WiredHome 152:a013ac0133e4 95 unsigned char foreground_color;
WiredHome 152:a013ac0133e4 96 unsigned char background_color;
WiredHome 152:a013ac0133e4 97 } plaintext_extension_t;
WiredHome 152:a013ac0133e4 98 const uint16_t plaintext_extension_size = 12;
WiredHome 152:a013ac0133e4 99
WiredHome 152:a013ac0133e4 100
WiredHome 152:a013ac0133e4 101 size_t GraphicsDisplay::read_filesystem_bytes(void * buffer, int numBytes, FILE * fh) {
WiredHome 152:a013ac0133e4 102 size_t bytesRead;
WiredHome 152:a013ac0133e4 103
WiredHome 152:a013ac0133e4 104 bytesRead = fread(buffer, 1, numBytes, fh);
WiredHome 152:a013ac0133e4 105 HexDump("mem", (const uint8_t *) buffer, bytesRead);
WiredHome 152:a013ac0133e4 106 return bytesRead;
WiredHome 152:a013ac0133e4 107 }
WiredHome 152:a013ac0133e4 108
WiredHome 152:a013ac0133e4 109
WiredHome 152:a013ac0133e4 110 /// uncompress_gif the data to memory
WiredHome 152:a013ac0133e4 111 ///
WiredHome 152:a013ac0133e4 112 /// @param[in] code_length is the size of this descriptor field
WiredHome 152:a013ac0133e4 113 /// @param[in] input is a pointer to the input data
WiredHome 152:a013ac0133e4 114 /// @param[in] input_length is the number of bytes in the input.
WiredHome 152:a013ac0133e4 115 /// @param[out] out is where the uncompress_gifed information is written.
WiredHome 152:a013ac0133e4 116 /// @return noerror on success, or failure code
WiredHome 152:a013ac0133e4 117 ///
WiredHome 152:a013ac0133e4 118 RetCode_t GraphicsDisplay::uncompress_gif(int code_length, const unsigned char *input, int input_length, unsigned char *out) {
WiredHome 152:a013ac0133e4 119 int i, bit;
WiredHome 152:a013ac0133e4 120 int code, prev = -1;
WiredHome 152:a013ac0133e4 121 dictionary_entry_t * dictionary;
WiredHome 152:a013ac0133e4 122 int dictionary_ind;
WiredHome 152:a013ac0133e4 123 unsigned int mask = 0x01;
WiredHome 152:a013ac0133e4 124 int reset_code_length;
WiredHome 152:a013ac0133e4 125 int clear_code; // This varies depending on code_length
WiredHome 152:a013ac0133e4 126 int stop_code; // one more than clear code
WiredHome 152:a013ac0133e4 127 int match_len;
WiredHome 152:a013ac0133e4 128
WiredHome 152:a013ac0133e4 129 clear_code = 1 << (code_length);
WiredHome 152:a013ac0133e4 130 stop_code = clear_code + 1;
WiredHome 152:a013ac0133e4 131 reset_code_length = code_length;
WiredHome 152:a013ac0133e4 132
WiredHome 152:a013ac0133e4 133 // Create a dictionary large enough to hold "code_length" entries.
WiredHome 152:a013ac0133e4 134 // Once the dictionary overflows, code_length increases
WiredHome 177:d8e65c0e268a 135 size_t bytes = sizeof(dictionary_entry_t) * (1 << (code_length + 1));
WiredHome 177:d8e65c0e268a 136 INFO("uncompress_gif malloc(%d)", bytes);
WiredHome 177:d8e65c0e268a 137 dictionary = (dictionary_entry_t *) malloc(bytes);
WiredHome 177:d8e65c0e268a 138 if (dictionary == NULL) {
WiredHome 152:a013ac0133e4 139 return not_enough_ram;
WiredHome 177:d8e65c0e268a 140 }
WiredHome 152:a013ac0133e4 141 // Initialize the first 2^code_len entries of the dictionary with their
WiredHome 152:a013ac0133e4 142 // indices. The rest of the entries will be built up dynamically.
WiredHome 152:a013ac0133e4 143
WiredHome 152:a013ac0133e4 144 // Technically, it shouldn't be necessary to initialize the
WiredHome 152:a013ac0133e4 145 // dictionary. The spec says that the encoder "should output a
WiredHome 152:a013ac0133e4 146 // clear code as the first code in the image data stream". It doesn't
WiredHome 152:a013ac0133e4 147 // say must, though...
WiredHome 152:a013ac0133e4 148 for (dictionary_ind = 0; dictionary_ind < (1 << code_length); dictionary_ind++) {
WiredHome 152:a013ac0133e4 149 dictionary[dictionary_ind].byte = (uint8_t) dictionary_ind;
WiredHome 152:a013ac0133e4 150 // XXX this only works because prev is a 32-bit int (> 12 bits)
WiredHome 152:a013ac0133e4 151 dictionary[dictionary_ind].prev = -1;
WiredHome 152:a013ac0133e4 152 dictionary[dictionary_ind].len = 1;
WiredHome 152:a013ac0133e4 153 }
WiredHome 152:a013ac0133e4 154 // 2^code_len + 1 is the special "end" code; don't give it an entry here
WiredHome 152:a013ac0133e4 155 dictionary_ind++;
WiredHome 152:a013ac0133e4 156 dictionary_ind++;
WiredHome 152:a013ac0133e4 157
WiredHome 152:a013ac0133e4 158 // TODO verify that the very last byte is clear_code + 1
WiredHome 152:a013ac0133e4 159 while (input_length) {
WiredHome 152:a013ac0133e4 160 code = 0x0;
WiredHome 152:a013ac0133e4 161 // Always read one more bit than the code length
WiredHome 152:a013ac0133e4 162 for (i = 0; i < (code_length + 1); i++) {
WiredHome 152:a013ac0133e4 163 // This is different than in the file read example; that
WiredHome 152:a013ac0133e4 164 // was a call to "next_bit"
WiredHome 152:a013ac0133e4 165 bit = (*input & mask) ? 1 : 0;
WiredHome 152:a013ac0133e4 166 mask <<= 1;
WiredHome 152:a013ac0133e4 167 if (mask == 0x100) {
WiredHome 152:a013ac0133e4 168 mask = 0x01;
WiredHome 152:a013ac0133e4 169 input++;
WiredHome 152:a013ac0133e4 170 input_length--;
WiredHome 152:a013ac0133e4 171 }
WiredHome 152:a013ac0133e4 172 code = code | (bit << i);
WiredHome 152:a013ac0133e4 173 }
WiredHome 152:a013ac0133e4 174 if (code == clear_code) {
WiredHome 152:a013ac0133e4 175 code_length = reset_code_length;
WiredHome 152:a013ac0133e4 176 dictionary = (dictionary_entry_t *) realloc(dictionary,
WiredHome 152:a013ac0133e4 177 sizeof(dictionary_entry_t) * (1 << (code_length + 1)));
WiredHome 152:a013ac0133e4 178 for (dictionary_ind = 0; dictionary_ind < (1 << code_length); dictionary_ind++) {
WiredHome 152:a013ac0133e4 179 dictionary[dictionary_ind].byte = (uint8_t) dictionary_ind;
WiredHome 152:a013ac0133e4 180 // XXX this only works because prev is a 32-bit int (> 12 bits)
WiredHome 152:a013ac0133e4 181 dictionary[dictionary_ind].prev = -1;
WiredHome 152:a013ac0133e4 182 dictionary[dictionary_ind].len = 1;
WiredHome 152:a013ac0133e4 183 }
WiredHome 152:a013ac0133e4 184 dictionary_ind++;
WiredHome 152:a013ac0133e4 185 dictionary_ind++;
WiredHome 152:a013ac0133e4 186 prev = -1;
WiredHome 152:a013ac0133e4 187 continue;
WiredHome 152:a013ac0133e4 188 } else if (code == stop_code) {
WiredHome 152:a013ac0133e4 189 if (input_length > 1) {
WiredHome 152:a013ac0133e4 190 free(dictionary);
WiredHome 152:a013ac0133e4 191 return not_supported_format;
WiredHome 152:a013ac0133e4 192 }
WiredHome 152:a013ac0133e4 193 break;
WiredHome 152:a013ac0133e4 194 }
WiredHome 152:a013ac0133e4 195
WiredHome 152:a013ac0133e4 196 // Update the dictionary with this character plus the _entry_
WiredHome 152:a013ac0133e4 197 // (character or string) that came before it
WiredHome 152:a013ac0133e4 198 if ((prev > -1) && (code_length < 12)) {
WiredHome 152:a013ac0133e4 199 if (code > dictionary_ind) {
WiredHome 152:a013ac0133e4 200 //fprintf(stderr, "code = %.02x, but dictionary_ind = %.02x\n", code, dictionary_ind);
WiredHome 152:a013ac0133e4 201 free(dictionary);
WiredHome 152:a013ac0133e4 202 return not_supported_format;
WiredHome 152:a013ac0133e4 203 }
WiredHome 152:a013ac0133e4 204 if (code == dictionary_ind) {
WiredHome 152:a013ac0133e4 205 int ptr = prev;
WiredHome 152:a013ac0133e4 206
WiredHome 152:a013ac0133e4 207 while (dictionary[ptr].prev != -1) {
WiredHome 152:a013ac0133e4 208 ptr = dictionary[ptr].prev;
WiredHome 152:a013ac0133e4 209 }
WiredHome 152:a013ac0133e4 210 dictionary[dictionary_ind].byte = dictionary[ptr].byte;
WiredHome 152:a013ac0133e4 211 } else {
WiredHome 152:a013ac0133e4 212 int ptr = code;
WiredHome 152:a013ac0133e4 213 while (dictionary[ptr].prev != -1) {
WiredHome 152:a013ac0133e4 214 ptr = dictionary[ptr].prev;
WiredHome 152:a013ac0133e4 215 }
WiredHome 152:a013ac0133e4 216 dictionary[dictionary_ind].byte = dictionary[ptr].byte;
WiredHome 152:a013ac0133e4 217 }
WiredHome 152:a013ac0133e4 218 dictionary[dictionary_ind].prev = prev;
WiredHome 152:a013ac0133e4 219 dictionary[dictionary_ind].len = dictionary[prev].len + 1;
WiredHome 152:a013ac0133e4 220 dictionary_ind++;
WiredHome 152:a013ac0133e4 221 // GIF89a mandates that this stops at 12 bits
WiredHome 152:a013ac0133e4 222 if ((dictionary_ind == (1 << (code_length + 1))) &&
WiredHome 152:a013ac0133e4 223 (code_length < 11)) {
WiredHome 152:a013ac0133e4 224 code_length++;
WiredHome 152:a013ac0133e4 225 dictionary = (dictionary_entry_t *) realloc(dictionary,
WiredHome 152:a013ac0133e4 226 sizeof(dictionary_entry_t) * (1 << (code_length + 1)));
WiredHome 152:a013ac0133e4 227 }
WiredHome 152:a013ac0133e4 228 }
WiredHome 152:a013ac0133e4 229 prev = code;
WiredHome 152:a013ac0133e4 230 // Now copy the dictionary entry backwards into "out"
WiredHome 152:a013ac0133e4 231 match_len = dictionary[code].len;
WiredHome 152:a013ac0133e4 232 while (code != -1) {
WiredHome 152:a013ac0133e4 233 int pos = dictionary[code].len - 1;
WiredHome 152:a013ac0133e4 234 out[pos] = dictionary[code].byte;
WiredHome 177:d8e65c0e268a 235 //INFO("%p out[%d] = %02X", out, pos, out[pos]);
WiredHome 152:a013ac0133e4 236 if (dictionary[code].prev == code) {
WiredHome 152:a013ac0133e4 237 free(dictionary);
WiredHome 152:a013ac0133e4 238 return not_supported_format;
WiredHome 152:a013ac0133e4 239 }
WiredHome 152:a013ac0133e4 240 code = dictionary[code].prev;
WiredHome 152:a013ac0133e4 241 }
WiredHome 152:a013ac0133e4 242 out += match_len;
WiredHome 152:a013ac0133e4 243 }
WiredHome 152:a013ac0133e4 244 free(dictionary);
WiredHome 152:a013ac0133e4 245 return noerror;
WiredHome 152:a013ac0133e4 246 }
WiredHome 152:a013ac0133e4 247
WiredHome 152:a013ac0133e4 248
WiredHome 152:a013ac0133e4 249 /// read a block
WiredHome 197:853d08e2fb53 250 ///
WiredHome 152:a013ac0133e4 251 /// @param[in] fh is the handle to the gif file.
WiredHome 152:a013ac0133e4 252 /// @param[in] data is a pointer to a pointer to the data being processed.
WiredHome 152:a013ac0133e4 253 /// @return -1 on failure, 0 when done, or >0 as the length of a processed data block
WiredHome 152:a013ac0133e4 254 ///
WiredHome 152:a013ac0133e4 255 int GraphicsDisplay::read_gif_sub_blocks(FILE * fh, unsigned char **data) {
WiredHome 152:a013ac0133e4 256 int data_length;
WiredHome 152:a013ac0133e4 257 int index;
WiredHome 152:a013ac0133e4 258 unsigned char block_size;
WiredHome 152:a013ac0133e4 259
WiredHome 152:a013ac0133e4 260 // Everything following are data sub-blocks, until a 0-sized block is encountered.
WiredHome 152:a013ac0133e4 261 data_length = 0;
WiredHome 152:a013ac0133e4 262 *data = NULL;
WiredHome 152:a013ac0133e4 263 index = 0;
WiredHome 152:a013ac0133e4 264
WiredHome 152:a013ac0133e4 265 while (1) {
WiredHome 152:a013ac0133e4 266 if (read_filesystem_bytes(&block_size, 1, fh) < 1) {
WiredHome 152:a013ac0133e4 267 return -1;
WiredHome 152:a013ac0133e4 268 }
WiredHome 152:a013ac0133e4 269 if (block_size == 0) {
WiredHome 152:a013ac0133e4 270 break;
WiredHome 152:a013ac0133e4 271 }
WiredHome 152:a013ac0133e4 272 data_length += block_size;
WiredHome 152:a013ac0133e4 273 *data = (unsigned char *) realloc(*data, data_length);
WiredHome 152:a013ac0133e4 274 if (data) {
WiredHome 152:a013ac0133e4 275 if (read_filesystem_bytes(*data + index, block_size, fh) < block_size) {
WiredHome 152:a013ac0133e4 276 return -1;
WiredHome 152:a013ac0133e4 277 }
WiredHome 152:a013ac0133e4 278 index += block_size;
WiredHome 152:a013ac0133e4 279 } else {
WiredHome 152:a013ac0133e4 280 return -1;
WiredHome 152:a013ac0133e4 281 }
WiredHome 152:a013ac0133e4 282 }
WiredHome 152:a013ac0133e4 283 return data_length;
WiredHome 152:a013ac0133e4 284 }
WiredHome 152:a013ac0133e4 285
WiredHome 197:853d08e2fb53 286 // color table is encoded as 24-bit values, but we don't need that much space, since
WiredHome 152:a013ac0133e4 287 // the RA8875 is configured as either 8 or 16-bit color.
WiredHome 152:a013ac0133e4 288 //
WiredHome 152:a013ac0133e4 289 RetCode_t GraphicsDisplay::readColorTable(color_t * colorTable, int colorTableSize, FILE * fh) {
WiredHome 152:a013ac0133e4 290 struct {
WiredHome 152:a013ac0133e4 291 uint8_t r;
WiredHome 152:a013ac0133e4 292 uint8_t g;
WiredHome 152:a013ac0133e4 293 uint8_t b;
WiredHome 152:a013ac0133e4 294 } rgb;
WiredHome 152:a013ac0133e4 295 while (colorTableSize--) {
WiredHome 152:a013ac0133e4 296 if (read_filesystem_bytes(&rgb, 3, fh) < 3)
WiredHome 152:a013ac0133e4 297 return not_supported_format;
WiredHome 152:a013ac0133e4 298 *colorTable++ = RGB(rgb.r, rgb.g, rgb.b);
WiredHome 152:a013ac0133e4 299 }
WiredHome 152:a013ac0133e4 300 return noerror;
WiredHome 152:a013ac0133e4 301 }
WiredHome 152:a013ac0133e4 302
WiredHome 152:a013ac0133e4 303 RetCode_t GraphicsDisplay::readGIFImageDescriptor(FILE * fh, gif_image_descriptor_t * imageDescriptor) {
WiredHome 152:a013ac0133e4 304 if (read_filesystem_bytes(imageDescriptor, gif_image_descriptor_size, fh) < gif_image_descriptor_size)
WiredHome 152:a013ac0133e4 305 return not_supported_format;
WiredHome 177:d8e65c0e268a 306 INFO("gif_image_descriptor");
WiredHome 177:d8e65c0e268a 307 INFO(" left: %d", imageDescriptor->image_left_position);
WiredHome 177:d8e65c0e268a 308 INFO(" top: %d", imageDescriptor->image_top_position);
WiredHome 177:d8e65c0e268a 309 INFO(" width: %d", imageDescriptor->image_width);
WiredHome 177:d8e65c0e268a 310 INFO(" height: %d", imageDescriptor->image_height);
WiredHome 177:d8e65c0e268a 311 INFO(" fields: %02Xx", imageDescriptor->fields);
WiredHome 177:d8e65c0e268a 312 INFO(" lct: %2d", (imageDescriptor->fields & 0x80) ? 1 : 0);
WiredHome 177:d8e65c0e268a 313 INFO(" res: %2d", (imageDescriptor->fields & 0x40) ? 1 : 0);
WiredHome 177:d8e65c0e268a 314 INFO(" sort: %2d", (imageDescriptor->fields & 0x20) ? 1 : 0);
WiredHome 177:d8e65c0e268a 315 INFO(" res: %2d", ((imageDescriptor->fields & 0x18) >> 3));
WiredHome 177:d8e65c0e268a 316 INFO("locclrtbl siz: %2d", 1 << ((imageDescriptor->fields & 0x07) + 1));
WiredHome 152:a013ac0133e4 317 if (imageDescriptor->fields & 0x80) {
WiredHome 152:a013ac0133e4 318 local_color_table_size = 1 << ((imageDescriptor->fields & 0x07) + 1);
WiredHome 152:a013ac0133e4 319 local_color_table = (color_t *) malloc(sizeof(color_t) * local_color_table_size);
WiredHome 152:a013ac0133e4 320 if (local_color_table == NULL)
WiredHome 152:a013ac0133e4 321 return not_enough_ram;
WiredHome 152:a013ac0133e4 322 if (readColorTable(local_color_table, local_color_table_size, fh) != noerror) {
WiredHome 152:a013ac0133e4 323 free(local_color_table);
WiredHome 152:a013ac0133e4 324 local_color_table = NULL;
WiredHome 152:a013ac0133e4 325 return not_supported_format;
WiredHome 152:a013ac0133e4 326 }
WiredHome 152:a013ac0133e4 327 }
WiredHome 177:d8e65c0e268a 328 INFO("gif_image_descriptor end.");
WiredHome 152:a013ac0133e4 329 return noerror;
WiredHome 152:a013ac0133e4 330 }
WiredHome 152:a013ac0133e4 331
WiredHome 152:a013ac0133e4 332 /// Process the image section of the GIF file
WiredHome 152:a013ac0133e4 333 ///
WiredHome 152:a013ac0133e4 334 /// @param[in] fh is the handle to the file.
WiredHome 152:a013ac0133e4 335 /// @param[in] uncompress_gifed_data is a pointer to a pointer to where the data will be placed.
WiredHome 152:a013ac0133e4 336 /// @returns true if all went well.
WiredHome 152:a013ac0133e4 337 ///
WiredHome 152:a013ac0133e4 338 RetCode_t GraphicsDisplay::process_gif_image_descriptor(FILE * fh, uint8_t ** uncompress_gifed_data, int width, int height) {
WiredHome 152:a013ac0133e4 339 int compressed_data_length;
WiredHome 152:a013ac0133e4 340 unsigned char *compressed_data = NULL;
WiredHome 152:a013ac0133e4 341 unsigned char lzw_code_size;
WiredHome 152:a013ac0133e4 342 int uncompress_gifed_data_length = 0;
WiredHome 152:a013ac0133e4 343 RetCode_t res = not_supported_format;
WiredHome 152:a013ac0133e4 344 local_color_table_size = 0;
WiredHome 152:a013ac0133e4 345
WiredHome 152:a013ac0133e4 346 if (read_filesystem_bytes(&lzw_code_size, 1, fh) < 1)
WiredHome 152:a013ac0133e4 347 goto done;
WiredHome 177:d8e65c0e268a 348 INFO("lzw_code_size %d", lzw_code_size);
WiredHome 152:a013ac0133e4 349 compressed_data_length = read_gif_sub_blocks(fh, &compressed_data);
WiredHome 152:a013ac0133e4 350 if (compressed_data_length > 0) {
WiredHome 152:a013ac0133e4 351 uncompress_gifed_data_length = width * height;
WiredHome 177:d8e65c0e268a 352 *uncompress_gifed_data = (unsigned char *)malloc(uncompress_gifed_data_length);
WiredHome 177:d8e65c0e268a 353 if (*uncompress_gifed_data == NULL) {
WiredHome 152:a013ac0133e4 354 return not_enough_ram;
WiredHome 177:d8e65c0e268a 355 }
WiredHome 152:a013ac0133e4 356 res = uncompress_gif(lzw_code_size, compressed_data, compressed_data_length, *uncompress_gifed_data);
WiredHome 152:a013ac0133e4 357 }
WiredHome 152:a013ac0133e4 358 done:
WiredHome 152:a013ac0133e4 359 if (compressed_data)
WiredHome 152:a013ac0133e4 360 free(compressed_data);
WiredHome 177:d8e65c0e268a 361 INFO("lzw_code_size end %d", res);
WiredHome 152:a013ac0133e4 362 return res;
WiredHome 152:a013ac0133e4 363 }
WiredHome 152:a013ac0133e4 364
WiredHome 152:a013ac0133e4 365
WiredHome 152:a013ac0133e4 366 int GraphicsDisplay::process_gif_extension(FILE * fh) {
WiredHome 152:a013ac0133e4 367 extension_t extension;
WiredHome 152:a013ac0133e4 368 graphic_control_extension_t gce;
WiredHome 152:a013ac0133e4 369 application_extension_t application;
WiredHome 152:a013ac0133e4 370 plaintext_extension_t plaintext;
WiredHome 152:a013ac0133e4 371 unsigned char *extension_data = NULL;
WiredHome 152:a013ac0133e4 372 /* int extension_data_length; */
WiredHome 152:a013ac0133e4 373
WiredHome 152:a013ac0133e4 374 if (read_filesystem_bytes(&extension, extension_size, fh) < extension_size) {
WiredHome 152:a013ac0133e4 375 return 0;
WiredHome 152:a013ac0133e4 376 }
WiredHome 177:d8e65c0e268a 377 INFO("extension");
WiredHome 177:d8e65c0e268a 378 INFO(" code: %d", extension.extension_code);
WiredHome 177:d8e65c0e268a 379 INFO(" block size: %d", extension.block_size);
WiredHome 152:a013ac0133e4 380 switch (extension.extension_code) {
WiredHome 152:a013ac0133e4 381 case GRAPHIC_CONTROL:
WiredHome 152:a013ac0133e4 382 if (read_filesystem_bytes(&gce, graphic_control_extension_size, fh) < graphic_control_extension_size) {
WiredHome 152:a013ac0133e4 383 return 0;
WiredHome 152:a013ac0133e4 384 }
WiredHome 177:d8e65c0e268a 385 INFO("graphic_control_extension");
WiredHome 177:d8e65c0e268a 386 INFO(" fields: %d", gce.fields);
WiredHome 177:d8e65c0e268a 387 INFO(" delay time: %d", gce.delay_time);
WiredHome 177:d8e65c0e268a 388 INFO(" transparent: %d", gce.transparent_color_index);
WiredHome 152:a013ac0133e4 389 break;
WiredHome 152:a013ac0133e4 390 case APPLICATION_EXTENSION:
WiredHome 152:a013ac0133e4 391 if (read_filesystem_bytes(&application, application_extension_size, fh) < application_extension_size) {
WiredHome 152:a013ac0133e4 392 return 0;
WiredHome 152:a013ac0133e4 393 }
WiredHome 152:a013ac0133e4 394 HexDump("application", (const uint8_t *) &application, sizeof(application));
WiredHome 152:a013ac0133e4 395 break;
WiredHome 152:a013ac0133e4 396 case COMMENT_EXTENSION:
WiredHome 152:a013ac0133e4 397 // comment extension; do nothing - all the data is in the
WiredHome 152:a013ac0133e4 398 // sub-blocks that follow.
WiredHome 152:a013ac0133e4 399 break;
WiredHome 152:a013ac0133e4 400 case PLAINTEXT_EXTENSION:
WiredHome 152:a013ac0133e4 401 if (read_filesystem_bytes(&plaintext, plaintext_extension_size, fh) < plaintext_extension_size) {
WiredHome 152:a013ac0133e4 402 return 0;
WiredHome 152:a013ac0133e4 403 }
WiredHome 152:a013ac0133e4 404 HexDump("plaintext", (const uint8_t *) &plaintext, sizeof(plaintext));
WiredHome 152:a013ac0133e4 405 break;
WiredHome 152:a013ac0133e4 406 default:
WiredHome 152:a013ac0133e4 407 return (0);
WiredHome 152:a013ac0133e4 408 }
WiredHome 152:a013ac0133e4 409 // All extensions are followed by data sub-blocks; even if it's
WiredHome 152:a013ac0133e4 410 // just a single data sub-block of length 0
WiredHome 152:a013ac0133e4 411 /* extension_data_length = */ read_gif_sub_blocks(fh, &extension_data);
WiredHome 152:a013ac0133e4 412 if (extension_data != NULL)
WiredHome 152:a013ac0133e4 413 free(extension_data);
WiredHome 152:a013ac0133e4 414 return 1;
WiredHome 152:a013ac0133e4 415 }
WiredHome 152:a013ac0133e4 416
WiredHome 152:a013ac0133e4 417
WiredHome 152:a013ac0133e4 418 RetCode_t GraphicsDisplay::_RenderGIF(loc_t ScreenX, loc_t ScreenY, FILE * fh) {
WiredHome 152:a013ac0133e4 419 //int color_resolution_bits;
WiredHome 152:a013ac0133e4 420 global_color_table_size = 0;
WiredHome 152:a013ac0133e4 421 local_color_table_size = 0;
WiredHome 152:a013ac0133e4 422
WiredHome 152:a013ac0133e4 423 if (GetGIFHeader(fh) != noerror)
WiredHome 152:a013ac0133e4 424 return not_supported_format;
WiredHome 152:a013ac0133e4 425 //color_resolution_bits = ((screen_descriptor.fields & 0x70) >> 4) + 1;
WiredHome 152:a013ac0133e4 426 if (screen_descriptor.fields & 0x80) {
WiredHome 152:a013ac0133e4 427 // If bit 7 is set, the next block is a global color table; read it
WiredHome 152:a013ac0133e4 428 global_color_table_size = 1 << ((screen_descriptor.fields & 0x07) + 1);
WiredHome 152:a013ac0133e4 429 global_color_table = (color_t *) malloc(sizeof(color_t) * global_color_table_size);
WiredHome 152:a013ac0133e4 430 if (global_color_table == NULL)
WiredHome 152:a013ac0133e4 431 return not_enough_ram;
WiredHome 152:a013ac0133e4 432 // XXX this could conceivably return a short count...
WiredHome 152:a013ac0133e4 433 if (readColorTable(global_color_table, global_color_table_size, fh) != noerror) {
WiredHome 152:a013ac0133e4 434 return not_supported_format;
WiredHome 152:a013ac0133e4 435 }
WiredHome 152:a013ac0133e4 436 HexDump("Global Color Table", (const uint8_t *) global_color_table, 3 * global_color_table_size);
WiredHome 152:a013ac0133e4 437 }
WiredHome 152:a013ac0133e4 438 unsigned char block_type = 0x0;
WiredHome 152:a013ac0133e4 439 uint8_t * uncompress_gifed_data = NULL;
WiredHome 152:a013ac0133e4 440 gif_image_descriptor_t gif_image_descriptor; // the image fragment
WiredHome 152:a013ac0133e4 441 while (block_type != TRAILER) {
WiredHome 152:a013ac0133e4 442 if (read_filesystem_bytes(&block_type, sizeof(block_type), fh) < sizeof(block_type))
WiredHome 152:a013ac0133e4 443 return not_supported_format;
WiredHome 152:a013ac0133e4 444 INFO("block type: %02X", block_type);
WiredHome 197:853d08e2fb53 445
WiredHome 197:853d08e2fb53 446
WiredHome 177:d8e65c0e268a 447 RetCode_t r_pgid = noerror;
WiredHome 152:a013ac0133e4 448 switch (block_type) {
WiredHome 152:a013ac0133e4 449 case IMAGE_DESCRIPTOR:
WiredHome 177:d8e65c0e268a 450 if (readGIFImageDescriptor(fh, &gif_image_descriptor) != noerror) {
WiredHome 177:d8e65c0e268a 451 INFO("not supported format");
WiredHome 152:a013ac0133e4 452 return not_supported_format;
WiredHome 177:d8e65c0e268a 453 }
WiredHome 177:d8e65c0e268a 454 r_pgid = process_gif_image_descriptor(fh, &uncompress_gifed_data, gif_image_descriptor.image_width, gif_image_descriptor.image_height);
WiredHome 177:d8e65c0e268a 455 if (r_pgid != noerror) {
WiredHome 177:d8e65c0e268a 456 INFO("error %d", r_pgid);
WiredHome 177:d8e65c0e268a 457 return r_pgid;
WiredHome 177:d8e65c0e268a 458 } else {
WiredHome 152:a013ac0133e4 459 if (uncompress_gifed_data) {
WiredHome 152:a013ac0133e4 460 // Ready to render to the screen
WiredHome 177:d8e65c0e268a 461 INFO("Render to (%d,%d)", ScreenX, ScreenY);
WiredHome 152:a013ac0133e4 462 color_t * active_color_table = (local_color_table) ? local_color_table : global_color_table;
WiredHome 152:a013ac0133e4 463
WiredHome 152:a013ac0133e4 464 // create a local image buffer for this fragment
WiredHome 152:a013ac0133e4 465 color_t * cbmp = (color_t *) malloc(sizeof(color_t) * gif_image_descriptor.image_width * gif_image_descriptor.image_height);
WiredHome 177:d8e65c0e268a 466 if (cbmp == NULL) {
WiredHome 177:d8e65c0e268a 467 INFO("not enough ram");
WiredHome 152:a013ac0133e4 468 return not_enough_ram;
WiredHome 177:d8e65c0e268a 469 }
WiredHome 152:a013ac0133e4 470 for (int i = 0; i < gif_image_descriptor.image_width * gif_image_descriptor.image_height; i++) {
WiredHome 152:a013ac0133e4 471 int cIndex = uncompress_gifed_data[i];
WiredHome 152:a013ac0133e4 472 cbmp[i] = active_color_table[cIndex];
WiredHome 152:a013ac0133e4 473 }
WiredHome 152:a013ac0133e4 474 // Write Fragment to Screen
WiredHome 152:a013ac0133e4 475 #if 0
WiredHome 177:d8e65c0e268a 476 INFO("Render fragment: (%d,%d), offset: (%d,%d), w x h (%d,%d)",
WiredHome 152:a013ac0133e4 477 ScreenX, ScreenY,
WiredHome 152:a013ac0133e4 478 gif_image_descriptor.image_left_position,
WiredHome 152:a013ac0133e4 479 gif_image_descriptor.image_top_position,
WiredHome 152:a013ac0133e4 480 gif_image_descriptor.image_width,
WiredHome 152:a013ac0133e4 481 gif_image_descriptor.image_height);
WiredHome 152:a013ac0133e4 482 for (uint16_t y = 0; y < gif_image_descriptor.image_height; y++) {
WiredHome 152:a013ac0133e4 483 for (uint16_t x = 0; x < gif_image_descriptor.image_width; x++) {
WiredHome 152:a013ac0133e4 484 INFO("%04X ", cbmp[y * gif_image_descriptor.image_height + x]);
WiredHome 152:a013ac0133e4 485 }
WiredHome 177:d8e65c0e268a 486 INFO("");
WiredHome 152:a013ac0133e4 487 }
WiredHome 152:a013ac0133e4 488 #else
WiredHome 152:a013ac0133e4 489 rect_t restore = windowrect;
WiredHome 152:a013ac0133e4 490 window(ScreenX + gif_image_descriptor.image_left_position,
WiredHome 152:a013ac0133e4 491 ScreenY + gif_image_descriptor.image_top_position,
WiredHome 152:a013ac0133e4 492 gif_image_descriptor.image_width,
WiredHome 152:a013ac0133e4 493 gif_image_descriptor.image_height);
WiredHome 152:a013ac0133e4 494 pixelStream(cbmp, screen_descriptor.width * screen_descriptor.height,
WiredHome 152:a013ac0133e4 495 ScreenX + gif_image_descriptor.image_left_position,
WiredHome 152:a013ac0133e4 496 ScreenY + gif_image_descriptor.image_top_position);
WiredHome 152:a013ac0133e4 497 window(restore);
WiredHome 152:a013ac0133e4 498 #endif
WiredHome 152:a013ac0133e4 499 // end write
WiredHome 152:a013ac0133e4 500 free(cbmp);
WiredHome 152:a013ac0133e4 501 }
WiredHome 152:a013ac0133e4 502 if (local_color_table) {
WiredHome 152:a013ac0133e4 503 free(local_color_table);
WiredHome 152:a013ac0133e4 504 local_color_table = NULL;
WiredHome 152:a013ac0133e4 505 }
WiredHome 152:a013ac0133e4 506 }
WiredHome 152:a013ac0133e4 507 break;
WiredHome 152:a013ac0133e4 508 case EXTENSION_INTRODUCER:
WiredHome 177:d8e65c0e268a 509 if (!process_gif_extension(fh)) {
WiredHome 177:d8e65c0e268a 510 INFO("not supported format");
WiredHome 152:a013ac0133e4 511 return not_supported_format;
WiredHome 177:d8e65c0e268a 512 }
WiredHome 152:a013ac0133e4 513 break;
WiredHome 152:a013ac0133e4 514 case TRAILER:
WiredHome 152:a013ac0133e4 515 break;
WiredHome 152:a013ac0133e4 516 default:
WiredHome 177:d8e65c0e268a 517 INFO("not supported format");
WiredHome 152:a013ac0133e4 518 return not_supported_format;
WiredHome 152:a013ac0133e4 519 }
WiredHome 152:a013ac0133e4 520 }
WiredHome 177:d8e65c0e268a 521 INFO("no error");
WiredHome 152:a013ac0133e4 522 return noerror;
WiredHome 152:a013ac0133e4 523 }
WiredHome 152:a013ac0133e4 524
WiredHome 152:a013ac0133e4 525
WiredHome 152:a013ac0133e4 526 // hasGIFHeader determines if it is a GIF file
WiredHome 152:a013ac0133e4 527 //
WiredHome 152:a013ac0133e4 528 // This reads a few bytes of the file and determines if they have the
WiredHome 152:a013ac0133e4 529 // GIF89a signature. GIF87a is not supported.
WiredHome 152:a013ac0133e4 530 //
WiredHome 152:a013ac0133e4 531 // @param fh is a file handle.
WiredHome 152:a013ac0133e4 532 // @returns true if it is GIF89a.
WiredHome 152:a013ac0133e4 533 //
WiredHome 152:a013ac0133e4 534 bool GraphicsDisplay::hasGIFHeader(FILE * fh) {
WiredHome 152:a013ac0133e4 535 char GIF_Header[6];
WiredHome 152:a013ac0133e4 536 if (read_filesystem_bytes(GIF_Header, sizeof(GIF_Header), fh) != sizeof(GIF_Header))
WiredHome 152:a013ac0133e4 537 return false;
WiredHome 152:a013ac0133e4 538 if (strncmp("GIF89a", GIF_Header, sizeof(GIF_Header)))
WiredHome 152:a013ac0133e4 539 return false;
WiredHome 152:a013ac0133e4 540 return true;
WiredHome 152:a013ac0133e4 541 }
WiredHome 152:a013ac0133e4 542
WiredHome 152:a013ac0133e4 543
WiredHome 152:a013ac0133e4 544 RetCode_t GraphicsDisplay::GetGIFHeader(FILE * fh) {
WiredHome 152:a013ac0133e4 545 if (read_filesystem_bytes(&screen_descriptor, gif_screen_descriptor_size, fh) < gif_screen_descriptor_size) {
WiredHome 152:a013ac0133e4 546 return not_supported_format;
WiredHome 152:a013ac0133e4 547 }
WiredHome 152:a013ac0133e4 548 screen_descriptor_isvalid = true;
WiredHome 177:d8e65c0e268a 549 INFO("screen_descriptor");
WiredHome 177:d8e65c0e268a 550 INFO(" width: %d", screen_descriptor.width);
WiredHome 177:d8e65c0e268a 551 INFO(" height: %d", screen_descriptor.height);
WiredHome 177:d8e65c0e268a 552 INFO(" fields: %02Xx", screen_descriptor.fields);
WiredHome 177:d8e65c0e268a 553 INFO(" gct: %2d", (screen_descriptor.fields & 0x80) ? 1 : 0);
WiredHome 177:d8e65c0e268a 554 INFO(" res: %2d", ((screen_descriptor.fields & 0x70) >> 4) + 1);
WiredHome 177:d8e65c0e268a 555 INFO(" sort: %2d", (screen_descriptor.fields & 0x08) ? 1 : 0);
WiredHome 177:d8e65c0e268a 556 INFO(" gct siz: %2d", 1 << ((screen_descriptor.fields & 0x07) + 1));
WiredHome 177:d8e65c0e268a 557 INFO(" back clr: %d", screen_descriptor.background_color_index);
WiredHome 177:d8e65c0e268a 558 INFO(" pix rat: %d", screen_descriptor.pixel_aspect_ratio);
WiredHome 152:a013ac0133e4 559 return noerror;
WiredHome 152:a013ac0133e4 560 }
WiredHome 152:a013ac0133e4 561
WiredHome 152:a013ac0133e4 562
WiredHome 152:a013ac0133e4 563 RetCode_t GraphicsDisplay::GetGIFMetrics(gif_screen_descriptor_t * imageDescriptor, const char * Name_GIF) {
WiredHome 152:a013ac0133e4 564 RetCode_t ret = not_supported_format;
WiredHome 152:a013ac0133e4 565
WiredHome 152:a013ac0133e4 566 if (screen_descriptor_isvalid) {
WiredHome 152:a013ac0133e4 567 ret = noerror;
WiredHome 152:a013ac0133e4 568 } else {
WiredHome 152:a013ac0133e4 569 FILE *fh = fopen(Name_GIF, "rb");
WiredHome 152:a013ac0133e4 570 if (fh) {
WiredHome 152:a013ac0133e4 571 ret = GetGIFHeader(fh);
WiredHome 152:a013ac0133e4 572 fclose(fh);
WiredHome 152:a013ac0133e4 573 }
WiredHome 152:a013ac0133e4 574 }
WiredHome 152:a013ac0133e4 575 if (ret == noerror)
WiredHome 152:a013ac0133e4 576 *imageDescriptor = screen_descriptor;
WiredHome 152:a013ac0133e4 577 return ret;
WiredHome 152:a013ac0133e4 578 }
WiredHome 152:a013ac0133e4 579
WiredHome 152:a013ac0133e4 580
WiredHome 152:a013ac0133e4 581 RetCode_t GraphicsDisplay::RenderGIFFile(loc_t x, loc_t y, const char *Name_GIF) {
WiredHome 152:a013ac0133e4 582 RetCode_t rt = file_not_found;
WiredHome 152:a013ac0133e4 583
WiredHome 152:a013ac0133e4 584 INFO("Opening {%s}", Name_GIF);
WiredHome 152:a013ac0133e4 585 screen_descriptor_isvalid = false;
WiredHome 152:a013ac0133e4 586 FILE *fh = fopen(Name_GIF, "rb");
WiredHome 152:a013ac0133e4 587 if (fh) {
WiredHome 152:a013ac0133e4 588 if (hasGIFHeader(fh)) {
WiredHome 152:a013ac0133e4 589 rt = _RenderGIF(x, y, fh);
WiredHome 152:a013ac0133e4 590 }
WiredHome 152:a013ac0133e4 591 fclose(fh);
WiredHome 152:a013ac0133e4 592 if (global_color_table)
WiredHome 152:a013ac0133e4 593 free(global_color_table);
WiredHome 152:a013ac0133e4 594 if (local_color_table)
WiredHome 152:a013ac0133e4 595 free(local_color_table);
WiredHome 152:a013ac0133e4 596 }
WiredHome 152:a013ac0133e4 597 return rt;
WiredHome 152:a013ac0133e4 598 }
WiredHome 152:a013ac0133e4 599
WiredHome 152:a013ac0133e4 600