Browse Source

completed GIF parsing

Iver 6 days ago
parent
commit
16874d0413
8 changed files with 51 additions and 14 deletions
  1. 1 1
      README.md
  2. BIN
      builds/libpitmap.so
  3. BIN
      builds/main.bin
  4. 6 1
      changelog.txt
  5. BIN
      image.tga
  6. 2 0
      src/headers/pitmap.h
  7. 1 1
      src/launch_program/main.c
  8. 41 11
      src/library/main.c

+ 1 - 1
README.md

@@ -14,7 +14,7 @@ Pit, like a lemon would have. Sounds like "Bit"
 
 
 ### By End of February, 2026
 ### By End of February, 2026
 
 
- - [ ] GIF support
+ - [x] GIF support **`finished on January 8th, 2026`**
 
 
 ### By End of May, 2026
 ### By End of May, 2026
 
 

BIN
builds/libpitmap.so


BIN
builds/main.bin


+ 6 - 1
changelog.txt

@@ -1 +1,6 @@
--fixed errors that were holding me up for weeks. In the standard code addition branch, first_code was mistakenly set to previous code instead of code, & clear code was not reseting current_highest_defined_code
+-fixed GIF errors that were holding me up for weeks. In the standard code addition branch, first_code was mistakenly set to previous code instead of code, & clear code was not reseting current_highest_defined_code
+-flipped output of GIF parser
+-returned image has animation data
+-frame is equal to previous frame
+-if pixel is the transparent index ignore it
+-un-flipped parsers that flipped data before

BIN
image.tga


+ 2 - 0
src/headers/pitmap.h

@@ -6,6 +6,8 @@
 typedef struct {
 typedef struct {
     uint32_t* frame_buffer;
     uint32_t* frame_buffer;
     int width, height;
     int width, height;
+    int frame_count;
+    int frame_height;
 } PM_image;
 } PM_image;
 
 
 PM_image* PM_load_image(const char* filename, unsigned char debug_mode);
 PM_image* PM_load_image(const char* filename, unsigned char debug_mode);

+ 1 - 1
src/launch_program/main.c

@@ -43,7 +43,7 @@ int write_tga(const char* path, const PM_image* img) {
 }
 }
 
 
 int main(){
 int main(){
-    write_tga("./image.tga", PM_load_image("images/png.gif", 0));
+    write_tga("./image.tga", PM_load_image("images/test.gif.gif", 0));
 
 
     return 0;
     return 0;
 }
 }

+ 41 - 11
src/library/main.c

@@ -149,7 +149,7 @@ PM_image* PM_load_bitmap(unsigned char debug_mode){
             for (int y = image_height - 1; y >= 0; y--){
             for (int y = image_height - 1; y >= 0; y--){
                 int current_byte_of_row = 0;
                 int current_byte_of_row = 0;
 
 
-                for (int x = image_width - 1; x >= 0; x--){ // starting reversed becuase image data is backwards
+                for (uint32_t x = 0; x < image_width; x++){ // starting reversed becuase image data is backwards
                     image->frame_buffer[y * image_width + x] = (uint32_t)((uint8_t)get_1() << 24 | (uint8_t)get_1() << 16 | (uint8_t)get_1() << 8 | (uint8_t)get_1());
                     image->frame_buffer[y * image_width + x] = (uint32_t)((uint8_t)get_1() << 24 | (uint8_t)get_1() << 16 | (uint8_t)get_1() << 8 | (uint8_t)get_1());
 
 
                     current_byte_of_row += 4;
                     current_byte_of_row += 4;
@@ -165,7 +165,7 @@ PM_image* PM_load_bitmap(unsigned char debug_mode){
             for (int y = image_height - 1; y >= 0; y--){
             for (int y = image_height - 1; y >= 0; y--){
                 int current_byte_of_row = 0;
                 int current_byte_of_row = 0;
 
 
-                for (int x = image_width - 1; x >= 0; x--){ // starting reversed becuase image data is backwards
+                for (uint32_t x = 0; x < image_width; x++){ // starting reversed becuase image data is backwards
                     image->frame_buffer[y * image_width + x] = (uint32_t)((uint8_t)get_1() << 24 | (uint8_t)get_1() << 16 | (uint8_t)get_1() << 8 | 255);
                     image->frame_buffer[y * image_width + x] = (uint32_t)((uint8_t)get_1() << 24 | (uint8_t)get_1() << 16 | (uint8_t)get_1() << 8 | 255);
                     
                     
                     current_byte_of_row += 3;
                     current_byte_of_row += 3;
@@ -187,7 +187,7 @@ PM_image* PM_load_bitmap(unsigned char debug_mode){
             if (compression_method == 0){ // no compression
             if (compression_method == 0){ // no compression
                 for (int y = image_height - 1; y >= 0; y--){
                 for (int y = image_height - 1; y >= 0; y--){
 
 
-                    for (int x = image_width - 1; x >= 0; x--){ // starting reversed becuase image data is backwards
+                    for (uint32_t x = 0; x < image_width; x++){ // starting reversed becuase image data is backwards
                     uint8_t palette_index = get_1();
                     uint8_t palette_index = get_1();
 
 
                         // (*current_printf_function)("current pixel is %dx%d\npalette index is %d\n", x, y, palette_index);
                         // (*current_printf_function)("current pixel is %dx%d\npalette index is %d\n", x, y, palette_index);
@@ -199,7 +199,7 @@ PM_image* PM_load_bitmap(unsigned char debug_mode){
             }    
             }    
             }
             }
             else { // assume RLE
             else { // assume RLE
-                uint16_t x = image_width - 1;
+                uint16_t x = 0;
             uint16_t y = image_height - 1;
             uint16_t y = image_height - 1;
 
 
             unsigned char reading_file = 1;
             unsigned char reading_file = 1;
@@ -211,16 +211,16 @@ PM_image* PM_load_bitmap(unsigned char debug_mode){
                 if (number_of_repetitions > 0){
                 if (number_of_repetitions > 0){
                     for (uint8_t pixel = 0; pixel < number_of_repetitions; pixel++){
                     for (uint8_t pixel = 0; pixel < number_of_repetitions; pixel++){
                         // (*current_printf_function)("current pixel is %dx%d\npalette index is %d\n", x, y, palette_index);
                         // (*current_printf_function)("current pixel is %dx%d\npalette index is %d\n", x, y, palette_index);
-                        image->frame_buffer[y * image_width + x--] = color_palette[palette_index];
+                        image->frame_buffer[y * image_width + x++] = color_palette[palette_index];
                     }
                     }
                 } else {
                 } else {
                     if (palette_index == 0) { // end of a line
                     if (palette_index == 0) { // end of a line
-                        x = image_width - 1;
+                        x = 0;
                         y--;
                         y--;
                     } else if (palette_index == 1){ // end of image
                     } else if (palette_index == 1){ // end of image
                         reading_file = 0;
                         reading_file = 0;
                     } else { // delta   
                     } else { // delta   
-                        x -= get_1();
+                        x += get_1();
                         y -= get_1();
                         y -= get_1();
                     }
                     }
                 }
                 }
@@ -281,6 +281,8 @@ PM_image* PM_load_gif(unsigned char debug_mode){
     uint16_t image_width = get_2();
     uint16_t image_width = get_2();
     uint16_t image_height = get_2();
     uint16_t image_height = get_2();
     
     
+    image->frame_height = image_height;
+
     image->frame_buffer = NULL;
     image->frame_buffer = NULL;
 
 
     image->width = image_width;
     image->width = image_width;
@@ -342,6 +344,9 @@ PM_image* PM_load_gif(unsigned char debug_mode){
         // return image;
         // return image;
     }
     }
 
 
+    uint8_t transparent_color_gct_index = 0;
+    uint8_t has_transparency = 0;
+
     unsigned char still_reading_file = 1;
     unsigned char still_reading_file = 1;
 
 
     while (still_reading_file){        
     while (still_reading_file){        
@@ -359,7 +364,7 @@ PM_image* PM_load_gif(unsigned char debug_mode){
                 uint8_t gce_size = get_1();
                 uint8_t gce_size = get_1();
                 uint8_t packed_field = get_1(); // bit field
                 uint8_t packed_field = get_1(); // bit field
                 skip(2);
                 skip(2);
-                uint8_t transparent_color_gct_index = get_1();
+                transparent_color_gct_index = get_1();
                 skip(1);
                 skip(1);
 
 
                 // "disposal method" is the first variable in the packed field
                 // "disposal method" is the first variable in the packed field
@@ -372,8 +377,7 @@ PM_image* PM_load_gif(unsigned char debug_mode){
 
 
                 (*current_printf_function)("transparency index: %d\n", transparent_color_gct_index);
                 (*current_printf_function)("transparency index: %d\n", transparent_color_gct_index);
 
 
-                // set the transparent color to 0% opacity
-                if (packed_field & 1) global_color_table[transparent_color_gct_index] &= 0xFFFFFF00; // bit mask for alpha channel to be 0
+                has_transparency = packed_field & 1;
 
 
                 break;
                 break;
             }
             }
@@ -643,9 +647,33 @@ PM_image* PM_load_gif(unsigned char debug_mode){
                     printf("error: number of decoded pixels is not equal to number of total pixels\n");
                     printf("error: number of decoded pixels is not equal to number of total pixels\n");
                 }
                 }
 
 
+                (*current_printf_function)("image descriptor is %dx%d, offset is %dx%d\n", image_descriptor_width, image_descriptor_height, image_left_pos, image_top_pos);
+
+                if (frame_count > 1){
+                    for (int y = 0; y < image_height; y++){
+                        for (int x = 0; x < image_width; x++){
+                            uint32_t frame_offset_1 = image_height * (frame_count - 1);
+                            uint32_t frame_offset_2 = image_height * (frame_count - 2);
+                            
+                            image->frame_buffer[(y + frame_offset_1) * image_width + x] = 
+                                image->frame_buffer[(y + frame_offset_2) * image_width + x];
+                        }
+                    }
+                }
+
                 for (int y = 0; y < image_descriptor_height; y++){
                 for (int y = 0; y < image_descriptor_height; y++){
                     for (int x = 0; x < image_descriptor_width; x++){
                     for (int x = 0; x < image_descriptor_width; x++){
-                        image->frame_buffer[(y + image_top_pos + image_height * (frame_count - 1)) * image_width + (x + image_left_pos)] = local_color_table_flag ? local_color_table[decoded_color_codes[y * image_width + x]] : global_color_table[decoded_color_codes[y * image_width + x]];
+                        if (has_transparency && decoded_color_codes[y * image_descriptor_width + x] == transparent_color_gct_index)
+                            continue;
+                        else{
+                            uint32_t frame_offset = image_height * (frame_count - 1);
+
+                            uint32_t color = local_color_table_flag ? 
+                                local_color_table[decoded_color_codes[y * image_descriptor_width + x]] : 
+                                global_color_table[decoded_color_codes[y * image_descriptor_width + x]];
+
+                            image->frame_buffer[(y + image_top_pos + frame_offset) * image_width + x + image_left_pos] = color;
+                        }
                     }
                     }
                 }
                 }
                 
                 
@@ -662,6 +690,8 @@ PM_image* PM_load_gif(unsigned char debug_mode){
         }
         }
     }
     }
 
 
+    image->frame_count = frame_count;
+
     return image;
     return image;
 }
 }