1 /* Various functions relating to tone curve adjustment.
2  *
3  * Author: John Cupitt
4  * Written on: 18/7/1995
5  * 17/9/96 JC
6  *	- restrictions on Ps, Pm, Ph relaxed
7  *	- restrictions on S, M, H relaxed
8  * 25/7/01 JC
9  *	- patched for im_extract_band() change
10  * 11/7/04
11  *	- generalised to im_tone_build_range() ... so you can use it for any
12  *	  image, not just LabS
13  * 26/3/10
14  * 	- cleanups
15  * 	- gtkdoc
16  */
17 
18 /*
19 
20     This file is part of VIPS.
21 
22     VIPS is free software; you can redistribute it and/or modify
23     it under the terms of the GNU Lesser General Public License as published by
24     the Free Software Foundation; either version 2 of the License, or
25     (at your option) any later version.
26 
27     This program is distributed in the hope that it will be useful,
28     but WITHOUT ANY WARRANTY; without even the implied warranty of
29     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
30     GNU Lesser General Public License for more details.
31 
32     You should have received a copy of the GNU Lesser General Public License
33     along with this program; if not, write to the Free Software
34     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
35     02110-1301  USA
36 
37  */
38 
39 /*
40 
41     These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
42 
43  */
44 
45 #ifdef HAVE_CONFIG_H
46 #include <config.h>
47 #endif /*HAVE_CONFIG_H*/
48 #include <vips/intl.h>
49 
50 #include <stdio.h>
51 #include <stdlib.h>
52 #include <math.h>
53 
54 #include <vips/vips.h>
55 #include <vips/vips7compat.h>
56 
57 /**
58  * im_tone_map:
59  * @in: input image
60  * @out: output image
61  * @lut: look-up table
62  *
63  * Map the first channel of @in through @lut. If @in is IM_CODING_LABQ, unpack
64  * to LABS, map L and then repack.
65  *
66  * @in should be a LABS or LABQ image for this to work
67  * sensibly.
68  *
69  * See also: im_maplut().
70  *
71  * Returns: 0 on success, -1 on error
72  */
73 int
im_tone_map(IMAGE * in,IMAGE * out,IMAGE * lut)74 im_tone_map( IMAGE *in, IMAGE *out, IMAGE *lut )
75 {
76 	IMAGE *t[8];
77 
78 	if( im_check_hist( "im_tone_map", lut ) ||
79 		im_open_local_array( out, t, 8, "im_tone_map", "p" ) )
80 		return( -1 );
81 
82 	/* If in is IM_CODING_LABQ, unpack.
83 	 */
84 	if( in->Coding == IM_CODING_LABQ ) {
85 		if( im_LabQ2LabS( in, t[0] ) )
86 			return( -1 );
87 	}
88 	else
89 		t[0] = in;
90 
91 	/* Split into bands.
92 	 */
93 	if( im_extract_band( t[0], t[1], 0 ) )
94 		return( -1 );
95 	if( t[0]->Bands > 1 ) {
96 		if( im_extract_bands( t[0], t[2], 1, t[0]->Bands - 1 ) )
97 			return( -1 );
98 	}
99 
100 	/* Map L.
101 	 */
102 	if( im_maplut( t[1], t[3], lut ) )
103 		return( -1 );
104 
105 	/* Recombine bands.
106 	 */
107 	if( t[0]->Bands > 1 ) {
108 		if( im_bandjoin( t[3], t[2], t[4] ) )
109 			return( -1 );
110 	}
111 	else
112 		t[4] = t[3];
113 
114 	/* If input was LabQ, repack.
115 	 */
116 	if( in->Coding == IM_CODING_LABQ ) {
117 		if( im_LabS2LabQ( t[4], t[5] ) )
118 			return( -1 );
119 	}
120 	else
121 		t[5] = t[4];
122 
123 	return( im_copy( t[4], out ) );
124 }
125 
126 /**
127  * im_tone_analyse:
128  * @in: input image
129  * @out: output image
130  * @Ps: shadow point (eg. 0.2)
131  * @Pm: mid-tone point (eg. 0.5)
132  * @Ph: highlight point (eg. 0.8)
133  * @S: shadow adjustment (+/- 30)
134  * @M: mid-tone adjustment (+/- 30)
135  * @H: highlight adjustment (+/- 30)
136  *
137  * As im_tone_build(), but analyse the histogram of @in and use it to
138  * pick the 0.1% and 99.9% points for @Lb and @Lw.
139  *
140  * See also: im_tone_build().
141  *
142  * Returns: 0 on success, -1 on error
143  */
144 int
im_tone_analyse(IMAGE * in,IMAGE * out,double Ps,double Pm,double Ph,double S,double M,double H)145 im_tone_analyse(
146 	IMAGE *in,
147 	IMAGE *out,
148 	double Ps, double Pm, double Ph,
149 	double S, double M, double H )
150 {
151 	IMAGE *t[4];
152 	int low, high;
153 	double Lb, Lw;
154 
155 	if( im_open_local_array( out, t, 4, "im_tone_map", "p" ) )
156 		return( -1 );
157 
158 	/* If in is IM_CODING_LABQ, unpack.
159 	 */
160 	if( in->Coding == IM_CODING_LABQ ) {
161 		if( im_LabQ2LabS( in, t[0] ) )
162 			return( -1 );
163 	}
164 	else
165 		t[0] = in;
166 
167 	/* Should now be 3-band short.
168 	 */
169 	if( im_check_uncoded( "im_tone_analyse", t[0] ) ||
170 		im_check_bands( "im_tone_analyse", t[0], 3 ) ||
171 		im_check_format( "im_tone_analyse", t[0], IM_BANDFMT_SHORT ) )
172 		return( -1 );
173 
174 	if( im_extract_band( t[0], t[1], 0 ) ||
175 		im_clip2fmt( t[1], t[2], IM_BANDFMT_USHORT ) )
176 		return( -1 );
177 
178 	if( im_mpercent( t[2], 0.1 / 100.0, &high ) ||
179 		im_mpercent( t[2], 99.9 / 100.0, &low ) )
180 		return( -1 );
181 
182 	Lb = 100 * low / 32768;
183 	Lw = 100 * high / 32768;
184 
185 	im_diag( "im_tone_analyse", "set Lb = %g, Lw = %g", Lb, Lw );
186 
187 	return( im_tone_build( out, Lb, Lw, Ps, Pm, Ph, S, M, H ) );
188 }
189