Advertisement
jcdkiki

Untitled

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