]> git.sesse.net Git - qscale/commitdiff
Add support for grayscale JPEGs, although in a quite ugly way.
authorSteinar H. Gunderson <sesse@debian.org>
Sun, 21 Jun 2009 13:43:28 +0000 (15:43 +0200)
committerSteinar H. Gunderson <sesse@debian.org>
Sun, 21 Jun 2009 13:43:28 +0000 (15:43 +0200)
libqscale.c
libqscale.h

index b784294def3eedb9f4210bd187675b56dee71393..47b6fe8959c8d0db09545c0f3448a012658d6dde 100644 (file)
@@ -75,11 +75,11 @@ qscale_img *qscale_load_jpeg_from_stdio(FILE *file)
        dinfo.raw_data_out = TRUE;
        jpeg_start_decompress(&dinfo);
        
        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;
        }
                qscale_destroy(img);
                return NULL;
        }
+       img->num_components = dinfo.num_components;
 
        img->width = dinfo.image_width;
        img->height = dinfo.image_height;
 
        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->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_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_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;
        }
 
                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;
        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;
                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;
                 }
 
                 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->width = width;
        dst->height = height;
+       dst->num_components = src->num_components;
 
        unsigned max_samp_h, max_samp_v;
         max_samp_h = samp_h0;
 
        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;
 
         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->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_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);
 
        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);
        }
                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;
        }
 
        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.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);
 
         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;
         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[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);
         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;
 
                         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;
                 }
 
                 total_lines += max_lines;
index d9e18e7440ed7d8eabb768c02bd54e1e4d0e767b..409a9bb7488366ddee5770bd38489eaddae48a2a 100644 (file)
@@ -8,6 +8,9 @@ typedef struct {
        /* True image size */
        unsigned width, height;
 
        /* 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;
        /* Component image sizes (possibly subsampled) */
        unsigned w0, h0;
        unsigned w1, h1;