fork download
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. typedef unsigned char uint8_t;
  5. typedef unsigned short int uint16_t;
  6. typedef unsigned int uint32_t;
  7.  
  8. // Define structures
  9. typedef struct {
  10. char name[2];
  11. unsigned int size;
  12. unsigned int reserved;
  13. unsigned int image_offset;
  14. } BMP_HEADER;
  15.  
  16. typedef struct {
  17. unsigned int size;
  18. unsigned int width;
  19. unsigned int height;
  20. unsigned short int number_color_plane;
  21. unsigned short int number_bit_per_pixel;
  22. unsigned int compression_method;
  23. unsigned int image_size;
  24. unsigned int horizontal_resolution;
  25. unsigned int vertical_resolution;
  26. unsigned int number_color;
  27. unsigned int ignored;
  28. } DIB_HEADER;
  29.  
  30. typedef struct {
  31. uint8_t y;
  32. uint8_t r;
  33. uint8_t g;
  34. uint8_t b;
  35. } PIXEL;
  36.  
  37. typedef struct {
  38. BMP_HEADER header;
  39. DIB_HEADER dib;
  40. PIXEL* image;
  41. } BMP_FILE;
  42.  
  43. // Function prototypes
  44. int openbmpfile(const char* file_name, BMP_FILE* input_file);
  45. int createbmpfile(const char* file_name, BMP_FILE* input_file);
  46. int image_scale(BMP_FILE* bmp, BMP_FILE* output, float times);
  47.  
  48. int openbmpfile(const char* file_name, BMP_FILE* input_file) {
  49. FILE* bmp_file;
  50. bmp_file = fopen(file_name, "rb");
  51. if (bmp_file == NULL) return 1;
  52.  
  53. // Read header of bmp file
  54. fread(input_file->header.name, 2, 1, bmp_file);
  55. fread(&(input_file->header.size), 3 * sizeof(int), 1, bmp_file);
  56. if ((input_file->header.name[0] != 'B') || (input_file->header.name[1] != 'M')) {
  57. fclose(bmp_file);
  58. return 1;
  59. }
  60.  
  61. // Read dib of bmp file
  62. fread(&(input_file->dib), 40, 1, bmp_file);
  63. if ((input_file->dib.size != 40) || (input_file->dib.compression_method != 0)) {
  64. fclose(bmp_file);
  65. return 1;
  66. }
  67.  
  68. // Go to the initial position of image data
  69. fseek(bmp_file, input_file->header.image_offset, SEEK_SET);
  70.  
  71. // Calculate image data size
  72. uint32_t size_image_content, i, this_pixel;
  73. if (input_file->dib.image_size == 0)
  74. size_image_content = input_file->dib.width * input_file->dib.height;
  75. else
  76. size_image_content = input_file->dib.image_size / input_file->dib.number_bit_per_pixel;
  77.  
  78. // Declare dynamic array for image data
  79. input_file->image = (PIXEL*)malloc(size_image_content * sizeof(PIXEL));
  80.  
  81. // Read image data
  82. for (i = 0; i < size_image_content; i++) {
  83. if (input_file->dib.number_bit_per_pixel == 24) {
  84. fread(&this_pixel, 3, 1, bmp_file);
  85. input_file->image[i].r = this_pixel & 0xff;
  86. input_file->image[i].g = (this_pixel & 0xff00) >> 8;
  87. input_file->image[i].b = (this_pixel & 0xff0000) >> 16;
  88. } else if (input_file->dib.number_bit_per_pixel == 32) {
  89. fread(&this_pixel, 4, 1, bmp_file);
  90. input_file->image[i].y = this_pixel & 0xff;
  91. input_file->image[i].r = (this_pixel & 0xff00) >> 8;
  92. input_file->image[i].g = (this_pixel & 0xff0000) >> 16;
  93. input_file->image[i].b = (this_pixel & 0xff000000) >> 24;
  94. }
  95. }
  96. fclose(bmp_file);
  97. return 0;
  98. }
  99.  
  100. int createbmpfile(const char* file_name, BMP_FILE* input_file) {
  101. FILE* file = fopen(file_name, "wb");
  102. if (file == NULL) return 1;
  103. printf("[log] start write file\n");
  104.  
  105. // Write header and dib of bmp file
  106. fwrite(input_file->header.name, 2, 1, file);
  107. fwrite(&(input_file->header.size), 12, 1, file);
  108. fwrite(&(input_file->dib), 40, 1, file);
  109.  
  110. // Go to the position of image file
  111. fseek(file, input_file->header.image_offset, SEEK_SET);
  112.  
  113. // Calculate image data size
  114. uint32_t size_image_content, i, this_pixel;
  115. if (input_file->dib.image_size == 0)
  116. size_image_content = input_file->dib.width * input_file->dib.height;
  117. else
  118. size_image_content = input_file->dib.image_size / input_file->dib.number_bit_per_pixel;
  119. printf("[log] size of image: %d\n", size_image_content);
  120.  
  121. // Calculate the number of bytes per row
  122. uint32_t bytes_per_row = input_file->dib.width * (input_file->dib.number_bit_per_pixel / 8);
  123. // Calculate the number of padding bytes needed to align to 4 bytes
  124. uint32_t padding_bytes = (4 - (bytes_per_row % 4)) % 4;
  125. printf("[log] size of image: %d\n", size_image_content);
  126. // Write image data
  127. for (i = 0; i < size_image_content; i++) {
  128. if (input_file->dib.number_bit_per_pixel == 24) {
  129. this_pixel = 0;
  130. this_pixel |= input_file->image[i].r;
  131. this_pixel |= input_file->image[i].g << 8;
  132. this_pixel |= input_file->image[i].b << 16;
  133. fwrite(&(this_pixel), 3, 1, file);
  134. } else if (input_file->dib.number_bit_per_pixel == 32) {
  135. this_pixel = input_file->image[i].y;
  136. this_pixel |= input_file->image[i].r << 8;
  137. this_pixel |= input_file->image[i].g << 16;
  138. this_pixel |= input_file->image[i].b << 24;
  139. fwrite(&(this_pixel), 4, 1, file);
  140. }
  141. else
  142. printf("[log] [error] bit per pixel error\n");
  143. if(padding_bytes != 0)
  144. {
  145. if(i%input_file->dib.width==0)
  146. {
  147. uint32_t padding[4] = {0};
  148. fwrite(padding, padding_bytes, 1, file);
  149. }
  150. }
  151.  
  152. }
  153. fclose(file);
  154. printf("[log] write file success\n");
  155.  
  156. return 0;
  157. }
  158.  
  159. int image_scale(BMP_FILE* bmp, BMP_FILE* output, float times) {
  160. uint32_t height = bmp->dib.height * times;
  161. uint32_t width = bmp->dib.width * times;
  162. uint32_t origin_width = bmp->dib.width;
  163. uint32_t origin_height = bmp->dib.height;
  164. uint16_t bits = bmp->dib.number_bit_per_pixel;
  165.  
  166. printf("Height: %u Width: %u\n", height, width);
  167.  
  168. // Calculate image data size
  169. uint32_t size_image_content, i, j;
  170. uint32_t p1, p2;
  171. float d1, d2, d3, d4;
  172. size_image_content = height * width;
  173.  
  174. // Copy header and dib
  175. output->dib = bmp->dib;
  176. output->header = bmp->header;
  177.  
  178. // Change height and width
  179. output->dib.height = height;
  180. output->dib.width = width;
  181. output->header.size = height * width * bmp->dib.number_bit_per_pixel + 54;
  182.  
  183. // Generate dynamic array for image data
  184. output->image = (PIXEL*)malloc(size_image_content * sizeof(PIXEL));
  185.  
  186. // Bilinear interpolation
  187. for (i = 0; i < height; i++) {
  188. for (j = 0; j < width; j++) {
  189. p2 = i / times;
  190. if (p2 == origin_height - 1) p2 -= 1;
  191. p1 = j / times;
  192. if (p1 == origin_width - 1) p1 -= 1;
  193. d1 = i / times - p2;
  194. d2 = 1 - d1;
  195. d3 = j / times - p1;
  196. d4 = 1 - d3;
  197. output->image[i * width + j].y = (uint8_t)(
  198. bmp->image[(p2)*origin_width + p1].y * d2 * d4 +
  199. bmp->image[(p2 + 1) * origin_width + p1].y * d1 * d4 +
  200. bmp->image[(p2)*origin_width + p1 + 1].y * d2 * d3 +
  201. bmp->image[(p2 + 1) * origin_width + p1 + 1].y * d1 * d3);
  202. output->image[i * width + j].r = (uint8_t)(
  203. bmp->image[(p2)*origin_width + p1].r * d2 * d4 +
  204. bmp->image[(p2 + 1) * origin_width + p1].r * d1 * d4 +
  205. bmp->image[(p2)*origin_width + p1 + 1].r * d2 * d3 +
  206. bmp->image[(p2 + 1) * origin_width + p1 + 1].r * d1 * d3);
  207. output->image[i * width + j].g = (uint8_t)(
  208. bmp->image[(p2)*origin_width + p1].g * d2 * d4 +
  209. bmp->image[(p2 + 1) * origin_width + p1].g * d1 * d4 +
  210. bmp->image[(p2)*origin_width + p1 + 1].g * d2 * d3 +
  211. bmp->image[(p2 + 1) * origin_width + p1 + 1].g * d1 * d3);
  212. output->image[i * width + j].b = (uint8_t)(
  213. bmp->image[(p2)*origin_width + p1].b * d2 * d4 +
  214. bmp->image[(p2 + 1) * origin_width + p1].b * d1 * d4 +
  215. bmp->image[(p2)*origin_width + p1 + 1].b * d2 * d3 +
  216. bmp->image[(p2 + 1) * origin_width + p1 + 1].b * d1 * d3);
  217. }
  218. }
  219. return 0;
  220. }
  221.  
  222. int main() {
  223. BMP_FILE input_file_1, input_file_2, output_file;
  224. char input_file_name_1[] = "hw1.bmp";
  225. char input_file_name_2[] = "hw2.bmp";
  226.  
  227. // Read file
  228. openbmpfile(input_file_name_1, &input_file_1);
  229. openbmpfile(input_file_name_2, &input_file_2);
  230.  
  231. // Image scale
  232. image_scale(&input_file_1, &output_file, 1.5);
  233. createbmpfile("output1_up.bmp", &output_file);
  234. free(output_file.image);
  235. image_scale(&input_file_2, &output_file, 1.5);
  236. createbmpfile("output2_up.bmp", &output_file);
  237. free(output_file.image);
  238. image_scale(&input_file_1, &output_file, 1.0 / 1.5);
  239. createbmpfile("output1_down.bmp", &output_file);
  240. free(output_file.image);
  241. image_scale(&input_file_2, &output_file, 1.0 / 1.5);
  242. createbmpfile("output2_down.bmp", &output_file);
  243. free(output_file.image);
  244.  
  245. free(input_file_1.image);
  246. free(input_file_2.image);
  247. return 0;
  248. }
  249.  
Success #stdin #stdout 0.01s 5548KB
stdin
Standard input is empty
stdout
Height: 0 Width: 7807
Height: 0 Width: 0
Height: 0 Width: 3470
Height: 0 Width: 0