6 Copyright (C) 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)
54 int difference (ILuint n, struct PixelInfo *p, void *data);
55 static inline ILuint diff_1ch (ILint64 x, ILint64 y, ILint64 A, ILint64 B, ILint64 F);
57 char DIFF_MISSING_ARGS[] = "Missing parameters.\ndiff inPixA inPixB outPix [RA GA BA [RB GB BB]]\n";
59 int subtool_diff (int argc, char **argv, int argi, char **err)
62 struct diff_data data;
63 struct IL_full_info info[3];
64 uint_fast16_t id[3] = {0, 1, 2};
65 ILint xyf0[3] = {0, 0, 0};
66 FLAG_TYPE flags[3] = {
67 CAN_BE_MULTIPLE | CAN_BE_OVER_8BIT | CANNOT_BE_GRAY | NOT_WRITABLE,
68 CAN_BE_MULTIPLE | CAN_BE_OVER_8BIT | CANNOT_BE_GRAY | NOT_WRITABLE,
69 CAN_BE_MULTIPLE | CAN_BE_OVER_8BIT | CANNOT_BE_GRAY | NOT_READABLE
71 uint_fast8_t palette_only;
73 ILubyte new_pal[0x100 * 4];
78 *err = DIFF_MISSING_ARGS;
82 r = reserve_pictures(3);
89 r = load_picture(0, argv[argi], &(info[0]), &(flags[0]));
96 r = load_picture(1, argv[argi+1], &(info[1]), &(flags[1]));
103 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))
105 *err = SIZE_MISMATCH;
109 if ((info[0].image_bpc != info[1].image_bpc) || (!(flags[0] & IS_OVER_8BIT)) || (!(flags[0] & IS_OVER_8BIT)))
111 flags[0] &= ~CAN_BE_OVER_8BIT;
112 flags[1] &= ~CAN_BE_OVER_8BIT;
113 flags[2] &= ~CAN_BE_OVER_8BIT;
116 if ((flags[0] & HAS_ALPHA) || (flags[1] & HAS_ALPHA))
118 flags[0] |= MUST_HAVE_ALPHA;
119 flags[1] |= MUST_HAVE_ALPHA;
120 flags[2] |= MUST_HAVE_ALPHA;
123 flags[2] |= CANNOT_HAVE_ALPHA;
125 if ((flags[0] & IS_INDEXED) && (flags[1] & IS_INDEXED) && ((info[0].palette_num_cols * info[1].palette_num_cols) <= 0x100))
128 flags[0] |= OK_PALETTE_ONLY;
129 flags[1] |= OK_PALETTE_ONLY;
130 flags[2] |= OK_PALETTE_ONLY;
131 flags[0] &= ~CAN_BE_OVER_8BIT;
132 flags[1] &= ~CAN_BE_OVER_8BIT;
133 flags[2] &= ~CAN_BE_OVER_8BIT;
134 flags[2] |= MUST_BE_INDEXED;
139 flags[0] |= CANNOT_BE_INDEXED;
140 flags[1] |= CANNOT_BE_INDEXED;
141 flags[2] |= CANNOT_BE_INDEXED;
144 r = convert_picture(0, &(info[0]), &(flags[0]));
147 *err = CONVERT_FAILED;
151 r = convert_picture(1, &(info[1]), &(flags[1]));
154 *err = CONVERT_FAILED;
158 if (argc >= argi + 6)
160 sscanf(argv[argi+3],"%hhu",&v);
161 data.r_a = upscale_value(v, info[0].image_bpc);
162 sscanf(argv[argi+4],"%hhu",&v);
163 data.g_a = upscale_value(v, info[0].image_bpc);
164 sscanf(argv[argi+5],"%hhu",&v);
165 data.b_a = upscale_value(v, info[0].image_bpc);
169 data.r_a = upscale_value(RA, info[0].image_bpc);
170 data.g_a = upscale_value(GA, info[0].image_bpc);
171 data.b_a = upscale_value(BA, info[0].image_bpc);
173 if (argc >= argi + 9)
175 sscanf(argv[argi+6],"%hhu",&v);
176 data.r_b = upscale_value(v, info[0].image_bpc);
177 sscanf(argv[argi+7],"%hhu",&v);
178 data.g_b = upscale_value(v, info[0].image_bpc);
179 sscanf(argv[argi+8],"%hhu",&v);
180 data.b_b = upscale_value(v, info[0].image_bpc);
184 data.r_b = upscale_value(RB, info[0].image_bpc);
185 data.g_b = upscale_value(GB, info[0].image_bpc);
186 data.b_b = upscale_value(BB, info[0].image_bpc);
188 data.max = upscale_value(0xFF, info[0].image_bpc);
190 r = build_picture_from_info(2, &(info[0]), &(info[2]), &(flags[2]));
193 *err = CREATE_FAILED;
199 for (i=0; i<=info[2].num_images; ++i)
204 info[0].palette_num_cols * info[1].palette_num_cols * info[0].palette_bpp,
205 info[0].palette_type,
210 r = perform_action_palette_mix(
218 *err = CONVERT_FAILED;
221 flags[0] &= ~OK_PALETTE_ONLY;
222 flags[1] &= ~OK_PALETTE_ONLY;
223 flags[2] &= ~OK_PALETTE_ONLY;
235 *err = CONVERT_FAILED;
252 *err = CONVERT_FAILED;
257 r = save_picture(2, argv[argi+2], flags[2]);
267 int difference (ILuint n, struct PixelInfo *p, void *data)
275 p[2].red = diff_1ch(p[0].red, p[1].red, d->r_a, d->r_b, d->max);
276 p[2].green = diff_1ch(p[0].green, p[1].green, d->g_a, d->g_b, d->max);
277 p[2].blue = diff_1ch(p[0].blue, p[1].blue, d->b_a, d->b_b, d->max);
278 if (p[2].flags & EFF_ALPHA)
279 p[2].alpha = (p[0].alpha + p[1].alpha) / 2; /* no better idea */
284 static inline ILuint diff_1ch (ILint64 x, ILint64 y, ILint64 A, ILint64 B, ILint64 F)
291 v = y + ((A * (x - y)) / F);
293 v = x + ((B * (y - x)) / F);