1793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* 2793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * jdmerge.c 3793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * 4793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * Copyright (C) 1994-1996, Thomas G. Lane. 5793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * This file is part of the Independent JPEG Group's software. 6793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * For conditions of distribution and use, see the accompanying README file. 7793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * 8793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * This file contains code for merged upsampling/color conversion. 9793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * 10793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * This file combines functions from jdsample.c and jdcolor.c; 11793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * read those files first to understand what's going on. 12793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * 13793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * When the chroma components are to be upsampled by simple replication 14793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * (ie, box filtering), we can save some work in color conversion by 15793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * calculating all the output pixels corresponding to a pair of chroma 16793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * samples at one time. In the conversion equations 17793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * R = Y + K1 * Cr 18793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * G = Y + K2 * Cb + K3 * Cr 19793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * B = Y + K4 * Cb 20793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * only the Y term varies among the group of pixels corresponding to a pair 21793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * of chroma samples, so the rest of the terms can be calculated just once. 22793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * At typical sampling ratios, this eliminates half or three-quarters of the 23793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * multiplications needed for color conversion. 24793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * 25793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * This file currently provides implementations for the following cases: 26793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * YCbCr => RGB color conversion only. 27793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * Sampling ratios of 2h1v or 2h2v. 28793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * No scaling needed at upsample time. 29793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * Corner-aligned (non-CCIR601) sampling alignment. 30793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * Other special cases could be added, but in most applications these are 31793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * the only common cases. (For uncommon cases we fall back on the more 32793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * general code in jdsample.c and jdcolor.c.) 33793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */ 34793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 35793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define JPEG_INTERNALS 36793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include "jinclude.h" 37793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include "jpeglib.h" 38793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 39793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#ifdef UPSAMPLE_MERGING_SUPPORTED 40793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 41793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 42793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* Private subobject */ 43793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 44793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslertypedef struct { 45793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler struct jpeg_upsampler pub; /* public fields */ 46793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 47793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* Pointer to routine to do actual upsampling/conversion of one row group */ 48793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler JMETHOD(void, upmethod, (j_decompress_ptr cinfo, 49793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, 50793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler JSAMPARRAY output_buf)); 51793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 52793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* Private state for YCC->RGB conversion */ 53793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int * Cr_r_tab; /* => table for Cr to R conversion */ 54793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int * Cb_b_tab; /* => table for Cb to B conversion */ 55793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler INT32 * Cr_g_tab; /* => table for Cr to G conversion */ 56793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler INT32 * Cb_g_tab; /* => table for Cb to G conversion */ 57793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 58793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* For 2:1 vertical sampling, we produce two output rows at a time. 59793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * We need a "spare" row buffer to hold the second output row if the 60793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * application provides just a one-row buffer; we also use the spare 61793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * to discard the dummy last row if the image height is odd. 62793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */ 63793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler JSAMPROW spare_row; 64793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler boolean spare_full; /* T if spare buffer is occupied */ 65793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 66793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler JDIMENSION out_row_width; /* samples per output row */ 67793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler JDIMENSION rows_to_go; /* counts rows remaining in image */ 68793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} my_upsampler; 69793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 70793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslertypedef my_upsampler * my_upsample_ptr; 71793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 72793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define SCALEBITS 16 /* speediest right-shift on some machines */ 73793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define ONE_HALF ((INT32) 1 << (SCALEBITS-1)) 74793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define FIX(x) ((INT32) ((x) * (1L<<SCALEBITS) + 0.5)) 75793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 76793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 77793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* 78793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * Initialize tables for YCC->RGB colorspace conversion. 79793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * This is taken directly from jdcolor.c; see that file for more info. 80793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */ 81793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 82793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerLOCAL(void) 83793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerbuild_ycc_rgb_table (j_decompress_ptr cinfo) 84793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 85793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; 86793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int i; 87793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler INT32 x; 88793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler SHIFT_TEMPS 89793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 90793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler upsample->Cr_r_tab = (int *) 91793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 92793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (MAXJSAMPLE+1) * SIZEOF(int)); 93793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler upsample->Cb_b_tab = (int *) 94793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 95793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (MAXJSAMPLE+1) * SIZEOF(int)); 96793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler upsample->Cr_g_tab = (INT32 *) 97793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 98793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (MAXJSAMPLE+1) * SIZEOF(INT32)); 99793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler upsample->Cb_g_tab = (INT32 *) 100793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 101793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (MAXJSAMPLE+1) * SIZEOF(INT32)); 102793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 103793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { 104793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ 105793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ 106793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* Cr=>R value is nearest int to 1.40200 * x */ 107793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler upsample->Cr_r_tab[i] = (int) 108793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS); 109793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* Cb=>B value is nearest int to 1.77200 * x */ 110793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler upsample->Cb_b_tab[i] = (int) 111793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS); 112793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* Cr=>G value is scaled-up -0.71414 * x */ 113793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler upsample->Cr_g_tab[i] = (- FIX(0.71414)) * x; 114793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* Cb=>G value is scaled-up -0.34414 * x */ 115793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* We also add in ONE_HALF so that need not do it in inner loop */ 116793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler upsample->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF; 117793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 118793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 119793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 120793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 121793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* 122793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * Initialize for an upsampling pass. 123793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */ 124793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 125793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerMETHODDEF(void) 126793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstart_pass_merged_upsample (j_decompress_ptr cinfo) 127793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 128793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; 129793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 130793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* Mark the spare buffer empty */ 131793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler upsample->spare_full = FALSE; 132793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* Initialize total-height counter for detecting bottom of image */ 133793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler upsample->rows_to_go = cinfo->output_height; 134793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 135793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 136793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 137793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* 138793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * Control routine to do upsampling (and color conversion). 139793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * 140793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * The control routine just handles the row buffering considerations. 141793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */ 142793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 143793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerMETHODDEF(void) 144793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslermerged_2v_upsample (j_decompress_ptr cinfo, 145793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, 146793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler JDIMENSION in_row_groups_avail, 147793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, 148793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler JDIMENSION out_rows_avail) 149793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* 2:1 vertical sampling case: may need a spare row. */ 150793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 151793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; 152793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler JSAMPROW work_ptrs[2]; 153793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler JDIMENSION num_rows; /* number of rows returned to caller */ 154793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 155793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if (upsample->spare_full) { 156793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* If we have a spare row saved from a previous cycle, just return it. */ 157793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler jcopy_sample_rows(& upsample->spare_row, 0, output_buf + *out_row_ctr, 0, 158793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1, upsample->out_row_width); 159793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler num_rows = 1; 160793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler upsample->spare_full = FALSE; 161793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } else { 162793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* Figure number of rows to return to caller. */ 163793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler num_rows = 2; 164793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* Not more than the distance to the end of the image. */ 165793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if (num_rows > upsample->rows_to_go) 166793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler num_rows = upsample->rows_to_go; 167793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* And not more than what the client can accept: */ 168793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler out_rows_avail -= *out_row_ctr; 169793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if (num_rows > out_rows_avail) 170793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler num_rows = out_rows_avail; 171793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* Create output pointer array for upsampler. */ 172793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler work_ptrs[0] = output_buf[*out_row_ctr]; 173793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if (num_rows > 1) { 174793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler work_ptrs[1] = output_buf[*out_row_ctr + 1]; 175793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } else { 176793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler work_ptrs[1] = upsample->spare_row; 177793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler upsample->spare_full = TRUE; 178793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 179793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* Now do the upsampling. */ 180793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr, work_ptrs); 181793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 182793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 183793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* Adjust counts */ 184793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler *out_row_ctr += num_rows; 185793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler upsample->rows_to_go -= num_rows; 186793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* When the buffer is emptied, declare this input row group consumed */ 187793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if (! upsample->spare_full) 188793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (*in_row_group_ctr)++; 189793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 190793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 191793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 192793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerMETHODDEF(void) 193793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslermerged_1v_upsample (j_decompress_ptr cinfo, 194793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, 195793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler JDIMENSION in_row_groups_avail, 196793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, 197793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler JDIMENSION out_rows_avail) 198793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* 1:1 vertical sampling case: much easier, never need a spare row. */ 199793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 200793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; 201793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 202793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* Just do the upsampling. */ 203793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr, 204793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler output_buf + *out_row_ctr); 205793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* Adjust counts */ 206793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (*out_row_ctr)++; 207793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (*in_row_group_ctr)++; 208793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 209793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 210793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 211793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* 212793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * These are the routines invoked by the control routines to do 213793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * the actual upsampling/conversion. One row group is processed per call. 214793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * 215793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * Note: since we may be writing directly into application-supplied buffers, 216793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * we have to be honest about the output width; we can't assume the buffer 217793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * has been rounded up to an even width. 218793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */ 219793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 220793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 221793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* 222793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * Upsample and color convert for the case of 2:1 horizontal and 1:1 vertical. 223793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */ 224793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 225793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerMETHODDEF(void) 226793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerh2v1_merged_upsample (j_decompress_ptr cinfo, 227793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, 228793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler JSAMPARRAY output_buf) 229793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 230793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; 231793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler register int y, cred, cgreen, cblue; 232793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int cb, cr; 233793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler register JSAMPROW outptr; 234793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler JSAMPROW inptr0, inptr1, inptr2; 235793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler JDIMENSION col; 236793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* copy these pointers into registers if possible */ 237793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler register JSAMPLE * range_limit = cinfo->sample_range_limit; 238793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int * Crrtab = upsample->Cr_r_tab; 239793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int * Cbbtab = upsample->Cb_b_tab; 240793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler INT32 * Crgtab = upsample->Cr_g_tab; 241793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler INT32 * Cbgtab = upsample->Cb_g_tab; 242793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler SHIFT_TEMPS 243793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 244793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler inptr0 = input_buf[0][in_row_group_ctr]; 245793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler inptr1 = input_buf[1][in_row_group_ctr]; 246793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler inptr2 = input_buf[2][in_row_group_ctr]; 247793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr = output_buf[0]; 248793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* Loop for each pair of output pixels */ 249793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for (col = cinfo->output_width >> 1; col > 0; col--) { 250793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* Do the chroma part of the calculation */ 251793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cb = GETJSAMPLE(*inptr1++); 252793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cr = GETJSAMPLE(*inptr2++); 253793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cred = Crrtab[cr]; 254793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); 255793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cblue = Cbbtab[cb]; 256793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* Fetch 2 Y values and emit 2 pixels */ 257793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler y = GETJSAMPLE(*inptr0++); 258793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr[RGB_RED] = range_limit[y + cred]; 259793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr[RGB_GREEN] = range_limit[y + cgreen]; 260793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr[RGB_BLUE] = range_limit[y + cblue]; 261793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr += RGB_PIXELSIZE; 262793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler y = GETJSAMPLE(*inptr0++); 263793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr[RGB_RED] = range_limit[y + cred]; 264793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr[RGB_GREEN] = range_limit[y + cgreen]; 265793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr[RGB_BLUE] = range_limit[y + cblue]; 266793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr += RGB_PIXELSIZE; 267793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 268793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* If image width is odd, do the last output column separately */ 269793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if (cinfo->output_width & 1) { 270793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cb = GETJSAMPLE(*inptr1); 271793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cr = GETJSAMPLE(*inptr2); 272793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cred = Crrtab[cr]; 273793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); 274793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cblue = Cbbtab[cb]; 275793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler y = GETJSAMPLE(*inptr0); 276793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr[RGB_RED] = range_limit[y + cred]; 277793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr[RGB_GREEN] = range_limit[y + cgreen]; 278793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr[RGB_BLUE] = range_limit[y + cblue]; 279793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 280793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 281793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 282793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 283793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* 284793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * Upsample and color convert for the case of 2:1 horizontal and 2:1 vertical. 285793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */ 286793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 287793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerMETHODDEF(void) 288793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerh2v2_merged_upsample (j_decompress_ptr cinfo, 289793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, 290793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler JSAMPARRAY output_buf) 291793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 292793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; 293793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler register int y, cred, cgreen, cblue; 294793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int cb, cr; 295793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler register JSAMPROW outptr0, outptr1; 296793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler JSAMPROW inptr00, inptr01, inptr1, inptr2; 297793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler JDIMENSION col; 298793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* copy these pointers into registers if possible */ 299793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler register JSAMPLE * range_limit = cinfo->sample_range_limit; 300793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int * Crrtab = upsample->Cr_r_tab; 301793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int * Cbbtab = upsample->Cb_b_tab; 302793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler INT32 * Crgtab = upsample->Cr_g_tab; 303793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler INT32 * Cbgtab = upsample->Cb_g_tab; 304793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler SHIFT_TEMPS 305793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 306793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler inptr00 = input_buf[0][in_row_group_ctr*2]; 307793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler inptr01 = input_buf[0][in_row_group_ctr*2 + 1]; 308793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler inptr1 = input_buf[1][in_row_group_ctr]; 309793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler inptr2 = input_buf[2][in_row_group_ctr]; 310793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr0 = output_buf[0]; 311793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr1 = output_buf[1]; 312793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* Loop for each group of output pixels */ 313793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for (col = cinfo->output_width >> 1; col > 0; col--) { 314793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* Do the chroma part of the calculation */ 315793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cb = GETJSAMPLE(*inptr1++); 316793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cr = GETJSAMPLE(*inptr2++); 317793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cred = Crrtab[cr]; 318793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); 319793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cblue = Cbbtab[cb]; 320793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* Fetch 4 Y values and emit 4 pixels */ 321793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler y = GETJSAMPLE(*inptr00++); 322793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr0[RGB_RED] = range_limit[y + cred]; 323793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr0[RGB_GREEN] = range_limit[y + cgreen]; 324793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr0[RGB_BLUE] = range_limit[y + cblue]; 325793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr0 += RGB_PIXELSIZE; 326793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler y = GETJSAMPLE(*inptr00++); 327793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr0[RGB_RED] = range_limit[y + cred]; 328793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr0[RGB_GREEN] = range_limit[y + cgreen]; 329793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr0[RGB_BLUE] = range_limit[y + cblue]; 330793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr0 += RGB_PIXELSIZE; 331793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler y = GETJSAMPLE(*inptr01++); 332793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr1[RGB_RED] = range_limit[y + cred]; 333793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr1[RGB_GREEN] = range_limit[y + cgreen]; 334793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr1[RGB_BLUE] = range_limit[y + cblue]; 335793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr1 += RGB_PIXELSIZE; 336793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler y = GETJSAMPLE(*inptr01++); 337793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr1[RGB_RED] = range_limit[y + cred]; 338793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr1[RGB_GREEN] = range_limit[y + cgreen]; 339793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr1[RGB_BLUE] = range_limit[y + cblue]; 340793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr1 += RGB_PIXELSIZE; 341793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 342793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* If image width is odd, do the last output column separately */ 343793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if (cinfo->output_width & 1) { 344793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cb = GETJSAMPLE(*inptr1); 345793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cr = GETJSAMPLE(*inptr2); 346793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cred = Crrtab[cr]; 347793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); 348793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cblue = Cbbtab[cb]; 349793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler y = GETJSAMPLE(*inptr00); 350793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr0[RGB_RED] = range_limit[y + cred]; 351793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr0[RGB_GREEN] = range_limit[y + cgreen]; 352793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr0[RGB_BLUE] = range_limit[y + cblue]; 353793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler y = GETJSAMPLE(*inptr01); 354793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr1[RGB_RED] = range_limit[y + cred]; 355793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr1[RGB_GREEN] = range_limit[y + cgreen]; 356793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr1[RGB_BLUE] = range_limit[y + cblue]; 357793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 358793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 359793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 360793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 361793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* 362793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * Module initialization routine for merged upsampling/color conversion. 363793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * 364793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * NB: this is called under the conditions determined by use_merged_upsample() 365793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * in jdmaster.c. That routine MUST correspond to the actual capabilities 366793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * of this module; no safety checks are made here. 367793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */ 368793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 369793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerGLOBAL(void) 370793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerjinit_merged_upsampler (j_decompress_ptr cinfo) 371793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 372793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler my_upsample_ptr upsample; 373793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 374793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler upsample = (my_upsample_ptr) 375793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 376793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler SIZEOF(my_upsampler)); 377793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cinfo->upsample = (struct jpeg_upsampler *) upsample; 378793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler upsample->pub.start_pass = start_pass_merged_upsample; 379793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler upsample->pub.need_context_rows = FALSE; 380793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 381793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler upsample->out_row_width = cinfo->output_width * cinfo->out_color_components; 382793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 383793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if (cinfo->max_v_samp_factor == 2) { 384793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler upsample->pub.upsample = merged_2v_upsample; 385793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler upsample->upmethod = h2v2_merged_upsample; 386793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* Allocate a spare row buffer */ 387793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler upsample->spare_row = (JSAMPROW) 388793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, 389793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (size_t) (upsample->out_row_width * SIZEOF(JSAMPLE))); 390793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } else { 391793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler upsample->pub.upsample = merged_1v_upsample; 392793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler upsample->upmethod = h2v1_merged_upsample; 393793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* No spare row needed */ 394793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler upsample->spare_row = NULL; 395793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 396793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 397793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler build_ycc_rgb_table(cinfo); 398793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 399793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 400793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif /* UPSAMPLE_MERGING_SUPPORTED */ 401