]> bicyclesonthemoon.info Git - ott/enhance/blob - pal_unmix.c
reveal online
[ott/enhance] / pal_unmix.c
1 /*\r
2 pal_unmix.c\r
3 The tool to extract two images hidden iside one indexed image\r
4 03.12.2022\r
5 \r
6 Copyright (C) 2015, 2022  Balthasar SzczepaƄski\r
7 \r
8 This program is free software: you can redistribute it and/or modify\r
9 it under the terms of the GNU Affero General Public License as\r
10 published by the Free Software Foundation, either version 3 of the\r
11 License, or (at your option) any later version.\r
12 \r
13 This program is distributed in the hope that it will be useful,\r
14 but WITHOUT ANY WARRANTY; without even the implied warranty of\r
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
16 GNU Affero General Public License for more details.\r
17 \r
18 You should have received a copy of the GNU Affero General Public License\r
19 along with this program.  If not, see <http://www.gnu.org/licenses/>.\r
20 \r
21 \r
22 Requires Dev Image Library (libdevil) (http://openil.sourceforge.net/)\r
23 on Pentium III libdevil must be recompiled with\r
24 --disable-ssl2 --disable-ssl3\r
25 (https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=572954)\r
26 \r
27 */\r
28 \r
29 #include <stdint.h>\r
30 #include <getopt.h>\r
31 #include <errno.h>\r
32 \r
33 #include "core.h"\r
34 #include "pal_unmix.h"\r
35 \r
36 int palette_unmix_index (ILuint n, struct PixelInfo *p, void *data);\r
37 \r
38 char PAL_UNMIX_MISSING_ARGS[] = "Missing parameters.\npal_unmix inPix outPix1 outPix2 [n1 n2]\n";\r
39 \r
40 int subtool_pal_unmix (int argc, char **argv, int argi, char **err)\r
41 {\r
42         uint_fast16_t id[3] = {0, 1, 2};\r
43         ILint xyf0[3] = {0, 0, 0};\r
44         struct IL_full_info info[3];\r
45         FLAG_TYPE flags[3] = {\r
46                 MUST_BE_INDEXED | NOT_READABLE | CAN_BE_MULTIPLE,\r
47                 MUST_BE_INDEXED | NOT_READABLE | CAN_BE_MULTIPLE,\r
48                 MUST_BE_INDEXED | NOT_WRITABLE | CAN_BE_MULTIPLE\r
49         };\r
50         ILubyte new_pal0[0x100 * 4];\r
51         ILubyte new_pal1[0x100 * 4];\r
52         ILubyte *pal2;\r
53         ILubyte *rd, *wr;\r
54         ILuint n0, n1, n;\r
55         uint_fast8_t size_defined = 0;\r
56         ILuint i, j, k;\r
57         int r;\r
58         \r
59         if (argc < argi + 3)\r
60         {\r
61                 *err = PAL_UNMIX_MISSING_ARGS;\r
62                 return EINVAL;\r
63         }\r
64         \r
65         if (argc >= argi + 5)\r
66         {\r
67                 sscanf(argv[argi+3],"%u",&n0);\r
68                 sscanf(argv[argi+4],"%u",&n1);\r
69                 n = n0 * n1;\r
70                 size_defined = 1;\r
71         }\r
72         \r
73         r = reserve_pictures(3);\r
74         if (r)\r
75         {\r
76                 *err = CREATE_FAILED;\r
77                 return r;\r
78         }\r
79         \r
80         r = load_picture(2, argv[argi], &(info[2]), &(flags[2]));\r
81         if (r)\r
82         {\r
83                 *err = LOAD_FAILED;\r
84                 return r;\r
85         }\r
86         \r
87         if (size_defined)\r
88         {\r
89                 if (info[2].palette_num_cols < n)\r
90                 {\r
91                         *err = BAD_PALETTE_SIZE;\r
92                         return EINVAL;\r
93                 }\r
94         }\r
95         else\r
96         {\r
97                 n = info[2].palette_num_cols;\r
98                 n0 = tsqrt(n);\r
99                 if (n0 == 0)\r
100                 {\r
101                         *err = BAD_PALETTE_SIZE;\r
102                         return EINVAL;\r
103                 }\r
104                 n1 = n0;\r
105         }\r
106         \r
107         if (flags[2] & HAS_ALPHA)\r
108         {\r
109                 flags[0] |= MUST_HAVE_ALPHA;\r
110                 flags[1] |= MUST_HAVE_ALPHA;\r
111         }\r
112         else\r
113         {\r
114                 flags[0] |= CANNOT_HAVE_ALPHA;\r
115                 flags[1] |= CANNOT_HAVE_ALPHA;\r
116         }\r
117         \r
118         r = build_picture_from_info(0, &(info[2]), &(info[0]), &(flags[0]));\r
119         if (r!=0)\r
120         {\r
121                 *err = CREATE_FAILED;\r
122                 return EIO;\r
123         }\r
124         \r
125         r = build_picture_from_info(1, &(info[2]), &(info[1]), &(flags[1]));\r
126         if (r!=0)\r
127         {\r
128                 *err = CREATE_FAILED;\r
129                 return EIO;\r
130         }\r
131         \r
132         /* create palettes - I didn't define separate action of this type */\r
133         \r
134         for (i=0; i<=info[2].num_images; ++i)\r
135         {\r
136                 r = get_palette(2, &pal2, i);\r
137                 if (r!=0)\r
138                 {\r
139                         *err = CONVERT_FAILED;\r
140                         return EIO;\r
141                 }\r
142                 \r
143                 wr = new_pal0;\r
144                 for (j=0; j<n0; ++j)\r
145                 {\r
146                         rd = pal2 + ((2*(j*(n-1))+1)/(2*(n0-1))) * info[2].palette_bpp;\r
147                         for (k=0; k<info[2].palette_bpp; ++k)\r
148                         {\r
149                                 *wr = *rd;\r
150                                 ++wr;\r
151                                 ++rd;\r
152                         }\r
153                 }\r
154                 wr = new_pal1;\r
155                 for (j=0; j<n1; ++j)\r
156                 {\r
157                         rd = pal2 + ((2*(j*(n-1))+1)/(2*(n1-1))) * info[2].palette_bpp;\r
158                         for (k=0; k<info[2].palette_bpp; ++k)\r
159                         {\r
160                                 *wr = *rd;\r
161                                 ++wr;\r
162                                 ++rd;\r
163                         }\r
164                 }\r
165                 \r
166                 r = set_palette (\r
167                         0,\r
168                         new_pal0,\r
169                         n0 * info[2].palette_bpp,\r
170                         info[2].palette_type,\r
171                         i\r
172                 );\r
173                 if (r!=0)\r
174                 {\r
175                         *err = CONVERT_FAILED;\r
176                         return EIO;\r
177                 }\r
178                 \r
179                 r = set_palette (\r
180                         1,\r
181                         new_pal1,\r
182                         n1 * info[2].palette_bpp,\r
183                         info[2].palette_type,\r
184                         i\r
185                 );\r
186                 if (r!=0)\r
187                 {\r
188                         *err = CONVERT_FAILED;\r
189                         return EIO;\r
190                 }\r
191         }\r
192         \r
193         r = perform_action(\r
194                 3,\r
195                 id,\r
196                 xyf0, xyf0, xyf0,\r
197                 0, 0, 0,\r
198                 &palette_unmix_index,\r
199                 flags,\r
200                 &n1\r
201         );\r
202         if (r)\r
203         {\r
204                 *err = CONVERT_FAILED;\r
205                 return r;\r
206         }\r
207         \r
208         r = save_picture(0, argv[argi+1], flags[0]);\r
209         if (r!=0)\r
210         {\r
211                 *err = SAVE_FAILED;\r
212                 return r;\r
213         }\r
214         \r
215         r = save_picture(1, argv[argi+2], flags[1]);\r
216         if (r!=0)\r
217         {\r
218                 *err = SAVE_FAILED;\r
219                 return r;\r
220         }\r
221         \r
222         return 0;\r
223 }\r
224 \r
225 int palette_unmix_index (ILuint n, struct PixelInfo *p, void *data)\r
226 {\r
227         ILuint *d = data;\r
228         \r
229         if (n < 3)\r
230                 return EIO;\r
231         \r
232         p[0].index = p[2].index / *d;\r
233         p[1].index = p[2].index % *d;\r
234         \r
235         return 0;\r
236 }\r