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 | 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
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 *err = CONVERT_FAILED;
160 r = perform_action_palette_mix(
168 *err = CONVERT_FAILED;
172 flags[0] &= ~OK_PALETTE_ONLY;
173 flags[1] &= ~OK_PALETTE_ONLY;
174 flags[2] &= ~OK_PALETTE_ONLY;
187 *err = CONVERT_FAILED;
191 r = save_picture(2, argv[argi+2], flags[2]);
201 int palette_mix_value (ILuint n, struct PixelInfo *p, void *data)
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);
215 ILuint mix_value_1ch (ILint64 x, ILint64 y, struct rel_data *rel)
217 ILint64 v = (x * rel->p0 + y * rel->p1) / rel->p;
226 int mustard(const char *t,int m,int e);
227 int main(int argc, char *argv[]);
229 ILuint inpix1, inpix2, outpix;
233 int main(int argc, char *argv[])
236 ILubyte *pal1, *pal2, *data1, *data2, *data;
240 ILuint col1, col2, col, x1, x2, y1, y2;
242 unsigned short p1, p2, p3;
245 return mustard("insert inpix1 inpix2 outpix [p1 p2]",0,1);
260 ilEnable(IL_ORIGIN_SET);
261 ilEnable(IL_FILE_OVERWRITE);
263 ilGenImages(1,&inpix1);
264 ilGenImages(1,&inpix2);
265 ilGenImages(1,&outpix);
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);
275 return mustard("inpix1 too many colors.",1,1);
276 x1=ilGetInteger(IL_IMAGE_WIDTH);
277 y1=ilGetInteger(IL_IMAGE_HEIGHT);
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);
289 return mustard("inpix2 too many colors.",1,1);
291 return mustard("different palette size.",1,1);
292 x2=ilGetInteger(IL_IMAGE_WIDTH);
294 return mustard("different widths",1,1);
295 y2=ilGetInteger(IL_IMAGE_HEIGHT);
297 return mustard("different heights",1,1);
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;
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);
319 data[k]=data1[k]*col2+data2[k];
321 if(!ilSave(IL_PNG,argv[3]))
322 return mustard("outpix save fail",1,1);
324 return mustard("Ok",1,0);
328 int mustard(const char *t, int m,int e)
334 ilDeleteImages(1,&inpix1);
335 ilDeleteImages(1,&inpix2);
336 ilDeleteImages(1,&outpix);