123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <jpeglib.h>
- #include <omp.h>
-
- unsigned char *process_image(
- unsigned char *input_image, int input_width, int input_height,
- int desired_width, int desired_height) {
- unsigned char *output = calloc(3, desired_width * desired_height);
-
- double scale_w = (double)desired_width / (double)input_width;
- double scale_h = (double)desired_height / (double)input_height;
- double scale;
- printf("scales are %fx%f\n", scale_w, scale_h);
- int rect_x, rect_y, rect_w, rect_h;
- if (scale_w < scale_h) {
- printf("too wide?\n");
- scale = scale_w;
- } else {
- printf("too tall?\n");
- scale = scale_h;
- }
-
- rect_w = input_width * scale;
- rect_h = input_height * scale;
- rect_x = (desired_width - rect_w) / 2.0;
- rect_y = (desired_height - rect_h) / 2.0;
-
- printf("rect is %ix%i:%i,%i\n", rect_w, rect_h, rect_x, rect_y);
-
- // Write main image
- #pragma omp parallel for
- for (int y = 0; y < rect_h; ++y) {
- for (int x = 0; x < rect_w; ++x) {
- int input_y = y / scale;
- int input_x = x / scale;
- int input_idx = input_y * input_width * 3 + input_x * 3;
- int output_idx = (y + rect_y) * desired_width * 3 + (x + rect_x) * 3;
- output[output_idx + 0] = input_image[input_idx + 0];
- output[output_idx + 1] = input_image[input_idx + 1];
- output[output_idx + 2] = input_image[input_idx + 2];
- }
- }
-
- return output;
- }
-
- unsigned char *read_jpg(FILE *in, int *width, int *height) {
- struct jpeg_decompress_struct cinfo = { 0 };
- struct jpeg_error_mgr jerr = { 0 };
- cinfo.err = jpeg_std_error(&jerr);
-
- jpeg_create_decompress(&cinfo);
- jpeg_stdio_src(&cinfo, in);
- jpeg_read_header(&cinfo, TRUE);
- jpeg_start_decompress(&cinfo);
-
- *width = cinfo.output_width;
- *height = cinfo.output_height;
- int bytes_per_line = cinfo.output_width * 3;
- unsigned char *image = malloc(bytes_per_line * cinfo.output_height);
-
- /* Make a one-row-high sample array that will go away when done with image */
- JSAMPARRAY buffer = (*cinfo.mem->alloc_sarray)
- ((j_common_ptr)&cinfo, JPOOL_IMAGE, bytes_per_line, 1);
-
- while (cinfo.output_scanline < cinfo.output_height) {
- jpeg_read_scanlines(&cinfo, buffer, 1);
- /* Assume put_scanline_someplace wants a pointer and sample count. */
- memcpy(&image[bytes_per_line * (cinfo.output_scanline - 1)], buffer[0], bytes_per_line);
- }
-
- jpeg_finish_decompress(&cinfo);
- jpeg_destroy_decompress(&cinfo);
-
- return image;
- }
-
- void write_jpg(FILE *out, unsigned char *image, int width, int height) {
- struct jpeg_compress_struct cinfo = { 0 };
- struct jpeg_error_mgr jerr = { 0 };
- cinfo.err = jpeg_std_error(&jerr);
-
- jpeg_create_compress(&cinfo);
- jpeg_stdio_dest(&cinfo, out);
-
- printf("writing %ix%i\n", width, height);
- cinfo.image_width = width;
- cinfo.image_height = height;
- cinfo.input_components = 3;
- cinfo.in_color_space = JCS_RGB;
-
- jpeg_set_defaults(&cinfo);
- jpeg_set_quality(&cinfo, 90, FALSE);
- jpeg_start_compress(&cinfo, TRUE);
-
- int bytes_per_line = width * 3;
- JSAMPROW row_pointer[1];
-
- while (cinfo.next_scanline < cinfo.image_height) {
- row_pointer[0] = &image[cinfo.next_scanline * bytes_per_line];
- jpeg_write_scanlines(&cinfo, row_pointer, 1);
- }
-
- jpeg_finish_compress(&cinfo);
- jpeg_destroy_compress(&cinfo);
- }
-
- int main(int argc, char **argv) {
- if (argc != 4) {
- printf("Usage: %s <resolution> <input> <output>\n", argv[0]);
- return EXIT_FAILURE;
- }
-
- int desired_width, desired_height;
- if (sscanf(argv[1], "%ix%i", &desired_width, &desired_height) != 2) {
- fprintf(stderr, "Error parsing resolution '%s'\n", argv[1]);
- return EXIT_FAILURE;
- }
-
- FILE *in;
- if (strcmp(argv[2], "-") == 0) {
- in = stdin;
- } else {
- in = fopen(argv[2], "r");
- if (in == NULL) {
- perror(argv[2]);
- return EXIT_FAILURE;
- }
- }
-
- int input_width, input_height;
- unsigned char *input_image = read_jpg(in, &input_width, &input_height);
- fclose(in);
-
- unsigned char *output_image = process_image(
- input_image, input_width, input_height, desired_width, desired_height);
- free(input_image);
-
- FILE *out;
- if (strcmp(argv[3], "-") == 0) {
- out = stdout;
- } else {
- out = fopen(argv[3], "w");
- if (out == NULL) {
- perror(argv[3]);
- free(output_image);
- return EXIT_FAILURE;
- }
- }
-
- write_jpg(out, output_image, desired_width, desired_height);
- free(output_image);
-
- return EXIT_SUCCESS;
- }
|