3 The tool to hide two indexed images iside one
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)
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);
46 char PAL_MIX_MISSING_ARGS[] = "Missing parameters.\npal_mix inPix1 inpix2 outPix [p1 p2]\n";
48 int subtool_pal_mix (int argc, char **argv, int argi, char **err)
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,
55 MUST_BE_INDEXED | NOT_WRITABLE | OK_PALETTE_ONLY,
56 MUST_BE_INDEXED | NOT_READABLE | OK_PALETTE_ONLY
58 ILubyte new_pal[0x100 * 4];
65 *err = PAL_MIX_MISSING_ARGS;
71 sscanf(argv[argi+3],"%u",&(data.p0));
72 sscanf(argv[argi+4],"%u",&(data.p1));
79 data.p = data.p0 + data.p1;
81 r = reserve_pictures(3);
88 r = load_picture(0, argv[argi], &(info[0]), &(flags[0]));
95 r = load_picture(1, argv[argi+1], &(info[1]), &(flags[1]));
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))
104 *err = SIZE_MISMATCH;
108 if ((info[0].palette_num_cols * info[1].palette_num_cols) > 0x100)
110 *err = BAD_PALETTE_SIZE;
114 if ((flags[0] & HAS_ALPHA) || (flags[1] & HAS_ALPHA))
116 flags[0] |= MUST_HAVE_ALPHA;
117 flags[1] |= MUST_HAVE_ALPHA;
118 flags[2] |= MUST_HAVE_ALPHA;
121 flags[2] |= CANNOT_HAVE_ALPHA;
123 r = convert_picture(0, &(info[0]), &(flags[0]));
126 *err = CONVERT_FAILED;
130 r = convert_picture(1, &(info[1]), &(flags[1]));
133 *err = CONVERT_FAILED;
137 r = build_picture_from_info(2, &(info[0]), &(info[2]), &(flags[2]));
140 *err = CREATE_FAILED;
144 for (i=0; i<=info[2].num_images; ++i)
149 info[0].palette_num_cols * info[1].palette_num_cols * info[0].palette_bpp,
150 info[0].palette_type,
155 r = perform_action_palette_mix(
163 *err = CONVERT_FAILED;
167 flags[0] &= ~OK_PALETTE_ONLY;
168 flags[1] &= ~OK_PALETTE_ONLY;
169 flags[2] &= ~OK_PALETTE_ONLY;
182 *err = CONVERT_FAILED;
186 r = save_picture(2, argv[argi+2], flags[2]);
196 int palette_mix_value (ILuint n, struct PixelInfo *p, void *data)
201 p[2].red = mix_value_1ch(p[0].red, p[1].red, data);
202 p[2].green = mix_value_1ch(p[0].green, p[1].green, data);
203 p[2].blue = mix_value_1ch(p[0].blue, p[1].blue, data);
204 if (p[2].flags & EFF_ALPHA)
205 p[2].alpha = mix_value_1ch(p[0].alpha, p[1].alpha, data);
210 ILuint mix_value_1ch (ILint64 x, ILint64 y, struct rel_data *rel)
212 ILint64 v = (x * rel->p0 + y * rel->p1) / rel->p;
221 int mustard(const char *t,int m,int e);
222 int main(int argc, char *argv[]);
224 ILuint inpix1, inpix2, outpix;
228 int main(int argc, char *argv[])
231 ILubyte *pal1, *pal2, *data1, *data2, *data;
235 ILuint col1, col2, col, x1, x2, y1, y2;
237 unsigned short p1, p2, p3;
240 return mustard("insert inpix1 inpix2 outpix [p1 p2]",0,1);
255 ilEnable(IL_ORIGIN_SET);
256 ilEnable(IL_FILE_OVERWRITE);
258 ilGenImages(1,&inpix1);
259 ilGenImages(1,&inpix2);
260 ilGenImages(1,&outpix);
263 if(!ilLoadImage(argv[1]))
264 return mustard("inpix1 load fail.",1,1);
265 if(ilGetInteger(IL_IMAGE_FORMAT)!=IL_COLOUR_INDEX)
266 return mustard("inpix1 not indexed.",1,1);
267 ilConvertPal(IL_PAL_RGB24);
268 col1=ilGetInteger(IL_PALETTE_NUM_COLS);
270 return mustard("inpix1 too many colors.",1,1);
271 x1=ilGetInteger(IL_IMAGE_WIDTH);
272 y1=ilGetInteger(IL_IMAGE_HEIGHT);
277 if(!ilLoadImage(argv[2]))
278 return mustard("inpix2 load fail.",1,1);
279 if(ilGetInteger(IL_IMAGE_FORMAT)!=IL_COLOUR_INDEX)
280 return mustard("inpix2 not indexed.",1,1);
281 ilConvertPal(IL_PAL_RGB24);
282 col2=ilGetInteger(IL_PALETTE_NUM_COLS);
284 return mustard("inpix2 too many colors.",1,1);
286 return mustard("different palette size.",1,1);
287 x2=ilGetInteger(IL_IMAGE_WIDTH);
289 return mustard("different widths",1,1);
290 y2=ilGetInteger(IL_IMAGE_HEIGHT);
292 return mustard("different heights",1,1);
301 pal[3*(i*col1+j) ]=(pal1[3*i ]*p1+pal2[3*j ]*p2)/p3;
302 pal[3*(i*col1+j)+1]=(pal1[3*i+1]*p1+pal2[3*j+1]*p2)/p3;
303 pal[3*(i*col1+j)+2]=(pal1[3*i+2]*p1+pal2[3*j+2]*p2)/p3;
308 if(!ilTexImage(x1,y1,1,1,IL_COLOUR_INDEX,IL_UNSIGNED_BYTE,NULL))
309 return mustard ("outpix create fail.",1,1);
310 ilRegisterPal(pal,col*3,IL_PAL_RGB24);
314 data[k]=data1[k]*col2+data2[k];
316 if(!ilSave(IL_PNG,argv[3]))
317 return mustard("outpix save fail",1,1);
319 return mustard("Ok",1,0);
323 int mustard(const char *t, int m,int e)
329 ilDeleteImages(1,&inpix1);
330 ilDeleteImages(1,&inpix2);
331 ilDeleteImages(1,&outpix);