From: Steinar H. Gunderson Date: Sun, 21 Jun 2009 13:43:28 +0000 (+0200) Subject: Add support for grayscale JPEGs, although in a quite ugly way. X-Git-Url: https://git.sesse.net/?p=qscale;a=commitdiff_plain;h=285b119e49d181da10e41c0127ca3c324c786503 Add support for grayscale JPEGs, although in a quite ugly way. --- diff --git a/libqscale.c b/libqscale.c index b784294..47b6fe8 100644 --- a/libqscale.c +++ b/libqscale.c @@ -75,11 +75,11 @@ qscale_img *qscale_load_jpeg_from_stdio(FILE *file) dinfo.raw_data_out = TRUE; jpeg_start_decompress(&dinfo); - /* We do not handle anything but YCbCr images (yet?). */ - if (dinfo.num_components != 3) { + if (dinfo.num_components != 1 && dinfo.num_components != 3) { qscale_destroy(img); return NULL; } + img->num_components = dinfo.num_components; img->width = dinfo.image_width; img->height = dinfo.image_height; @@ -87,30 +87,40 @@ qscale_img *qscale_load_jpeg_from_stdio(FILE *file) 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; + if (img->num_components == 3) { + 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->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->samp_h0 = dinfo.comp_info[0].h_samp_factor; img->samp_v0 = dinfo.comp_info[0].v_samp_factor; - img->samp_h1 = dinfo.comp_info[1].h_samp_factor; - img->samp_v1 = dinfo.comp_info[1].v_samp_factor; + if (img->num_components == 3) { + img->samp_h1 = dinfo.comp_info[1].h_samp_factor; + img->samp_v1 = dinfo.comp_info[1].v_samp_factor; - img->samp_h2 = dinfo.comp_info[2].h_samp_factor; - img->samp_v2 = dinfo.comp_info[2].v_samp_factor; + img->samp_h2 = dinfo.comp_info[2].h_samp_factor; + img->samp_v2 = dinfo.comp_info[2].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) { + if (img->data_y == NULL) { qscale_destroy(img); return NULL; } + if (img->num_components == 3) { + 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_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; @@ -123,8 +133,10 @@ qscale_img *qscale_load_jpeg_from_stdio(FILE *file) 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; + if (img->num_components == 3) { + 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; @@ -568,37 +580,46 @@ qscale_img *qscale_scale(qscale_img *src, unsigned width, unsigned height, unsig dst->width = width; dst->height = height; + dst->num_components = src->num_components; unsigned max_samp_h, max_samp_v; max_samp_h = samp_h0; - if (samp_h1 > max_samp_h) - max_samp_h = samp_h1; - if (samp_h2 > max_samp_h) - max_samp_h = samp_h2; + if (src->num_components == 3) { + if (samp_h1 > max_samp_h) + max_samp_h = samp_h1; + if (samp_h2 > max_samp_h) + max_samp_h = samp_h2; + } max_samp_v = samp_v0; - if (samp_v1 > max_samp_v) - max_samp_v = samp_v1; - if (samp_v2 > max_samp_v) - max_samp_v = samp_v2; + if (src->num_components == 3) { + if (samp_v1 > max_samp_v) + max_samp_v = samp_v1; + if (samp_v2 > max_samp_v) + max_samp_v = samp_v2; + } dst->w0 = width * samp_h0 / max_samp_h; dst->h0 = height * samp_v0 / max_samp_v; - dst->w1 = width * samp_h1 / max_samp_h; - dst->h1 = height * samp_v1 / max_samp_v; + if (src->num_components == 3) { + dst->w1 = width * samp_h1 / max_samp_h; + dst->h1 = height * samp_v1 / max_samp_v; - dst->w2 = width * samp_h2 / max_samp_h; - dst->h2 = height * samp_v2 / max_samp_v; + dst->w2 = width * samp_h2 / max_samp_h; + dst->h2 = height * samp_v2 / max_samp_v; + } dst->samp_h0 = samp_h0; dst->samp_v0 = samp_v0; - dst->samp_h1 = samp_h1; - dst->samp_v1 = samp_v1; + if (src->num_components == 3) { + dst->samp_h1 = samp_h1; + dst->samp_v1 = samp_v1; - dst->samp_h2 = samp_h2; - dst->samp_v2 = samp_v2; + dst->samp_h2 = samp_h2; + dst->samp_v2 = samp_v2; + } unsigned dstride0 = (dst->w0 + DCTSIZE-1) & ~(DCTSIZE-1); unsigned dstride1 = (dst->w1 + DCTSIZE-1) & ~(DCTSIZE-1); @@ -616,19 +637,21 @@ qscale_img *qscale_scale(qscale_img *src, unsigned width, unsigned height, unsig hscale(npix, dst->data_y, src->w0, dst->h0, dst->w0, sstride0, dstride0, scaling_filter); free(npix); } - { - float *npix = (float*)memalign(16, sstride1 * dst->h1 * sizeof(float)); - vscale(src->data_cr, npix, sstride1, src->h1, dst->h1, sstride1, scaling_filter); - dst->data_cr = (unsigned char *)malloc(dst->h1 * dstride1); - hscale(npix, dst->data_cr, src->w1, dst->h1, dst->w1, sstride1, dstride1, scaling_filter); - free(npix); - } - { - float *npix = (float*)memalign(16, sstride2 * dst->h2 * sizeof(float)); - vscale(src->data_cb, npix, sstride2, src->h2, dst->h2, sstride2, scaling_filter); - dst->data_cb = (unsigned char *)malloc(dst->h2 * dstride2); - hscale(npix, dst->data_cb, src->w2, dst->h2, dst->w2, sstride2, dstride2, scaling_filter); - free(npix); + if (src->num_components == 3) { + { + float *npix = (float*)memalign(16, sstride1 * dst->h1 * sizeof(float)); + vscale(src->data_cr, npix, sstride1, src->h1, dst->h1, sstride1, scaling_filter); + dst->data_cr = (unsigned char *)malloc(dst->h1 * dstride1); + hscale(npix, dst->data_cr, src->w1, dst->h1, dst->w1, sstride1, dstride1, scaling_filter); + free(npix); + } + { + float *npix = (float*)memalign(16, sstride2 * dst->h2 * sizeof(float)); + vscale(src->data_cb, npix, sstride2, src->h2, dst->h2, sstride2, scaling_filter); + dst->data_cb = (unsigned char *)malloc(dst->h2 * dstride2); + hscale(npix, dst->data_cb, src->w2, dst->h2, dst->w2, sstride2, dstride2, scaling_filter); + free(npix); + } } return dst; @@ -654,7 +677,7 @@ int qscale_save_jpeg_to_stdio(const qscale_img *img, FILE *file, unsigned jpeg_q cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); jpeg_stdio_dest(&cinfo, file); - cinfo.input_components = 3; + cinfo.input_components = img->num_components; jpeg_set_defaults(&cinfo); jpeg_set_quality(&cinfo, jpeg_quality, FALSE); @@ -665,13 +688,19 @@ int qscale_save_jpeg_to_stdio(const qscale_img *img, FILE *file, unsigned jpeg_q cinfo.image_width = img->width; cinfo.image_height = img->height; cinfo.raw_data_in = TRUE; - jpeg_set_colorspace(&cinfo, JCS_YCbCr); + if (img->num_components == 3) { + jpeg_set_colorspace(&cinfo, JCS_YCbCr); + } else { + jpeg_set_colorspace(&cinfo, JCS_GRAYSCALE); + } cinfo.comp_info[0].h_samp_factor = img->samp_h0; cinfo.comp_info[0].v_samp_factor = img->samp_v0; - cinfo.comp_info[1].h_samp_factor = img->samp_h1; - cinfo.comp_info[1].v_samp_factor = img->samp_v1; - cinfo.comp_info[2].h_samp_factor = img->samp_h2; - cinfo.comp_info[2].v_samp_factor = img->samp_v2; + if (img->num_components == 3) { + cinfo.comp_info[1].h_samp_factor = img->samp_h1; + cinfo.comp_info[1].v_samp_factor = img->samp_v1; + cinfo.comp_info[2].h_samp_factor = img->samp_h2; + cinfo.comp_info[2].v_samp_factor = img->samp_v2; + } jpeg_start_compress(&cinfo, TRUE); unsigned dstride0 = (img->w0 + DCTSIZE-1) & ~(DCTSIZE-1); @@ -695,17 +724,20 @@ int qscale_save_jpeg_to_stdio(const qscale_img *img, FILE *file, unsigned jpeg_q if (yline > img->h0 - 1) yline = img->h0 - 1; - int cbline = i + blocks*DCTSIZE*cinfo.comp_info[1].v_samp_factor; - if (cbline > img->h1 - 1) - cbline = img->h1 - 1; + y_row_ptrs[i] = img->data_y + yline * dstride0; + + if (img->num_components == 3) { + int cbline = i + blocks*DCTSIZE*cinfo.comp_info[1].v_samp_factor; + if (cbline > img->h1 - 1) + cbline = img->h1 - 1; - int crline = i + blocks*DCTSIZE*cinfo.comp_info[2].v_samp_factor; - if (crline > img->h2 - 1) - crline = img->h2 - 1; + int crline = i + blocks*DCTSIZE*cinfo.comp_info[2].v_samp_factor; + if (crline > img->h2 - 1) + crline = img->h2 - 1; - y_row_ptrs[i] = img->data_y + yline * dstride0; - cb_row_ptrs[i] = img->data_cb + cbline * dstride1; - cr_row_ptrs[i] = img->data_cr + crline * dstride2; + cb_row_ptrs[i] = img->data_cb + cbline * dstride1; + cr_row_ptrs[i] = img->data_cr + crline * dstride2; + } } total_lines += max_lines; diff --git a/libqscale.h b/libqscale.h index d9e18e7..409a9bb 100644 --- a/libqscale.h +++ b/libqscale.h @@ -8,6 +8,9 @@ typedef struct { /* True image size */ unsigned width, height; + /* 1 = B/W, 3 = YCbCr */ + unsigned num_components; + /* Component image sizes (possibly subsampled) */ unsigned w0, h0; unsigned w1, h1;