1 /*
2  * jdscale.c
3  *
4  * Copyright (C) 1998, Thomas G. Lane.
5  * This file is part of the Independent JPEG Group's software.
6  * For conditions of distribution and use, see the accompanying README file.
7  *
8  * This file contains sample scaling for lossless JPEG.  This is a
9  * combination of upscaling the undifferenced sample by 2^Pt and downscaling
10  * the sample to fit into JSAMPLE.
11  */
12 
13 #define JPEG_INTERNALS
14 #include "jinclude16.h"
15 #include "jpeglib16.h"
16 #include "jlossls16.h"		/* Private declarations for lossless codec */
17 
18 
19 #ifdef D_LOSSLESS_SUPPORTED
20 
21 /*
22  * Private scaler object for lossless decoding.
23  */
24 
25 typedef struct {
26   int scale_factor;
27 } scaler;
28 
29 typedef scaler * scaler_ptr;
30 
31 
32 /*
33  * Scalers for packing sample differences into JSAMPLEs.
34  */
35 
36 METHODDEF(void)
simple_upscale(j_decompress_ptr cinfo,const JDIFFROW diff_buf,JSAMPROW output_buf,JDIMENSION width)37 simple_upscale(j_decompress_ptr cinfo,
38 	       const JDIFFROW diff_buf, JSAMPROW output_buf,
39 	       JDIMENSION width)
40 {
41   j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
42   scaler_ptr scale = (scaler_ptr) losslsd->scaler_private;
43   int scale_factor = scale->scale_factor;
44   unsigned int xindex;
45 
46   for (xindex = 0; xindex < width; xindex++)
47     output_buf[xindex] = (JSAMPLE) (diff_buf[xindex] << scale_factor);
48 }
49 
50 METHODDEF(void)
simple_downscale(j_decompress_ptr cinfo,const JDIFFROW diff_buf,JSAMPROW output_buf,JDIMENSION width)51 simple_downscale(j_decompress_ptr cinfo,
52 		 const JDIFFROW diff_buf, JSAMPROW output_buf,
53 		 JDIMENSION width)
54 {
55   j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
56   scaler_ptr scale = (scaler_ptr) losslsd->scaler_private;
57   int scale_factor = scale->scale_factor;
58   unsigned int xindex;
59   SHIFT_TEMPS
60 
61   for (xindex = 0; xindex < width; xindex++)
62     output_buf[xindex] = (JSAMPLE) RIGHT_SHIFT(diff_buf[xindex], scale_factor);
63 }
64 
65 METHODDEF(void)
noscale(j_decompress_ptr cinfo,const JDIFFROW diff_buf,JSAMPROW output_buf,JDIMENSION width)66 noscale(j_decompress_ptr cinfo,
67 	const JDIFFROW diff_buf, JSAMPROW output_buf,
68 	JDIMENSION width)
69 {
70   unsigned int xindex;
71 
72   for (xindex = 0; xindex < width; xindex++)
73     output_buf[xindex] = (JSAMPLE) diff_buf[xindex];
74 }
75 
76 
77 METHODDEF(void)
scaler_start_pass(j_decompress_ptr cinfo)78 scaler_start_pass (j_decompress_ptr cinfo)
79 {
80   j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
81   scaler_ptr scale = (scaler_ptr) losslsd->scaler_private;
82   int downscale;
83 
84   /*
85    * Downscale by the difference in the input vs. output precision.  If the
86    * output precision >= input precision, then do not downscale.
87    */
88   downscale = BITS_IN_JSAMPLE < cinfo->data_precision ?
89     cinfo->data_precision - BITS_IN_JSAMPLE : 0;
90 
91   scale->scale_factor = cinfo->Al - downscale;
92 
93   /* Set scaler functions based on scale_factor (positive = left shift) */
94   if (scale->scale_factor > 0)
95     losslsd->scaler_scale = simple_upscale;
96   else if (scale->scale_factor < 0) {
97     scale->scale_factor = -scale->scale_factor;
98     losslsd->scaler_scale = simple_downscale;
99   }
100   else
101     losslsd->scaler_scale = noscale;
102 }
103 
104 
105 GLOBAL(void)
jinit_d_scaler(j_decompress_ptr cinfo)106 jinit_d_scaler (j_decompress_ptr cinfo)
107 {
108   j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
109   scaler_ptr scale;
110 
111   scale = (scaler_ptr)
112     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
113 				SIZEOF(scaler));
114   losslsd->scaler_private = (void *) scale;
115   losslsd->scaler_start_pass = scaler_start_pass;
116 }
117 
118 #endif /* D_LOSSLESS_SUPPORTED */
119 
120