main.c 6.8 KB

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