Simple and fast tool to add a fancy blurred letterbox effect to images.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

blurrerbox.c 4.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <jpeglib.h>
  5. #include <omp.h>
  6. unsigned char *process_image(
  7. unsigned char *input_image, int input_width, int input_height,
  8. int desired_width, int desired_height) {
  9. unsigned char *output = calloc(3, desired_width * desired_height);
  10. double scale_w = (double)desired_width / (double)input_width;
  11. double scale_h = (double)desired_height / (double)input_height;
  12. double scale;
  13. printf("scales are %fx%f\n", scale_w, scale_h);
  14. int rect_x, rect_y, rect_w, rect_h;
  15. if (scale_w < scale_h) {
  16. printf("too wide?\n");
  17. scale = scale_w;
  18. } else {
  19. printf("too tall?\n");
  20. scale = scale_h;
  21. }
  22. rect_w = input_width * scale;
  23. rect_h = input_height * scale;
  24. rect_x = (desired_width - rect_w) / 2.0;
  25. rect_y = (desired_height - rect_h) / 2.0;
  26. printf("rect is %ix%i:%i,%i\n", rect_w, rect_h, rect_x, rect_y);
  27. // Write main image
  28. #pragma omp parallel for
  29. for (int y = 0; y < rect_h; ++y) {
  30. for (int x = 0; x < rect_w; ++x) {
  31. int input_y = y / scale;
  32. int input_x = x / scale;
  33. int input_idx = input_y * input_width * 3 + input_x * 3;
  34. int output_idx = (y + rect_y) * desired_width * 3 + (x + rect_x) * 3;
  35. output[output_idx + 0] = input_image[input_idx + 0];
  36. output[output_idx + 1] = input_image[input_idx + 1];
  37. output[output_idx + 2] = input_image[input_idx + 2];
  38. }
  39. }
  40. return output;
  41. }
  42. unsigned char *read_jpg(FILE *in, int *width, int *height) {
  43. struct jpeg_decompress_struct cinfo = { 0 };
  44. struct jpeg_error_mgr jerr = { 0 };
  45. cinfo.err = jpeg_std_error(&jerr);
  46. jpeg_create_decompress(&cinfo);
  47. jpeg_stdio_src(&cinfo, in);
  48. jpeg_read_header(&cinfo, TRUE);
  49. jpeg_start_decompress(&cinfo);
  50. *width = cinfo.output_width;
  51. *height = cinfo.output_height;
  52. int bytes_per_line = cinfo.output_width * 3;
  53. unsigned char *image = malloc(bytes_per_line * cinfo.output_height);
  54. /* Make a one-row-high sample array that will go away when done with image */
  55. JSAMPARRAY buffer = (*cinfo.mem->alloc_sarray)
  56. ((j_common_ptr)&cinfo, JPOOL_IMAGE, bytes_per_line, 1);
  57. while (cinfo.output_scanline < cinfo.output_height) {
  58. jpeg_read_scanlines(&cinfo, buffer, 1);
  59. /* Assume put_scanline_someplace wants a pointer and sample count. */
  60. memcpy(&image[bytes_per_line * (cinfo.output_scanline - 1)], buffer[0], bytes_per_line);
  61. }
  62. jpeg_finish_decompress(&cinfo);
  63. jpeg_destroy_decompress(&cinfo);
  64. return image;
  65. }
  66. void write_jpg(FILE *out, unsigned char *image, int width, int height) {
  67. struct jpeg_compress_struct cinfo = { 0 };
  68. struct jpeg_error_mgr jerr = { 0 };
  69. cinfo.err = jpeg_std_error(&jerr);
  70. jpeg_create_compress(&cinfo);
  71. jpeg_stdio_dest(&cinfo, out);
  72. printf("writing %ix%i\n", width, height);
  73. cinfo.image_width = width;
  74. cinfo.image_height = height;
  75. cinfo.input_components = 3;
  76. cinfo.in_color_space = JCS_RGB;
  77. jpeg_set_defaults(&cinfo);
  78. jpeg_set_quality(&cinfo, 90, FALSE);
  79. jpeg_start_compress(&cinfo, TRUE);
  80. int bytes_per_line = width * 3;
  81. JSAMPROW row_pointer[1];
  82. while (cinfo.next_scanline < cinfo.image_height) {
  83. row_pointer[0] = &image[cinfo.next_scanline * bytes_per_line];
  84. jpeg_write_scanlines(&cinfo, row_pointer, 1);
  85. }
  86. jpeg_finish_compress(&cinfo);
  87. jpeg_destroy_compress(&cinfo);
  88. }
  89. int main(int argc, char **argv) {
  90. if (argc != 4) {
  91. printf("Usage: %s <resolution> <input> <output>\n", argv[0]);
  92. return EXIT_FAILURE;
  93. }
  94. int desired_width, desired_height;
  95. if (sscanf(argv[1], "%ix%i", &desired_width, &desired_height) != 2) {
  96. fprintf(stderr, "Error parsing resolution '%s'\n", argv[1]);
  97. return EXIT_FAILURE;
  98. }
  99. FILE *in;
  100. if (strcmp(argv[2], "-") == 0) {
  101. in = stdin;
  102. } else {
  103. in = fopen(argv[2], "r");
  104. if (in == NULL) {
  105. perror(argv[2]);
  106. return EXIT_FAILURE;
  107. }
  108. }
  109. int input_width, input_height;
  110. unsigned char *input_image = read_jpg(in, &input_width, &input_height);
  111. fclose(in);
  112. unsigned char *output_image = process_image(
  113. input_image, input_width, input_height, desired_width, desired_height);
  114. free(input_image);
  115. FILE *out;
  116. if (strcmp(argv[3], "-") == 0) {
  117. out = stdout;
  118. } else {
  119. out = fopen(argv[3], "w");
  120. if (out == NULL) {
  121. perror(argv[3]);
  122. free(output_image);
  123. return EXIT_FAILURE;
  124. }
  125. }
  126. write_jpg(out, output_image, desired_width, desired_height);
  127. free(output_image);
  128. return EXIT_SUCCESS;
  129. }