From cce321fe623a347fd2bda4e442bed42dfc9299c7 Mon Sep 17 00:00:00 2001 From: "sgunderson@bigfoot.com" <> Date: Wed, 28 May 2008 22:09:25 -0700 Subject: [PATCH] Move JPEG loading into libqscale. --- Makefile | 4 +- libqscale.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++ qscale.c | 103 ++++++++++++++++------------------------------------ 3 files changed, 133 insertions(+), 74 deletions(-) create mode 100644 libqscale.c diff --git a/Makefile b/Makefile index df52768..37a0dd8 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,10 @@ CC=gcc -OBJS=qscale.o +OBJS=qscale.o libqscale.o CFLAGS=-Wall -O2 -msse LDFLAGS=-lm -ljpeg -qscale: qscale.o +qscale: qscale.o libqscale.o clean: $(RM) qscale $(OBJS) diff --git a/libqscale.c b/libqscale.c new file mode 100644 index 0000000..b744a9b --- /dev/null +++ b/libqscale.c @@ -0,0 +1,100 @@ +#include +#include +#include + +#include "libqscale.h" + +qscale_img *qscale_load_jpeg(const char *filename) +{ + FILE *file = fopen(filename, "rb"); + qscale_img *img; + if (file == NULL) { + return NULL; + } + + img = qscale_load_jpeg_from_stdio(file); + + fclose(file); + return img; +} + +qscale_img *qscale_load_jpeg_from_stdio(FILE *file) +{ + qscale_img *img = (qscale_img *)malloc(sizeof(qscale_img)); + if (img == NULL) { + return NULL; + } + + img->data_y = img->data_cb = img->data_cr = NULL; + + /* FIXME: Better error handling here (ie., return NULL). */ + struct jpeg_decompress_struct dinfo; + struct jpeg_error_mgr jerr; + dinfo.err = jpeg_std_error(&jerr); + jpeg_create_decompress(&dinfo); + jpeg_stdio_src(&dinfo, stdin); + jpeg_read_header(&dinfo, TRUE); + dinfo.raw_data_out = TRUE; + jpeg_start_decompress(&dinfo); + + /* We do not handle anything but YCbCr images (yet?). */ + if (dinfo.num_components != 3) { + qscale_destroy(img); + return NULL; + } + + img->width = dinfo.image_width; + img->height = dinfo.image_height; + + img->w0 = dinfo.image_width * dinfo.comp_info[0].h_samp_factor / dinfo.max_h_samp_factor; + img->h0 = dinfo.image_height * dinfo.comp_info[0].v_samp_factor / dinfo.max_v_samp_factor; + + img->w1 = dinfo.image_width * dinfo.comp_info[1].h_samp_factor / dinfo.max_h_samp_factor; + img->h1 = dinfo.image_height * dinfo.comp_info[1].v_samp_factor / dinfo.max_v_samp_factor; + + img->w2 = dinfo.image_width * dinfo.comp_info[2].h_samp_factor / dinfo.max_h_samp_factor; + img->h2 = dinfo.image_height * dinfo.comp_info[2].v_samp_factor / dinfo.max_v_samp_factor; + + img->data_y = (JSAMPLE*)memalign(16, dinfo.comp_info[0].height_in_blocks * dinfo.comp_info[0].width_in_blocks * DCTSIZE * DCTSIZE); + img->data_cb = (JSAMPLE*)memalign(16, dinfo.comp_info[1].height_in_blocks * dinfo.comp_info[1].width_in_blocks * DCTSIZE * DCTSIZE); + img->data_cr = (JSAMPLE*)memalign(16, dinfo.comp_info[2].height_in_blocks * dinfo.comp_info[2].width_in_blocks * DCTSIZE * DCTSIZE); + + if (img->data_y == NULL || img->data_cb == NULL || img->data_cr == NULL) { + qscale_destroy(img); + return NULL; + } + + int total_lines = 0, blocks = 0; + while (total_lines < dinfo.comp_info[0].height_in_blocks * DCTSIZE) { + unsigned max_lines = dinfo.max_v_samp_factor * DCTSIZE; + + JSAMPROW y_row_ptrs[max_lines]; + JSAMPROW cb_row_ptrs[max_lines]; + JSAMPROW cr_row_ptrs[max_lines]; + JSAMPROW* ptrs[] = { y_row_ptrs, cb_row_ptrs, cr_row_ptrs }; + + int i; + for (i = 0; i < max_lines; ++i) { + y_row_ptrs[i] = img->data_y + (i+blocks*DCTSIZE*dinfo.comp_info[0].v_samp_factor) * dinfo.comp_info[0].width_in_blocks * DCTSIZE; + cb_row_ptrs[i] = img->data_cb + (i+blocks*DCTSIZE*dinfo.comp_info[1].v_samp_factor) * dinfo.comp_info[1].width_in_blocks * DCTSIZE; + cr_row_ptrs[i] = img->data_cr + (i+blocks*DCTSIZE*dinfo.comp_info[2].v_samp_factor) * dinfo.comp_info[2].width_in_blocks * DCTSIZE; + } + + total_lines += max_lines; + ++blocks; + + if (jpeg_read_raw_data(&dinfo, ptrs, max_lines) == 0) + break; + } + + jpeg_destroy_decompress(&dinfo); + return img; +} + +void qscale_destroy(qscale_img *img) +{ + free(img->data_y); + free(img->data_cb); + free(img->data_cr); + free(img); +} diff --git a/qscale.c b/qscale.c index d89c8b9..440f9de 100644 --- a/qscale.c +++ b/qscale.c @@ -22,15 +22,16 @@ #include #include #include "jpeglib.h" +#include "libqscale.h" /* The number of pixels to process at a time when scaling vertically. */ #define CACHE_LINE_FACTOR 16 /* Whether to use SSE for horizontal scaling or not (requires SSE3). */ -#define USE_HORIZONTAL_SSE 1 +#define USE_HORIZONTAL_SSE 0 /* Whether to use SSE for vertical scaling or not (requires only SSE1). */ -#define USE_VERTICAL_SSE 1 +#define USE_VERTICAL_SSE 0 #if USE_VERTICAL_SSE #undef CACHE_LINE_FACTOR @@ -403,85 +404,41 @@ int main(int argc, char **argv) unsigned nw1 = nominal_w * samp_h1 / max_samp_h, nh1 = nominal_h * samp_v1 / max_samp_v; unsigned nw2 = nominal_w * samp_h2 / max_samp_h, nh2 = nominal_h * samp_v2 / max_samp_v; - unsigned stride0 = (nw0 + DCTSIZE-1) & ~(DCTSIZE-1); - unsigned stride1 = (nw1 + DCTSIZE-1) & ~(DCTSIZE-1); - unsigned stride2 = (nw2 + DCTSIZE-1) & ~(DCTSIZE-1); + unsigned dstride0 = (nw0 + DCTSIZE-1) & ~(DCTSIZE-1); + unsigned dstride1 = (nw1 + DCTSIZE-1) & ~(DCTSIZE-1); + unsigned dstride2 = (nw2 + DCTSIZE-1) & ~(DCTSIZE-1); - struct jpeg_decompress_struct dinfo; - struct jpeg_error_mgr jerr; - dinfo.err = jpeg_std_error(&jerr); - jpeg_create_decompress(&dinfo); - jpeg_stdio_src(&dinfo, stdin); - jpeg_read_header(&dinfo, TRUE); - dinfo.raw_data_out = TRUE; - jpeg_start_decompress(&dinfo); - - unsigned w0 = dinfo.image_width * dinfo.comp_info[0].h_samp_factor / dinfo.max_h_samp_factor; - unsigned h0 = dinfo.image_height * dinfo.comp_info[0].v_samp_factor / dinfo.max_v_samp_factor; - - unsigned w1 = dinfo.image_width * dinfo.comp_info[1].h_samp_factor / dinfo.max_h_samp_factor; - unsigned h1 = dinfo.image_height * dinfo.comp_info[1].v_samp_factor / dinfo.max_v_samp_factor; - - unsigned w2 = dinfo.image_width * dinfo.comp_info[2].h_samp_factor / dinfo.max_h_samp_factor; - unsigned h2 = dinfo.image_height * dinfo.comp_info[2].v_samp_factor / dinfo.max_v_samp_factor; - - fprintf(stderr, "Scaling using Lanczos filter:\n"); - fprintf(stderr, " Y component: %ux%u -> %ux%u\n", dinfo.comp_info[0].width_in_blocks * DCTSIZE, dinfo.comp_info[0].height_in_blocks * DCTSIZE, nw0, nh0); - fprintf(stderr, " Cb component: %ux%u -> %ux%u\n", dinfo.comp_info[1].width_in_blocks * DCTSIZE, dinfo.comp_info[1].height_in_blocks * DCTSIZE, nw1, nh1); - fprintf(stderr, " Cr component: %ux%u -> %ux%u\n", dinfo.comp_info[2].width_in_blocks * DCTSIZE, dinfo.comp_info[2].height_in_blocks * DCTSIZE, nw2, nh2); - - JSAMPLE *data_y = (JSAMPLE*)memalign(16, dinfo.comp_info[0].height_in_blocks * dinfo.comp_info[0].width_in_blocks * DCTSIZE * DCTSIZE); - JSAMPLE *data_cb = (JSAMPLE*)memalign(16, dinfo.comp_info[1].height_in_blocks * dinfo.comp_info[1].width_in_blocks * DCTSIZE * DCTSIZE); - JSAMPLE *data_cr = (JSAMPLE*)memalign(16, dinfo.comp_info[2].height_in_blocks * dinfo.comp_info[2].width_in_blocks * DCTSIZE * DCTSIZE); + qscale_img *img = qscale_load_jpeg_from_stdio(stdin); + unsigned sstride0 = (img->w0 + DCTSIZE-1) & ~(DCTSIZE-1); + unsigned sstride1 = (img->w1 + DCTSIZE-1) & ~(DCTSIZE-1); + unsigned sstride2 = (img->w2 + DCTSIZE-1) & ~(DCTSIZE-1); + JSAMPLE *data_ny, *data_ncb, *data_ncr; - int total_lines = 0, blocks = 0; - while (total_lines < dinfo.comp_info[0].height_in_blocks * DCTSIZE) { - unsigned max_lines = dinfo.max_v_samp_factor * DCTSIZE; - - JSAMPROW y_row_ptrs[max_lines]; - JSAMPROW cb_row_ptrs[max_lines]; - JSAMPROW cr_row_ptrs[max_lines]; - JSAMPROW* ptrs[] = { y_row_ptrs, cb_row_ptrs, cr_row_ptrs }; - int i; - - for (i = 0; i < max_lines; ++i) { - y_row_ptrs[i] = data_y + (i+blocks*DCTSIZE*dinfo.comp_info[0].v_samp_factor) * dinfo.comp_info[0].width_in_blocks * DCTSIZE; - cb_row_ptrs[i] = data_cb + (i+blocks*DCTSIZE*dinfo.comp_info[1].v_samp_factor) * dinfo.comp_info[1].width_in_blocks * DCTSIZE; - cr_row_ptrs[i] = data_cr + (i+blocks*DCTSIZE*dinfo.comp_info[2].v_samp_factor) * dinfo.comp_info[2].width_in_blocks * DCTSIZE; - } - - total_lines += max_lines; - ++blocks; - - if (jpeg_read_raw_data(&dinfo, ptrs, max_lines) == 0) - break; - } - { - float *npix = (float*)memalign(16, dinfo.comp_info[0].width_in_blocks * DCTSIZE * nh0 * sizeof(float)); - vscale(data_y, npix, dinfo.comp_info[0].width_in_blocks * DCTSIZE, h0, nh0, dinfo.comp_info[0].width_in_blocks * DCTSIZE); - data_ny = (unsigned char *)malloc(nh0 * stride0); - hscale(npix, data_ny, w0, nh0, nw0, dinfo.comp_info[0].width_in_blocks * DCTSIZE, stride0); + float *npix = (float*)memalign(16, sstride0 * nh0 * sizeof(float)); + vscale(img->data_y, npix, sstride0, img->h0, nh0, sstride0); + data_ny = (unsigned char *)malloc(nh0 * dstride0); + hscale(npix, data_ny, img->w0, nh0, nw0, sstride0, dstride0); free(npix); } { - float *npix = (float*)memalign(16, dinfo.comp_info[1].width_in_blocks * DCTSIZE * nh1 * sizeof(float)); - vscale(data_cr, npix, dinfo.comp_info[1].width_in_blocks * DCTSIZE, h1, nh1, dinfo.comp_info[1].width_in_blocks * DCTSIZE); - data_ncr = (unsigned char *)malloc(nh1 * stride1); - hscale(npix, data_ncr, w1, nh1, nw1, dinfo.comp_info[1].width_in_blocks * DCTSIZE, stride1); + float *npix = (float*)memalign(16, sstride1 * nh1 * sizeof(float)); + vscale(img->data_cr, npix, sstride1, img->h1, nh1, sstride1); + data_ncr = (unsigned char *)malloc(nh1 * dstride1); + hscale(npix, data_ncr, img->w1, nh1, nw1, sstride1, dstride1); free(npix); } { - float *npix = (float*)memalign(16, dinfo.comp_info[2].width_in_blocks * DCTSIZE * nh2 * sizeof(float)); - vscale(data_cb, npix, dinfo.comp_info[2].width_in_blocks * DCTSIZE, h2, nh2, dinfo.comp_info[2].width_in_blocks * DCTSIZE); - data_ncb = (unsigned char *)malloc(nh2 * stride2); - hscale(npix, data_ncb, w2, nh2, nw2, dinfo.comp_info[2].width_in_blocks * DCTSIZE, stride2); + float *npix = (float*)memalign(16, sstride2 * nh2 * sizeof(float)); + vscale(img->data_cb, npix, sstride2, img->h2, nh2, sstride2); + data_ncb = (unsigned char *)malloc(nh2 * dstride2); + hscale(npix, data_ncb, img->w2, nh2, nw2, sstride2, dstride2); free(npix); } - jpeg_destroy_decompress(&dinfo); struct jpeg_compress_struct cinfo; + struct jpeg_error_mgr jerr; cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); jpeg_stdio_dest(&cinfo, stdout); @@ -500,8 +457,8 @@ int main(int argc, char **argv) cinfo.comp_info[2].v_samp_factor = samp_v2; jpeg_start_compress(&cinfo, TRUE); - total_lines = 0; - blocks = 0; + int total_lines = 0; + int blocks = 0; while (total_lines < cinfo.comp_info[0].height_in_blocks * DCTSIZE) { unsigned max_lines = cinfo.max_v_samp_factor * DCTSIZE; @@ -525,9 +482,9 @@ int main(int argc, char **argv) if (crline > nh2 - 1) crline = nh2 - 1; - y_row_ptrs[i] = data_ny + yline * stride0; - cb_row_ptrs[i] = data_ncb + cbline * stride1; - cr_row_ptrs[i] = data_ncr + crline * stride2; + y_row_ptrs[i] = data_ny + yline * dstride0; + cb_row_ptrs[i] = data_ncb + cbline * dstride1; + cr_row_ptrs[i] = data_ncr + crline * dstride2; } total_lines += max_lines; @@ -538,6 +495,8 @@ int main(int argc, char **argv) jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo); + qscale_destroy(img); + return 0; } -- 2.39.5