| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| #define JPEG_INTERNALS |
| #include "jinclude.h" |
| #include "jpeglib.h" |
| |
| |
| |
| |
| typedef struct { |
| struct jpeg_color_deconverter pub; |
| |
| |
| int * Cr_r_tab; |
| int * Cb_b_tab; |
| INT32 * Cr_g_tab; |
| INT32 * Cb_g_tab; |
| |
| |
| INT32 * rgb_y_tab; |
| } my_color_deconverter; |
| |
| typedef my_color_deconverter * my_cconvert_ptr; |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| #define SCALEBITS 16 |
| #define ONE_HALF ((INT32) 1 << (SCALEBITS-1)) |
| #define FIX(x) ((INT32) ((x) * (1L<<SCALEBITS) + 0.5)) |
| |
| |
| |
| |
| |
| |
| |
| |
| #define R_Y_OFF 0 |
| #define G_Y_OFF (1*(MAXJSAMPLE+1)) |
| #define B_Y_OFF (2*(MAXJSAMPLE+1)) |
| #define TABLE_SIZE (3*(MAXJSAMPLE+1)) |
| |
| |
| |
| |
| |
| |
| LOCAL(void) |
| build_ycc_rgb_table (j_decompress_ptr cinfo) |
| { |
| my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; |
| int i; |
| INT32 x; |
| SHIFT_TEMPS |
| |
| cconvert->Cr_r_tab = (int *) |
| (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, |
| (MAXJSAMPLE+1) * SIZEOF(int)); |
| cconvert->Cb_b_tab = (int *) |
| (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, |
| (MAXJSAMPLE+1) * SIZEOF(int)); |
| cconvert->Cr_g_tab = (INT32 *) |
| (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, |
| (MAXJSAMPLE+1) * SIZEOF(INT32)); |
| cconvert->Cb_g_tab = (INT32 *) |
| (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, |
| (MAXJSAMPLE+1) * SIZEOF(INT32)); |
| |
| for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { |
| |
| |
| |
| cconvert->Cr_r_tab[i] = (int) |
| RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS); |
| |
| cconvert->Cb_b_tab[i] = (int) |
| RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS); |
| |
| cconvert->Cr_g_tab[i] = (- FIX(0.71414)) * x; |
| |
| |
| cconvert->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF; |
| } |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| METHODDEF(void) |
| ycc_rgb_convert (j_decompress_ptr cinfo, |
| JSAMPIMAGE input_buf, JDIMENSION input_row, |
| JSAMPARRAY output_buf, int num_rows) |
| { |
| my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; |
| register int y, cb, cr; |
| register JSAMPROW outptr; |
| register JSAMPROW inptr0, inptr1, inptr2; |
| register JDIMENSION col; |
| JDIMENSION num_cols = cinfo->output_width; |
| |
| register JSAMPLE * range_limit = cinfo->sample_range_limit; |
| register int * Crrtab = cconvert->Cr_r_tab; |
| register int * Cbbtab = cconvert->Cb_b_tab; |
| register INT32 * Crgtab = cconvert->Cr_g_tab; |
| register INT32 * Cbgtab = cconvert->Cb_g_tab; |
| SHIFT_TEMPS |
| |
| while (--num_rows >= 0) { |
| inptr0 = input_buf[0][input_row]; |
| inptr1 = input_buf[1][input_row]; |
| inptr2 = input_buf[2][input_row]; |
| input_row++; |
| outptr = *output_buf++; |
| for (col = 0; col < num_cols; col++) { |
| y = GETJSAMPLE(inptr0[col]); |
| cb = GETJSAMPLE(inptr1[col]); |
| cr = GETJSAMPLE(inptr2[col]); |
| |
| outptr[RGB_RED] = range_limit[y + Crrtab[cr]]; |
| outptr[RGB_GREEN] = range_limit[y + |
| ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], |
| SCALEBITS))]; |
| outptr[RGB_BLUE] = range_limit[y + Cbbtab[cb]]; |
| outptr += RGB_PIXELSIZE; |
| } |
| } |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| LOCAL(void) |
| build_rgb_y_table (j_decompress_ptr cinfo) |
| { |
| my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; |
| INT32 * rgb_y_tab; |
| INT32 i; |
| |
| |
| cconvert->rgb_y_tab = rgb_y_tab = (INT32 *) |
| (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, |
| (TABLE_SIZE * SIZEOF(INT32))); |
| |
| for (i = 0; i <= MAXJSAMPLE; i++) { |
| rgb_y_tab[i+R_Y_OFF] = FIX(0.29900) * i; |
| rgb_y_tab[i+G_Y_OFF] = FIX(0.58700) * i; |
| rgb_y_tab[i+B_Y_OFF] = FIX(0.11400) * i + ONE_HALF; |
| } |
| } |
| |
| |
| |
| |
| |
| |
| METHODDEF(void) |
| rgb_gray_convert (j_decompress_ptr cinfo, |
| JSAMPIMAGE input_buf, JDIMENSION input_row, |
| JSAMPARRAY output_buf, int num_rows) |
| { |
| my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; |
| register INT32 * ctab = cconvert->rgb_y_tab; |
| register int r, g, b; |
| register JSAMPROW outptr; |
| register JSAMPROW inptr0, inptr1, inptr2; |
| register JDIMENSION col; |
| JDIMENSION num_cols = cinfo->output_width; |
| |
| while (--num_rows >= 0) { |
| inptr0 = input_buf[0][input_row]; |
| inptr1 = input_buf[1][input_row]; |
| inptr2 = input_buf[2][input_row]; |
| input_row++; |
| outptr = *output_buf++; |
| for (col = 0; col < num_cols; col++) { |
| r = GETJSAMPLE(inptr0[col]); |
| g = GETJSAMPLE(inptr1[col]); |
| b = GETJSAMPLE(inptr2[col]); |
| |
| outptr[col] = (JSAMPLE) |
| ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) |
| >> SCALEBITS); |
| } |
| } |
| } |
| |
| |
| |
| |
| |
| |
| |
| METHODDEF(void) |
| rgb1_rgb_convert (j_decompress_ptr cinfo, |
| JSAMPIMAGE input_buf, JDIMENSION input_row, |
| JSAMPARRAY output_buf, int num_rows) |
| { |
| register int r, g, b; |
| register JSAMPROW outptr; |
| register JSAMPROW inptr0, inptr1, inptr2; |
| register JDIMENSION col; |
| JDIMENSION num_cols = cinfo->output_width; |
| |
| while (--num_rows >= 0) { |
| inptr0 = input_buf[0][input_row]; |
| inptr1 = input_buf[1][input_row]; |
| inptr2 = input_buf[2][input_row]; |
| input_row++; |
| outptr = *output_buf++; |
| for (col = 0; col < num_cols; col++) { |
| r = GETJSAMPLE(inptr0[col]); |
| g = GETJSAMPLE(inptr1[col]); |
| b = GETJSAMPLE(inptr2[col]); |
| |
| |
| |
| outptr[RGB_RED] = (JSAMPLE) ((r + g - CENTERJSAMPLE) & MAXJSAMPLE); |
| outptr[RGB_GREEN] = (JSAMPLE) g; |
| outptr[RGB_BLUE] = (JSAMPLE) ((b + g - CENTERJSAMPLE) & MAXJSAMPLE); |
| outptr += RGB_PIXELSIZE; |
| } |
| } |
| } |
| |
| |
| |
| |
| |
| |
| |
| METHODDEF(void) |
| rgb1_gray_convert (j_decompress_ptr cinfo, |
| JSAMPIMAGE input_buf, JDIMENSION input_row, |
| JSAMPARRAY output_buf, int num_rows) |
| { |
| my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; |
| register INT32 * ctab = cconvert->rgb_y_tab; |
| register int r, g, b; |
| register JSAMPROW outptr; |
| register JSAMPROW inptr0, inptr1, inptr2; |
| register JDIMENSION col; |
| JDIMENSION num_cols = cinfo->output_width; |
| |
| while (--num_rows >= 0) { |
| inptr0 = input_buf[0][input_row]; |
| inptr1 = input_buf[1][input_row]; |
| inptr2 = input_buf[2][input_row]; |
| input_row++; |
| outptr = *output_buf++; |
| for (col = 0; col < num_cols; col++) { |
| r = GETJSAMPLE(inptr0[col]); |
| g = GETJSAMPLE(inptr1[col]); |
| b = GETJSAMPLE(inptr2[col]); |
| |
| |
| |
| r = (r + g - CENTERJSAMPLE) & MAXJSAMPLE; |
| b = (b + g - CENTERJSAMPLE) & MAXJSAMPLE; |
| |
| outptr[col] = (JSAMPLE) |
| ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) |
| >> SCALEBITS); |
| } |
| } |
| } |
| |
| |
| |
| |
| |
| |
| |
| METHODDEF(void) |
| rgb_convert (j_decompress_ptr cinfo, |
| JSAMPIMAGE input_buf, JDIMENSION input_row, |
| JSAMPARRAY output_buf, int num_rows) |
| { |
| register JSAMPROW outptr; |
| register JSAMPROW inptr0, inptr1, inptr2; |
| register JDIMENSION col; |
| JDIMENSION num_cols = cinfo->output_width; |
| |
| while (--num_rows >= 0) { |
| inptr0 = input_buf[0][input_row]; |
| inptr1 = input_buf[1][input_row]; |
| inptr2 = input_buf[2][input_row]; |
| input_row++; |
| outptr = *output_buf++; |
| for (col = 0; col < num_cols; col++) { |
| |
| outptr[RGB_RED] = inptr0[col]; |
| outptr[RGB_GREEN] = inptr1[col]; |
| outptr[RGB_BLUE] = inptr2[col]; |
| outptr += RGB_PIXELSIZE; |
| } |
| } |
| } |
| |
| |
| |
| |
| |
| |
| |
| METHODDEF(void) |
| null_convert (j_decompress_ptr cinfo, |
| JSAMPIMAGE input_buf, JDIMENSION input_row, |
| JSAMPARRAY output_buf, int num_rows) |
| { |
| int ci; |
| register int nc = cinfo->num_components; |
| register JSAMPROW outptr; |
| register JSAMPROW inptr; |
| register JDIMENSION col; |
| JDIMENSION num_cols = cinfo->output_width; |
| |
| while (--num_rows >= 0) { |
| for (ci = 0; ci < nc; ci++) { |
| inptr = input_buf[ci][input_row]; |
| outptr = output_buf[0] + ci; |
| for (col = 0; col < num_cols; col++) { |
| *outptr = *inptr++; |
| outptr += nc; |
| } |
| } |
| input_row++; |
| output_buf++; |
| } |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| METHODDEF(void) |
| grayscale_convert (j_decompress_ptr cinfo, |
| JSAMPIMAGE input_buf, JDIMENSION input_row, |
| JSAMPARRAY output_buf, int num_rows) |
| { |
| jcopy_sample_rows(input_buf[0], (int) input_row, output_buf, 0, |
| num_rows, cinfo->output_width); |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| METHODDEF(void) |
| gray_rgb_convert (j_decompress_ptr cinfo, |
| JSAMPIMAGE input_buf, JDIMENSION input_row, |
| JSAMPARRAY output_buf, int num_rows) |
| { |
| register JSAMPROW outptr; |
| register JSAMPROW inptr; |
| register JDIMENSION col; |
| JDIMENSION num_cols = cinfo->output_width; |
| |
| while (--num_rows >= 0) { |
| inptr = input_buf[0][input_row++]; |
| outptr = *output_buf++; |
| for (col = 0; col < num_cols; col++) { |
| |
| outptr[RGB_RED] = outptr[RGB_GREEN] = outptr[RGB_BLUE] = inptr[col]; |
| outptr += RGB_PIXELSIZE; |
| } |
| } |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| METHODDEF(void) |
| ycck_cmyk_convert (j_decompress_ptr cinfo, |
| JSAMPIMAGE input_buf, JDIMENSION input_row, |
| JSAMPARRAY output_buf, int num_rows) |
| { |
| my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; |
| register int y, cb, cr; |
| register JSAMPROW outptr; |
| register JSAMPROW inptr0, inptr1, inptr2, inptr3; |
| register JDIMENSION col; |
| JDIMENSION num_cols = cinfo->output_width; |
| |
| register JSAMPLE * range_limit = cinfo->sample_range_limit; |
| register int * Crrtab = cconvert->Cr_r_tab; |
| register int * Cbbtab = cconvert->Cb_b_tab; |
| register INT32 * Crgtab = cconvert->Cr_g_tab; |
| register INT32 * Cbgtab = cconvert->Cb_g_tab; |
| SHIFT_TEMPS |
| |
| while (--num_rows >= 0) { |
| inptr0 = input_buf[0][input_row]; |
| inptr1 = input_buf[1][input_row]; |
| inptr2 = input_buf[2][input_row]; |
| inptr3 = input_buf[3][input_row]; |
| input_row++; |
| outptr = *output_buf++; |
| for (col = 0; col < num_cols; col++) { |
| y = GETJSAMPLE(inptr0[col]); |
| cb = GETJSAMPLE(inptr1[col]); |
| cr = GETJSAMPLE(inptr2[col]); |
| |
| outptr[0] = range_limit[MAXJSAMPLE - (y + Crrtab[cr])]; |
| outptr[1] = range_limit[MAXJSAMPLE - (y + |
| ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], |
| SCALEBITS)))]; |
| outptr[2] = range_limit[MAXJSAMPLE - (y + Cbbtab[cb])]; |
| |
| outptr[3] = inptr3[col]; |
| outptr += 4; |
| } |
| } |
| } |
| |
| |
| |
| |
| |
| |
| METHODDEF(void) |
| start_pass_dcolor (j_decompress_ptr cinfo) |
| { |
| |
| } |
| |
| |
| |
| |
| |
| |
| GLOBAL(void) |
| jinit_color_deconverter (j_decompress_ptr cinfo) |
| { |
| my_cconvert_ptr cconvert; |
| int ci; |
| |
| cconvert = (my_cconvert_ptr) |
| (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, |
| SIZEOF(my_color_deconverter)); |
| cinfo->cconvert = &cconvert->pub; |
| cconvert->pub.start_pass = start_pass_dcolor; |
| |
| |
| switch (cinfo->jpeg_color_space) { |
| case JCS_GRAYSCALE: |
| if (cinfo->num_components != 1) |
| ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); |
| break; |
| |
| case JCS_RGB: |
| case JCS_YCbCr: |
| if (cinfo->num_components != 3) |
| ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); |
| break; |
| |
| case JCS_CMYK: |
| case JCS_YCCK: |
| if (cinfo->num_components != 4) |
| ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); |
| break; |
| |
| default: |
| if (cinfo->num_components < 1) |
| ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); |
| break; |
| } |
| |
| |
| if (cinfo->color_transform && cinfo->jpeg_color_space != JCS_RGB) |
| ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); |
| |
| |
| |
| |
| |
| |
| switch (cinfo->out_color_space) { |
| case JCS_GRAYSCALE: |
| cinfo->out_color_components = 1; |
| if (cinfo->jpeg_color_space == JCS_GRAYSCALE || |
| cinfo->jpeg_color_space == JCS_YCbCr) { |
| cconvert->pub.color_convert = grayscale_convert; |
| |
| for (ci = 1; ci < cinfo->num_components; ci++) |
| cinfo->comp_info[ci].component_needed = FALSE; |
| } else if (cinfo->jpeg_color_space == JCS_RGB) { |
| switch (cinfo->color_transform) { |
| case JCT_NONE: |
| cconvert->pub.color_convert = rgb_gray_convert; |
| break; |
| case JCT_SUBTRACT_GREEN: |
| cconvert->pub.color_convert = rgb1_gray_convert; |
| break; |
| default: |
| ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); |
| break; |
| } |
| build_rgb_y_table(cinfo); |
| } else |
| ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); |
| break; |
| |
| case JCS_RGB: |
| cinfo->out_color_components = RGB_PIXELSIZE; |
| if (cinfo->jpeg_color_space == JCS_YCbCr) { |
| cconvert->pub.color_convert = ycc_rgb_convert; |
| build_ycc_rgb_table(cinfo); |
| } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) { |
| cconvert->pub.color_convert = gray_rgb_convert; |
| } else if (cinfo->jpeg_color_space == JCS_RGB) { |
| switch (cinfo->color_transform) { |
| case JCT_NONE: |
| cconvert->pub.color_convert = rgb_convert; |
| break; |
| case JCT_SUBTRACT_GREEN: |
| cconvert->pub.color_convert = rgb1_rgb_convert; |
| break; |
| default: |
| ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); |
| break; |
| } |
| } else |
| ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); |
| break; |
| |
| case JCS_CMYK: |
| cinfo->out_color_components = 4; |
| if (cinfo->jpeg_color_space == JCS_YCCK) { |
| cconvert->pub.color_convert = ycck_cmyk_convert; |
| build_ycc_rgb_table(cinfo); |
| } else if (cinfo->jpeg_color_space == JCS_CMYK) { |
| cconvert->pub.color_convert = null_convert; |
| } else |
| ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); |
| break; |
| |
| default: |
| |
| if (cinfo->out_color_space == cinfo->jpeg_color_space) { |
| cinfo->out_color_components = cinfo->num_components; |
| cconvert->pub.color_convert = null_convert; |
| } else |
| ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); |
| break; |
| } |
| |
| if (cinfo->quantize_colors) |
| cinfo->output_components = 1; |
| else |
| cinfo->output_components = cinfo->out_color_components; |
| } |