6 Copyright (C) 2015, 2022 Balthasar SzczepaĆski
8 This program is free software: you can redistribute it and/or modify
9 it under the terms of the GNU Affero General Public License as
10 published by the Free Software Foundation, either version 3 of the
11 License, or (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU Affero General Public License for more details.
18 You should have received a copy of the GNU Affero General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 Requires Dev Image Library (libdevil) (http://openil.sourceforge.net/)
23 on Pentium III libdevil must be recompiled with
24 --disable-ssl2 --disable-ssl3
25 (https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=572954)
35 char BLUENH_MISSING_ARGS[] = "Missing parameters.\nbluenh inPix outPix a b c d e f\n";
54 int bluenhance (ILuint n, struct PixelInfo *p, void *data);
55 void calculate_bluenh_parameters (struct bluenh_data *data);
56 static inline ILuint bluenh_linear (ILuint x, ILint64 r, ILint64 s, ILint64 t, ILuint max);
57 static inline ILuint bluenh_top (ILuint x, struct bluenh_data *data);
58 static inline ILuint bluenh_mid (ILuint x, ILuint low, ILuint high_old, ILuint high_new, ILuint max);
61 int subtool_bluenh (int argc, char **argv, int argi, char **err)
64 struct bluenh_data data;
65 struct IL_full_info info;
66 FLAG_TYPE flags = CAN_BE_MULTIPLE | CAN_BE_OVER_8BIT | OK_PALETTE_ONLY;
71 *err = BLUENH_MISSING_ARGS;
75 r = reserve_pictures(1);
82 r = load_picture(0, argv[argi], &info, &flags);
89 if (!(flags & IS_GRAY))
91 sscanf(argv[argi+2],"%hhu",&v);
92 data.a = upscale_value(v, info.image_bpc);
93 sscanf(argv[argi+3],"%hhu",&v);
94 data.b = upscale_value(v, info.image_bpc);
95 sscanf(argv[argi+4],"%hhu",&v);
96 data.c = upscale_value(v, info.image_bpc);
97 sscanf(argv[argi+5],"%hhu",&v);
98 data.d = upscale_value(v, info.image_bpc);
99 sscanf(argv[argi+6],"%hhu",&v);
100 data.e = upscale_value(v, info.image_bpc);
101 sscanf(argv[argi+7],"%hhu",&v);
102 data.f = upscale_value(v, info.image_bpc);
103 data.max = upscale_value(0xFF, info.image_bpc);
104 calculate_bluenh_parameters (&data);
106 r = perform_action_1picture (
115 *err = CONVERT_FAILED;
120 r = save_picture (0, argv[argi+1], flags);
130 int bluenhance (ILuint n, struct PixelInfo *p, void *data)
132 struct bluenh_data *d;
133 ILuint *high, *mid, *low;
136 /* known to be RGB at this point*/
140 if ((p->red == p->green) && (p->green == p->blue))
141 return 0; /* nothing to do here */
143 if(p->red > p->green)
145 if(p->green > p->blue)
151 else if(p->blue > p->red)
172 else if(p->blue > p->green)
186 *high = bluenh_top(*high, d);
187 *mid = bluenh_mid(*mid, *low, high_old, *high, d->max);
192 void calculate_bluenh_parameters (struct bluenh_data *data)
194 data->r_high = (ILint64)(data->f) - (ILint64)(data->e);
195 data->s_high = (ILint64)(data->c) - (ILint64)(data->b);
196 data->t_high =((ILint64)(data->e))*((ILint64)(data->c))-((ILint64)(data->b))*((ILint64)(data->f));
197 data->r_low = (ILint64)(data->e) - (ILint64)(data->d);
198 data->s_low = (ILint64)(data->b) - (ILint64)(data->a);
199 data->t_low =((ILint64)(data->d))*((ILint64)(data->b))-((ILint64)(data->a))*((ILint64)(data->e));
202 static inline ILuint bluenh_linear (ILuint x, ILint64 r, ILint64 s, ILint64 t, ILuint max)
204 ILint64 y = (r*x + t)/s;
205 return (ILuint)((y>max)?max:((y<0)?0:y));
208 static inline ILuint bluenh_top (ILuint x, struct bluenh_data *data)
212 else if (x >= data->c)
214 else if (x > data->b)
215 return bluenh_linear(x, data->r_high, data->s_high, data->t_high, data->max);
216 else if (x < data->b)
217 return bluenh_linear(x, data->r_low, data->s_low, data->t_low, data->max);
222 static inline ILuint bluenh_mid (ILuint x, ILuint low, ILuint high_old, ILuint high_new, ILuint max)
224 return bluenh_linear(
226 ((ILuint64)high_new) - ((ILuint64)low),
227 ((ILuint64)high_old) - ((ILuint64)low),
228 (((ILuint64)high_old) - ((ILuint64)high_new)) * ((ILuint64)low),