]> git.sesse.net Git - qscale/blobdiff - libqscale.c
Move JPEG loading into libqscale.
[qscale] / libqscale.c
diff --git a/libqscale.c b/libqscale.c
new file mode 100644 (file)
index 0000000..b744a9b
--- /dev/null
@@ -0,0 +1,100 @@
+#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);
+}