]> bicyclesonthemoon.info Git - ott/enhance/blob - bluenh.c
makefile cleanup and safety (don't rm -rf)
[ott/enhance] / bluenh.c
1 /*
2 bluenh.c
3 ENHANCE the bluepix!
4 28.11.2022
5
6 Copyright (C) 2015, 2022  Balthasar SzczepaƄski
7
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.
12
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.
17
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/>.
20
21
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)
26
27 */
28
29 #include <stdio.h>
30 #include <errno.h>
31
32 #include "bluenh.h"
33 #include "core.h"
34
35 char BLUENH_MISSING_ARGS[] = "Missing parameters.\nbluenh inPix outPix a b c d e f\n";
36
37 struct bluenh_data
38 {
39         ILuint a;
40         ILuint b;
41         ILuint c;
42         ILuint d;
43         ILuint e;
44         ILuint f;
45         ILint64 r_high;
46         ILint64 s_high;
47         ILint64 t_high;
48         ILint64 r_low;
49         ILint64 s_low;
50         ILint64 t_low;
51         ILuint max;
52 };
53
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);
59
60
61 int subtool_bluenh (int argc, char **argv, int argi, char **err)
62 {
63         ILubyte v;
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;
67         int r;
68         
69         if (argc < argi + 8)
70         {
71                 *err = BLUENH_MISSING_ARGS;
72                 return EINVAL;
73         }
74         
75         r = reserve_pictures(1);
76         if (r)
77         {
78                 *err = CREATE_FAILED;
79                 return r;
80         }
81         
82         r = load_picture(0, argv[argi], &info, &flags);
83         if (r)
84         {
85                 *err = LOAD_FAILED;
86                 return r;
87         }
88         
89         if (!(flags & IS_GRAY))
90         {
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);
105                 
106                 r = perform_action_1picture (
107                         0,
108                         0, 0, 0, 0, 0, 0,
109                         &bluenhance,
110                         flags,
111                         &data
112                 );
113                 if (r)
114                 {
115                         *err = CONVERT_FAILED;
116                         return r;
117                 }
118         }
119         
120         r = save_picture (0, argv[argi+1], flags);
121         if (r)
122         {
123                 *err = SAVE_FAILED;
124                 return r;
125         }
126         
127         return 0;
128 }
129
130 int bluenhance (ILuint n, struct PixelInfo *p, void *data)
131 {
132         struct bluenh_data *d;
133         ILuint *high, *mid, *low;
134         ILuint high_old;
135         
136         /* known to be RGB at this point*/
137         
138         d = data;
139         
140         if ((p->red == p->green) && (p->green == p->blue))
141                 return 0; /* nothing to do here */
142         
143         if(p->red > p->green)
144         {
145                 if(p->green > p->blue)
146                 {
147                         high= &(p->red);
148                         mid = &(p->green);
149                         low = &(p->blue);
150                 }
151                 else if(p->blue > p->red)
152                 {
153                         high= &(p->blue);
154                         mid = &(p->red);
155                         low = &(p->green);
156                 }
157                 else
158                 {
159                         high = &(p->red);
160                         mid  = &(p->blue);
161                         low  = &(p->green);
162                 }
163         }
164         else
165         {
166                 if(p->red > p->blue)
167                 {
168                         high= &(p->green);
169                         mid = &(p->red);
170                         low = &(p->blue);
171                 }
172                 else if(p->blue > p->green)
173                 {
174                         high= &(p->blue);
175                         mid = &(p->green);
176                         low = &(p->red);
177                 }
178                 else
179                 {
180                         high= &(p->green);
181                         mid = &(p->blue);
182                         low = &(p->red);
183                 }
184         }
185         high_old = *high;
186         *high = bluenh_top(*high, d);
187         *mid  = bluenh_mid(*mid, *low, high_old, *high, d->max);
188         
189         return 0;
190 }
191
192 void calculate_bluenh_parameters (struct bluenh_data *data)
193 {
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));
200 }
201
202 static inline ILuint bluenh_linear (ILuint x, ILint64 r, ILint64 s, ILint64 t, ILuint max)
203 {
204         ILint64 y = (r*x + t)/s;
205         return (ILuint)((y>max)?max:((y<0)?0:y));
206 }
207
208 static inline ILuint bluenh_top (ILuint x, struct bluenh_data *data)
209 {
210                 if (x <= data->a)
211                         return data->d;
212                 else if (x >= data->c)
213                         return data->f;
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);
218                 else
219                         return data->e;
220 }
221
222 static inline ILuint bluenh_mid (ILuint x, ILuint low, ILuint high_old, ILuint high_new, ILuint max)
223 {
224         return bluenh_linear(
225                 x,
226                 ((ILuint64)high_new) - ((ILuint64)low),
227                 ((ILuint64)high_old) - ((ILuint64)low),
228                 (((ILuint64)high_old) - ((ILuint64)high_new)) * ((ILuint64)low),
229                 max
230         );
231 }