Browse Source

blurrerbox

master
Martin Dørum 4 years ago
commit
3ad00c9d24
2 changed files with 165 additions and 0 deletions
  1. 8
    0
      Makefile
  2. 157
    0
      blurrerbox.c

+ 8
- 0
Makefile View File

@@ -0,0 +1,8 @@
CFLAGS += -fopenmp $(shell pkg-config --cflags libjpeg) -g -fsanitize=address
LDFLAGS += -fopenmp $(shell pkg-config --libs libjpeg) -fsanitize=address

blurrerbox: blurrerbox.c

.PHONY: clean
clean:
rm -f blurrerbox

+ 157
- 0
blurrerbox.c View File

@@ -0,0 +1,157 @@
#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;
}

Loading…
Cancel
Save