--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <malloc.h>
+
+#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);
+}
#include <string.h>
#include <stdlib.h>
#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
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);
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;
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;
jpeg_finish_compress(&cinfo);
jpeg_destroy_compress(&cinfo);
+ qscale_destroy(img);
+
return 0;
}