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