Advertisement
jcdkiki

Untitled

May 1st, 2024
47
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.02 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <getopt.h>
  4. #include <string.h>
  5.  
  6. #define EXIT_ERROR 40
  7.  
  8. #pragma pack(push, 1)
  9.  
  10. typedef struct {
  11. unsigned short int signature;
  12. unsigned int size;
  13. unsigned short int reserved1, reserved2;
  14. unsigned int offset;
  15.  
  16. unsigned int info_size;
  17. int width, height;
  18. unsigned short int planes;
  19. unsigned short int bits;
  20. unsigned int compression;
  21. unsigned int imagesize;
  22. int xresolution, yresolution;
  23. unsigned int ncolours;
  24. unsigned int importantcolours;
  25. } BMPHeader;
  26.  
  27. typedef struct {
  28. unsigned char b;
  29. unsigned char g;
  30. unsigned char r;
  31. } RGB;
  32.  
  33. typedef struct {
  34. BMPHeader header;
  35. RGB **rgb;
  36. } Image;
  37.  
  38. #pragma pack(pop)
  39.  
  40. int create_image(Image *image, char *filename)
  41. {
  42. FILE *fp = fopen(filename, "rb");
  43. if (fp == NULL) {
  44. fputs("Failed to open file\n", stderr);
  45. return 0;
  46. }
  47.  
  48. fread(&image->header, 1, sizeof(BMPHeader), fp);
  49.  
  50. if (image->header.signature != 0x4D42) {
  51. fputs("Not a BMP file\n", stderr);
  52. return 0;
  53. }
  54.  
  55. if (image->header.bits != 24 || image->header.compression != 0 || image->header.planes != 1) {
  56. fputs("Unsupported BMP file", stderr);
  57. return 0;
  58. }
  59.  
  60. fseek(fp, image->header.offset, SEEK_SET);
  61.  
  62. RGB **rgb = calloc(image->header.height, sizeof(RGB*));
  63. if (rgb == NULL) {
  64. fputs("Failed to allocate memory", stderr);
  65. return 0;
  66. }
  67.  
  68. int padd = (4 - (sizeof(RGB) * image->header.width) % 4) % 4;
  69.  
  70. for (int i = 0; i < image->header.height; i++) {
  71. rgb[i] = calloc(image->header.width, sizeof(RGB));
  72. if (rgb[i] == NULL) {
  73. for (int j = 0; j < i; j++)
  74. free(rgb[j]);
  75.  
  76. free(rgb);
  77. fputs("Failed to allocate memory\n", stderr);
  78. return 0;
  79. }
  80.  
  81. fread(rgb[i], 1, sizeof(RGB) * image->header.width, fp);
  82. fseek(fp, padd, SEEK_CUR);
  83. }
  84.  
  85. image->rgb = rgb;
  86.  
  87. fclose(fp);
  88. return 1;
  89. }
  90.  
  91. int save_image(Image *image, char *filename)
  92. {
  93. FILE *fp = fopen(filename, "wb");
  94. if (fp == NULL) {
  95. fputs("Failed to open file\n", stderr);
  96. return 0;
  97. }
  98.  
  99. fwrite(&image->header, 1, sizeof(BMPHeader), fp);
  100. fseek(fp, image->header.offset, SEEK_SET);
  101.  
  102. int padd = (4 - (sizeof(RGB) * image->header.width) % 4) % 4;
  103. for (int i = 0; i < image->header.height; i++) {
  104. fwrite(image->rgb[i], 1, sizeof(RGB) * image->header.width, fp);
  105. for (int j = 0; j < padd; j++)
  106. fputc(0, fp);
  107. }
  108.  
  109. fclose(fp);
  110. return 1;
  111. }
  112.  
  113. void destroy_image(Image *image)
  114. {
  115. for (int i = 0; i < image->header.height; i++)
  116. free(image->rgb[i]);
  117.  
  118. free(image->rgb);
  119. }
  120.  
  121. enum {
  122. OPTION_INVERSE = 1,
  123. OPTION_COMPONENT_SUM
  124. };
  125.  
  126. enum {
  127. COMPONENT_UNSET,
  128. COMPONENT_RED,
  129. COMPONENT_GREEN,
  130. COMPONENT_BLUE
  131. };
  132.  
  133. const char *shortopts = "hin:I:O:";
  134.  
  135. struct option longopts[] = {
  136. { "help", no_argument, NULL, 'h' },
  137. { "info", no_argument, NULL, 'i' },
  138. { "inverse_image", no_argument, NULL, OPTION_INVERSE },
  139. { "component_max", no_argument, NULL, OPTION_COMPONENT_SUM },
  140. { "component_name", required_argument, NULL, 'n' },
  141.  
  142. { "input", required_argument, NULL, 'I' },
  143. { "output", required_argument, NULL, 'O' },
  144.  
  145. { NULL, 0, NULL, 0 }
  146. };
  147.  
  148. int get_component_name()
  149. {
  150. if (strcmp(optarg, "red") == 0)
  151. return COMPONENT_RED;
  152. else if (strcmp(optarg, "green") == 0)
  153. return COMPONENT_GREEN;
  154. else if (strcmp(optarg, "blue") == 0)
  155. return COMPONENT_BLUE;
  156. return COMPONENT_UNSET;
  157. }
  158.  
  159. void print_help()
  160. {
  161. puts(
  162. "Usage: cw [OPTION]...\n"
  163. "Options:\n"
  164. " -h, --help: print this help\n"
  165. " -i, --info: print image info\n"
  166. " --inverse_image: inverse image colors\n"
  167. " --component_max: sum all components and write them to component\n"
  168. " specified by --component_name, -n\n"
  169. );
  170. }
  171.  
  172. int print_image_info(Image *image)
  173. {
  174. printf("Image info:\n");
  175. printf(" width: %d\n", (int)image->header.width);
  176. printf(" height: %d\n", (int)image->header.height);
  177. printf(" planes: %d\n", (int)image->header.planes);
  178. printf(" bits: %d\n", (int)image->header.bits);
  179. printf(" compression: %d\n", (int)image->header.compression);
  180. printf(" imagesize: %d\n", (int)image->header.imagesize);
  181. printf(" xresolution: %d\n", (int)image->header.xresolution);
  182. printf(" yresolution: %d\n", (int)image->header.yresolution);
  183. printf(" ncolours: %d\n", (int)image->header.ncolours);
  184. printf(" importantcolours: %d\n", (int)image->header.importantcolours);
  185.  
  186. return 1;
  187. }
  188.  
  189. int invert_image(Image *image)
  190. {
  191. for (int i = 0; i < image->header.height; i++) {
  192. for (int j = 0; j < image->header.width; j++) {
  193. image->rgb[i][j].r = 255 - image->rgb[i][j].r;
  194. image->rgb[i][j].g = 255 - image->rgb[i][j].g;
  195. image->rgb[i][j].b = 255 - image->rgb[i][j].b;
  196. }
  197. }
  198.  
  199. return 1;
  200. }
  201.  
  202. int components_sum(Image *image, int component_name)
  203. {
  204. if (component_name == COMPONENT_UNSET) {
  205. fputs("Component name must be specified\n", stderr);
  206. return 0;
  207. }
  208.  
  209. for (int i = 0; i < image->header.height; i++) {
  210. for (int j = 0; j < image->header.width; j++) {
  211. int sum = image->rgb[i][j].r + image->rgb[i][j].g + image->rgb[i][j].b;
  212. switch (component_name) {
  213. case COMPONENT_RED: image->rgb[i][j].r = sum; break;
  214. case COMPONENT_GREEN: image->rgb[i][j].g = sum; break;
  215. case COMPONENT_BLUE: image->rgb[i][j].b = sum; break;
  216. }
  217. }
  218. }
  219.  
  220. return 1;
  221. }
  222.  
  223. int main(int argc, char **argv)
  224. {
  225. puts("Course work for option 3.2, created by Maxim Chernov");
  226. int function = 0;
  227.  
  228. int opt = getopt_long(argc, argv, shortopts, longopts, NULL);
  229. int component_name = COMPONENT_UNSET;
  230. char *input = NULL;
  231. char *output = "out.bmp";
  232.  
  233. while (opt != -1) {
  234. if (opt == '?') {
  235. fputs("Invalid option or missing argument\n", stderr);
  236. return EXIT_ERROR;
  237. }
  238.  
  239. switch (opt) {
  240. case 'h':
  241. print_help();
  242. return 0;
  243. case 'i':
  244. case OPTION_INVERSE:
  245. case OPTION_COMPONENT_SUM:
  246. function = opt;
  247. break;
  248. case 'n':
  249. component_name = get_component_name();
  250. if (component_name == COMPONENT_UNSET) {
  251. fputs("Invalid component name\n", stderr);
  252. return EXIT_ERROR;
  253. }
  254. break;
  255. case 'I':
  256. input = optarg;
  257. break;
  258. case 'O':
  259. output = optarg;
  260. break;
  261. }
  262.  
  263. opt = getopt_long(argc, argv, shortopts, longopts, NULL);
  264. }
  265.  
  266. if (function == 0) {
  267. fputs("No function specified\n", stderr);
  268. return EXIT_ERROR;
  269. }
  270.  
  271. if (input == NULL) {
  272. if (optind >= argc) {
  273. fputs("No input file specified\n", stderr);
  274. return EXIT_ERROR;
  275. }
  276. input = argv[optind];
  277. }
  278.  
  279. Image image;
  280. if (!create_image(&image, input))
  281. return EXIT_ERROR;
  282.  
  283. int ret;
  284. switch (function) {
  285. case 'i':
  286. ret = print_image_info(&image);
  287. break;
  288. case OPTION_INVERSE:
  289. ret = invert_image(&image);
  290. break;
  291. case OPTION_COMPONENT_SUM:
  292. ret = components_sum(&image, component_name);
  293. break;
  294. }
  295.  
  296. if (ret == 0) {
  297. destroy_image(&image);
  298. return EXIT_ERROR;
  299. }
  300.  
  301. if (function != 'i' && !save_image(&image, output)) {
  302. destroy_image(&image);
  303. return EXIT_ERROR;
  304. }
  305.  
  306. destroy_image(&image);
  307. return 0;
  308. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement