main.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. #include "../headers/pitmap.h"
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <math.h>
  5. #include <string.h>
  6. uint8_t *file_buffer;
  7. int current_byte;
  8. // byte funcs
  9. void skip(int bytes_to_skip){
  10. current_byte += bytes_to_skip;
  11. }
  12. int8_t get_1(){
  13. return file_buffer[current_byte++];
  14. }
  15. int16_t get_2(){
  16. return file_buffer[current_byte++] | file_buffer[current_byte++] << 8;
  17. }
  18. int32_t get_4(){
  19. return file_buffer[current_byte++] | file_buffer[current_byte++] << 8 | file_buffer[current_byte++] << 16 | file_buffer[current_byte++] << 24;
  20. }
  21. PM_image* PM_load_bitmap(unsigned char debug_mode){
  22. PM_image* image = malloc(sizeof(PM_image));
  23. current_byte = 0;
  24. // file header
  25. uint16_t header_field = get_2();
  26. if (header_field != 19778) {
  27. printf("file is not a bitmap file or bitmap is damaged\n");
  28. return NULL;
  29. }
  30. uint32_t file_size = get_4();
  31. skip(4); // reserved
  32. uint32_t pixel_buffer_offset = get_4();
  33. // bitmap information header / DIB header
  34. // BITMAPINFOHEADER
  35. uint32_t header_size = get_4();
  36. uint32_t image_width = header_size == 12 ? (uint32_t)get_2() : (uint32_t)get_4();
  37. uint32_t image_height = header_size == 12 ? (uint32_t)get_2() : (uint32_t)get_4();
  38. skip(2); // color planes, always 1
  39. uint16_t bits_per_pixel = get_2();
  40. uint32_t compression_method = get_4();
  41. uint32_t image_size = get_4();
  42. int32_t horizontal_res = get_4(); // pixels per meter
  43. int32_t vertical_res = get_4();
  44. uint32_t number_of_colors_in_palette = get_4();
  45. skip(4); // number of important colors, ignored
  46. if (debug_mode) printf("file size is %d bytes\nimage res is %dx%d\ncompression method is #%d\npixel buffer offset is %d\n", file_size, image_width, image_height, compression_method, pixel_buffer_offset);
  47. uint32_t* color_palette;
  48. if (number_of_colors_in_palette > 0) { // we've got a color palette!
  49. if (debug_mode) printf("color palette exists and has %d colors\n", number_of_colors_in_palette);
  50. // skip to color palette
  51. current_byte = header_size + 14 + // skip the file header (14 bytes) and the DIB
  52. 12 * (compression_method == 3) + 16 * (compression_method == 6); // skip the bit fields if they exist
  53. color_palette = malloc(sizeof(uint32_t) * number_of_colors_in_palette);
  54. for (uint32_t i = 0; i < number_of_colors_in_palette; i++){
  55. // BGR0 -> RGB255
  56. unsigned char r = get_1();
  57. unsigned char g = get_1();
  58. unsigned char b = get_1();
  59. color_palette[i] = r << 24 | g << 16 | b << 8 | 255 << 0;
  60. skip(1);
  61. }
  62. }
  63. image->frame_buffer = malloc(sizeof(uint32_t) * image_width * image_height);
  64. image->width = image_width;
  65. image->height = image_height;
  66. // pixel array
  67. current_byte = pixel_buffer_offset;
  68. int row_size = ceil((float)(bits_per_pixel * image_width) / (32)) * 4;
  69. if (debug_mode) printf("%d bits per pixel\n", bits_per_pixel);
  70. switch (bits_per_pixel){
  71. case (32): { // RGBA 1 byte each
  72. for (int y = image_height - 1; y >= 0; y--){
  73. int current_byte_of_row = 0;
  74. for (int x = image_width - 1; x >= 0; x--){ // starting reversed becuase image data is backwards
  75. 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());
  76. current_byte_of_row += 4;
  77. }
  78. skip(row_size - current_byte_of_row);
  79. }
  80. break;
  81. }
  82. case (24): { // RGB -> RGBA 1 byte each
  83. for (int y = image_height - 1; y >= 0; y--){
  84. int current_byte_of_row = 0;
  85. for (int x = image_width - 1; x >= 0; x--){ // starting reversed becuase image data is backwards
  86. 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);
  87. current_byte_of_row += 3;
  88. }
  89. skip(row_size - current_byte_of_row);
  90. }
  91. break;
  92. }
  93. case (16): {
  94. printf("16 BPP supporet not implemented");
  95. break;
  96. }
  97. case (8): { // paletted
  98. if (compression_method == 0){ // no compression
  99. for (int y = image_height - 1; y >= 0; y--){
  100. for (int x = image_width - 1; x >= 0; x--){ // starting reversed becuase image data is backwards
  101. uint8_t palette_index = get_1();
  102. // if (debug_mode) printf("current pixel is %dx%d\npalette index is %d\n", x, y, palette_index);
  103. image->frame_buffer[y * image_width + x] = color_palette[palette_index];
  104. }
  105. }
  106. }
  107. else { // assume RLE
  108. uint16_t x = image_width - 1;
  109. uint16_t y = image_height - 1;
  110. unsigned char reading_file = 1;
  111. while (reading_file){
  112. uint8_t number_of_repetitions = get_1();
  113. uint8_t palette_index = get_1();
  114. if (number_of_repetitions > 0){
  115. for (uint8_t pixel = 0; pixel < number_of_repetitions; pixel++){
  116. // if (debug_mode) printf("current pixel is %dx%d\npalette index is %d\n", x, y, palette_index);
  117. image->frame_buffer[y * image_width + x--] = color_palette[palette_index];
  118. }
  119. } else {
  120. if (palette_index == 0) { // end of a line
  121. x = image_width - 1;
  122. y--;
  123. } else if (palette_index == 1){ // end of image
  124. reading_file = 0;
  125. } else { // delta
  126. x -= get_1();
  127. y -= get_1();
  128. }
  129. }
  130. }}
  131. break;
  132. }
  133. case (4): { // paletted
  134. printf("4 BPP supporet not implemented");
  135. break;
  136. }
  137. case (1): {
  138. printf("1 BPP supporet not implemented");
  139. break;
  140. }
  141. }
  142. return image;
  143. }
  144. PM_image* PM_load_image(char *filename, unsigned char debug_mode){
  145. FILE *fp = fopen(filename, "rb");
  146. if (fp == NULL){
  147. printf("file does not exist !!!\n");
  148. return NULL;
  149. }
  150. fseek(fp, 0, SEEK_END);
  151. long size = ftell(fp);
  152. rewind(fp);
  153. file_buffer = malloc(size);
  154. fread(file_buffer, 1, size, fp);
  155. fclose(fp);
  156. // see what the file type is
  157. char *strtok_string = strtok(filename, ".");
  158. while(strtok_string != NULL) {
  159. strtok_string = strtok(NULL, ".");
  160. printf("%s\n", strtok_string);
  161. }
  162. return NULL;
  163. return PM_load_bitmap(debug_mode);
  164. }