]> bicyclesonthemoon.info Git - ott/enhance/blob - pal_mix.c
reveal online
[ott/enhance] / pal_mix.c
1 /*
2 pal_mix.c
3 The tool to hide two indexed images iside one
4 01.12.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 <stdint.h>
30 #include <getopt.h>
31 #include <errno.h>
32
33 #include "core.h"
34 #include "pal_mix.h"
35
36 struct rel_data
37 {
38         ILuint p0;
39         ILuint p1;
40         ILuint p;
41 };
42
43 int palette_mix_value (ILuint n, struct PixelInfo *p, void *data);
44 ILuint mix_value_1ch (ILint64 x, ILint64 y, struct rel_data *rel);
45
46 char PAL_MIX_MISSING_ARGS[] = "Missing parameters.\npal_mix inPix1 inpix2 outPix [p1 p2]\n";
47
48 int subtool_pal_mix (int argc, char **argv, int argi, char **err)
49 {
50         uint_fast16_t id[3] = {0, 1, 2};
51         ILint xyf0[3] = {0, 0, 0};
52         struct IL_full_info info[3];
53         FLAG_TYPE flags[3] = {
54                 MUST_BE_INDEXED | NOT_WRITABLE | OK_PALETTE_ONLY | CAN_BE_MULTIPLE,
55                 MUST_BE_INDEXED | NOT_WRITABLE | OK_PALETTE_ONLY | CAN_BE_MULTIPLE,
56                 MUST_BE_INDEXED | NOT_READABLE | OK_PALETTE_ONLY | CAN_BE_MULTIPLE
57         };
58         ILubyte new_pal[0x100 * 4];
59         struct rel_data data;
60         ILuint i;
61         int r;
62         
63         if (argc < argi + 3)
64         {
65                 *err = PAL_MIX_MISSING_ARGS;
66                 return EINVAL;
67         }
68         
69         if (argc >= argi + 5)
70         {
71                 sscanf(argv[argi+3],"%u",&(data.p0));
72                 sscanf(argv[argi+4],"%u",&(data.p1));
73         }
74         else
75         {
76                 data.p0 = 1;
77                 data.p1 = 0;
78         }
79         data.p = data.p0 + data.p1;
80         
81         r = reserve_pictures(3);
82         if (r)
83         {
84                 *err = CREATE_FAILED;
85                 return r;
86         }
87         
88         r = load_picture(0, argv[argi], &(info[0]), &(flags[0]));
89         if (r)
90         {
91                 *err = LOAD_FAILED;
92                 return r;
93         }
94         
95         r = load_picture(1, argv[argi+1], &(info[1]), &(flags[1]));
96         if (r)
97         {
98                 *err = LOAD_FAILED;
99                 return r;
100         }
101         
102         if ((info[0].image_height != info[1].image_height) || (info[0].image_width != info[1].image_width) || (info[0].num_images != info[1].num_images))
103         {
104                 *err = SIZE_MISMATCH;
105                 return EINVAL;
106         }
107         
108         if ((info[0].palette_num_cols * info[1].palette_num_cols) > 0x100)
109         {
110                 *err = BAD_PALETTE_SIZE;
111                 return EINVAL;
112         }
113         
114         if ((flags[0] & HAS_ALPHA) || (flags[1] & HAS_ALPHA))
115         {
116                 flags[0] |= MUST_HAVE_ALPHA;
117                 flags[1] |= MUST_HAVE_ALPHA;
118                 flags[2] |= MUST_HAVE_ALPHA;
119         }
120         else
121                 flags[2] |= CANNOT_HAVE_ALPHA;
122         
123         r = convert_picture(0, &(info[0]), &(flags[0]));
124         if (r!=0)
125         {
126                 *err = CONVERT_FAILED;
127                 return EIO;
128         }
129         
130         r = convert_picture(1, &(info[1]), &(flags[1]));
131         if (r!=0)
132         {
133                 *err = CONVERT_FAILED;
134                 return EIO;
135         }
136         
137         r = build_picture_from_info(2, &(info[0]), &(info[2]), &(flags[2]));
138         if (r!=0)
139         {
140                 *err = CREATE_FAILED;
141                 return EIO;
142         }
143         
144         for (i=0; i<=info[2].num_images; ++i)
145         {
146                 r = set_palette (
147                         2,
148                         new_pal,
149                         info[0].palette_num_cols * info[1].palette_num_cols * info[0].palette_bpp,
150                         info[0].palette_type,
151                         i
152                 );
153                 if (r!=0)
154                 {
155                         *err = CONVERT_FAILED;
156                         return EIO;
157                 }
158         }
159         
160         r = perform_action_palette_mix(
161                 id,
162                 &palette_mix_value,
163                 flags,
164                 &data
165         );
166         if (r)
167         {
168                 *err = CONVERT_FAILED;
169                 return r;
170         }
171         
172         flags[0] &= ~OK_PALETTE_ONLY;
173         flags[1] &= ~OK_PALETTE_ONLY;
174         flags[2] &= ~OK_PALETTE_ONLY;
175         
176         r = perform_action(
177                 3,
178                 id,
179                 xyf0, xyf0, xyf0,
180                 0, 0, 0,
181                 &palette_mix_index,
182                 flags,
183                 &data
184         );
185         if (r)
186         {
187                 *err = CONVERT_FAILED;
188                 return r;
189         }
190         
191         r = save_picture(2, argv[argi+2], flags[2]);
192         if (r!=0)
193         {
194                 *err = SAVE_FAILED;
195                 return r;
196         }
197         
198         return 0;
199 }
200
201 int palette_mix_value (ILuint n, struct PixelInfo *p, void *data)
202 {
203         if (n < 3)
204                 return EIO;
205         
206         p[2].red   = mix_value_1ch(p[0].red,   p[1].red,   data);
207         p[2].green = mix_value_1ch(p[0].green, p[1].green, data);
208         p[2].blue  = mix_value_1ch(p[0].blue,  p[1].blue,  data);
209         if (p[2].flags & EFF_ALPHA)
210                 p[2].alpha = mix_value_1ch(p[0].alpha, p[1].alpha, data);
211         
212         return 0;
213 }
214
215 ILuint mix_value_1ch (ILint64 x, ILint64 y, struct rel_data *rel)
216 {
217         ILint64 v = (x * rel->p0 + y * rel->p1) / rel->p;
218         return (ILuint) v;
219 }
220
221 /*
222 #include <stdlib.h>
223 #include <stdio.h>
224 #include "IL/il.h"
225
226 int mustard(const char *t,int m,int e);
227 int main(int argc, char *argv[]);
228
229 ILuint inpix1, inpix2, outpix;
230 unsigned char q =0;
231
232
233 int main(int argc, char *argv[])
234 {
235         
236         ILubyte *pal1, *pal2, *data1, *data2, *data;
237         ILubyte pal[256*3];
238         unsigned short i,j;
239         unsigned long k;
240         ILuint col1, col2, col,  x1, x2, y1, y2;
241         
242         unsigned short p1, p2, p3;
243         
244         if (argc<4)
245                 return mustard("insert inpix1 inpix2 outpix [p1 p2]",0,1);
246         if(argc>=5)
247                 p1=atoi(argv[4]);
248         else
249                 p1=1;
250         if(argc>=6)
251                 p2=atoi(argv[5]);
252         else
253                 p2=0;
254         if(argc>=7)
255                 q=1;
256         p3=p1+p2;
257         
258         ilInit();
259                 
260         ilEnable(IL_ORIGIN_SET);
261         ilEnable(IL_FILE_OVERWRITE);
262         
263         ilGenImages(1,&inpix1);
264         ilGenImages(1,&inpix2);
265         ilGenImages(1,&outpix);
266         
267         ilBindImage(inpix1);
268         if(!ilLoadImage(argv[1]))
269                 return mustard("inpix1 load fail.",1,1);
270         if(ilGetInteger(IL_IMAGE_FORMAT)!=IL_COLOUR_INDEX)
271                 return mustard("inpix1 not indexed.",1,1);
272         ilConvertPal(IL_PAL_RGB24);
273         col1=ilGetInteger(IL_PALETTE_NUM_COLS);
274         if(col1>16)
275                 return mustard("inpix1 too many colors.",1,1);
276         x1=ilGetInteger(IL_IMAGE_WIDTH);
277         y1=ilGetInteger(IL_IMAGE_HEIGHT);
278         pal1=ilGetPalette();
279         data1=ilGetData();
280         
281         ilBindImage(inpix2);
282         if(!ilLoadImage(argv[2]))
283                 return mustard("inpix2 load fail.",1,1);
284         if(ilGetInteger(IL_IMAGE_FORMAT)!=IL_COLOUR_INDEX)
285                 return mustard("inpix2 not indexed.",1,1);
286         ilConvertPal(IL_PAL_RGB24);
287         col2=ilGetInteger(IL_PALETTE_NUM_COLS);
288         if(col2>16)
289                 return mustard("inpix2 too many colors.",1,1);
290         if(col1!=col2)
291                 return mustard("different palette size.",1,1);
292         x2=ilGetInteger(IL_IMAGE_WIDTH);
293         if(x1!=x2)
294                 return mustard("different widths",1,1);
295         y2=ilGetInteger(IL_IMAGE_HEIGHT);
296         if(y1!=y2)
297                 return mustard("different heights",1,1);
298         pal2=ilGetPalette();
299         data2=ilGetData();
300         col=col1*col2;
301         
302         for(i=0;i<col1;++i)
303         {
304                 for(j=0;j<col2;++j)
305                 {
306                         pal[3*(i*col1+j)  ]=(pal1[3*i  ]*p1+pal2[3*j  ]*p2)/p3;
307                         pal[3*(i*col1+j)+1]=(pal1[3*i+1]*p1+pal2[3*j+1]*p2)/p3;
308                         pal[3*(i*col1+j)+2]=(pal1[3*i+2]*p1+pal2[3*j+2]*p2)/p3;
309                 }
310         }
311         
312         ilBindImage(outpix);
313         if(!ilTexImage(x1,y1,1,1,IL_COLOUR_INDEX,IL_UNSIGNED_BYTE,NULL))
314                 return mustard ("outpix create fail.",1,1);
315         ilRegisterPal(pal,col*3,IL_PAL_RGB24);
316         data=ilGetData();
317         
318         for(k=0;k<x1*y1;++k)
319                 data[k]=data1[k]*col2+data2[k];
320         
321         if(!ilSave(IL_PNG,argv[3]))
322                 return mustard("outpix save fail",1,1);
323                                 
324         return mustard("Ok",1,0);
325         
326         
327 }
328 int mustard(const char *t, int m,int e)
329 {
330         if(!q)puts(t);
331         switch (m)
332   {
333   case 1:
334         ilDeleteImages(1,&inpix1);
335                 ilDeleteImages(1,&inpix2);
336                 ilDeleteImages(1,&outpix);
337   case 0:
338   default:
339                 return e;
340         }
341 }
342         
343 */