From 3944d5e24836840fd4c0cded94b35f77c8e51cf2 Mon Sep 17 00:00:00 2001
From: b <rowerynaksiezycu@gmail.com>
Date: Thu, 1 Dec 2022 21:21:04 +0000
Subject: [PATCH] palette unmix tool is ready

---
 core.c         |   4 +-
 core.h         |   2 +-
 enhance.c      |   5 +-
 makefile       |  13 +-
 makefile.1.mak |  13 +-
 pal_mix.c      |  25 ++--
 pal_unmix.c    | 324 +++++++++++++++++++++++++++++++++----------------
 7 files changed, 256 insertions(+), 130 deletions(-)

diff --git a/core.c b/core.c
index 31e5063..6e2928a 100644
--- a/core.c
+++ b/core.c
@@ -89,7 +89,7 @@ int get_data (uint_fast16_t id, void **data, ILuint frame)
 	return 0;
 }
 
-int get_palette (uint_fast16_t id, void **palette, ILuint frame)
+int get_palette (uint_fast16_t id, void *palette, ILuint frame)
 {
 	if (id >= n_pictures)
 		return EINVAL;
@@ -101,7 +101,7 @@ int get_palette (uint_fast16_t id, void **palette, ILuint frame)
 	ilActiveImage(frame);
 	if (ilGetInteger(IL_IMAGE_FORMAT) != IL_COLOUR_INDEX)
 		return EINVAL;
-	*palette = ilGetPalette();
+	*((void **)palette) = ilGetPalette();
 	return 0;
 }
 
diff --git a/core.h b/core.h
index 7c5f326..f697bff 100644
--- a/core.h
+++ b/core.h
@@ -190,7 +190,7 @@ void finish (int const returnvalue, char const * const returntext);
 int init (void);
 ILuint get_handle (uint_fast16_t id);
 int get_data (uint_fast16_t id, void **data, ILuint frame);
-int get_palette (uint_fast16_t id, void **palette, ILuint frame);
+int get_palette (uint_fast16_t id, void *palette, ILuint frame);
 int set_palette (uint_fast16_t id, void *palette, ILuint size, ILenum type, ILuint frame);
 void create_picture (uint_fast16_t id);
 int create_pictures (uint_fast16_t n);
diff --git a/enhance.c b/enhance.c
index b9af262..0daa9fb 100644
--- a/enhance.c
+++ b/enhance.c
@@ -1,7 +1,7 @@
 /*
 enhance.c
 The tool with multiple enhancements and manipulations of pictures
-30.11.2022
+01.12.2022
 
 Copyright (C) 2022  Balthasar Szczepański
 
@@ -36,6 +36,7 @@ on Pentium III libdevil must be recompiled with
 #include "diff.h"
 #include "npb.h"
 #include "pal_mix.h"
+#include "pal_unmix.h"
 
 int main (int argc, char **argv)
 {
@@ -65,6 +66,8 @@ int main (int argc, char **argv)
 		f = &subtool_npb;
 	else if (strcmp(argv[1], "pal_mix")==0)
 		f = &subtool_pal_mix;
+	else if (strcmp(argv[1], "pal_unmix")==0)
+		f = &subtool_pal_unmix;
 	else
 		finish(EINVAL, "Unknown mode.\n");
 	
diff --git a/makefile b/makefile
index 8f38326..f57b8ce 100644
--- a/makefile
+++ b/makefile
@@ -44,7 +44,8 @@ bluenh\
 reveal\
 diff\
 npb\
-pal_mix
+pal_mix\
+pal_unmix
 
 C_STANDALONE=\
 standalone-nofading.c\
@@ -53,7 +54,8 @@ standalone-bluenh.c\
 standalone-reveal.c\
 standalone-diff.c\
 standalone-npb.c\
-standalone-pal_mix.c
+standalone-pal_mix.c\
+standalone-pal_unmix.c
 
 C_SUBTOOL=\
 nofading.c\
@@ -62,7 +64,8 @@ bluenh.c\
 reveal.c\
 diff.c\
 npb.c\
-pal_mix.c
+pal_mix.c\
+pal_unmix.c
 
 H_SUBTOOL=\
 nofading.h\
@@ -71,7 +74,8 @@ bluenh.h\
 reveal.h\
 diff.h\
 npb.h\
-pal_mix.h
+pal_mix.h\
+pal_unmix.h
 
 H_PNG=\
 npb0.h\
@@ -86,7 +90,6 @@ GENERATE_FROM=
 TO_GENERATE=
 
 
-
 #all: 403 npb npbd npb-ong1 npbd-ong1 bluenh bluenhd insert extract seediff insertframe mremapt-1 compare nofading nofadingd
 all: enhance $(STANDALONE)
 
diff --git a/makefile.1.mak b/makefile.1.mak
index 01c7dca..8dcc31a 100644
--- a/makefile.1.mak
+++ b/makefile.1.mak
@@ -44,7 +44,8 @@ bluenh\
 reveal\
 diff\
 npb\
-pal_mix
+pal_mix\
+pal_unmix
 
 C_STANDALONE=\
 standalone-nofading.c\
@@ -53,7 +54,8 @@ standalone-bluenh.c\
 standalone-reveal.c\
 standalone-diff.c\
 standalone-npb.c\
-standalone-pal_mix.c
+standalone-pal_mix.c\
+standalone-pal_unmix.c
 
 C_SUBTOOL=\
 nofading.c\
@@ -62,7 +64,8 @@ bluenh.c\
 reveal.c\
 diff.c\
 npb.c\
-pal_mix.c
+pal_mix.c\
+pal_unmix.c
 
 H_SUBTOOL=\
 nofading.h\
@@ -71,7 +74,8 @@ bluenh.h\
 reveal.h\
 diff.h\
 npb.h\
-pal_mix.h
+pal_mix.h\
+pal_unmix.h
 
 H_PNG=\
 npb0.h\
@@ -86,7 +90,6 @@ GENERATE_FROM=
 TO_GENERATE=
 
 
-
 #all: 403 npb npbd npb-ong1 npbd-ong1 bluenh bluenhd insert extract seediff insertframe mremapt-1 compare nofading nofadingd
 all: enhance $(STANDALONE)
 
diff --git a/pal_mix.c b/pal_mix.c
index 2ced874..8a713aa 100644
--- a/pal_mix.c
+++ b/pal_mix.c
@@ -1,7 +1,7 @@
 /*
 pal_mix.c
 The tool to hide two indexed images iside one
-30.11.2022
+01.12.2022
 
 Copyright (C) 2015, 2022  Balthasar Szczepański
 
@@ -51,9 +51,9 @@ int subtool_pal_mix (int argc, char **argv, int argi, char **err)
 	ILint xyf0[3] = {0, 0, 0};
 	struct IL_full_info info[3];
 	FLAG_TYPE flags[3] = {
-		MUST_BE_INDEXED | NOT_WRITABLE | OK_PALETTE_ONLY,
-		MUST_BE_INDEXED | NOT_WRITABLE | OK_PALETTE_ONLY,
-		MUST_BE_INDEXED | NOT_READABLE | OK_PALETTE_ONLY
+		MUST_BE_INDEXED | NOT_WRITABLE | OK_PALETTE_ONLY | CAN_BE_MULTIPLE,
+		MUST_BE_INDEXED | NOT_WRITABLE | OK_PALETTE_ONLY | CAN_BE_MULTIPLE,
+		MUST_BE_INDEXED | NOT_READABLE | OK_PALETTE_ONLY | CAN_BE_MULTIPLE
 	};
 	ILubyte new_pal[0x100 * 4];
 	struct rel_data data;
@@ -143,13 +143,18 @@ int subtool_pal_mix (int argc, char **argv, int argi, char **err)
 	
 	for (i=0; i<=info[2].num_images; ++i)
 	{
-		set_palette (
-		2,
-		new_pal,
-		info[0].palette_num_cols * info[1].palette_num_cols * info[0].palette_bpp,
-		info[0].palette_type,
-		i
+		r = set_palette (
+			2,
+			new_pal,
+			info[0].palette_num_cols * info[1].palette_num_cols * info[0].palette_bpp,
+			info[0].palette_type,
+			i
 		);
+		if (r!=0)
+		{
+			*err = CONVERT_FAILED;
+			return EIO;
+		}
 	}
 	
 	r = perform_action_palette_mix(
diff --git a/pal_unmix.c b/pal_unmix.c
index 3dd211c..69b3f65 100644
--- a/pal_unmix.c
+++ b/pal_unmix.c
@@ -1,131 +1,242 @@
-// extract.c
-// The tool to extract two images hidden iside one indexed image
-// 25.06.2015
-// 
-// Copyright (C) 2015  Balthasar Szczepański
-// 
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as
-// published by the Free Software Foundation, either version 3 of the
-// License, or (at your option) any later version.
-// 
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU Affero General Public License for more details.
-// 
-// You should have received a copy of the GNU Affero General Public License
-// along with this program.  If not, see <http://www.gnu.org/licenses/>.
-// 
+/*
+pal_unmix.c
+The tool to extract two images hidden iside one indexed image
+01.12.2022
 
-// Requires Dev Image Library (libdevil) (http://openil.sourceforge.net/)
-// on Pentium III libdevil must be recompiled with
-// --disable-ssl2 --disable-ssl3
-// (https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=572954)
+Copyright (C) 2015, 2022  Balthasar Szczepański
 
-#include <stdlib.h>
-#include <stdio.h>
-#include "IL/il.h"
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Affero General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
 
-int mustard(const char *t,int m,int e);
-int main(int argc, char *argv[]);
-//unsigned short psqrt(unsigned short s);
-unsigned short tsqrt(unsigned short s);
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Affero General Public License for more details.
 
-ILuint inpix, outpix1, outpix2;
-unsigned char q =0;
+You should have received a copy of the GNU Affero General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 
+Requires Dev Image Library (libdevil) (http://openil.sourceforge.net/)
+on Pentium III libdevil must be recompiled with
+--disable-ssl2 --disable-ssl3
+(https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=572954)
 
-int main(int argc, char *argv[])
+*/
+
+#include <stdint.h>
+#include <getopt.h>
+#include <errno.h>
+
+#include "core.h"
+#include "pal_mix.h"
+
+int palette_unmix_index (ILuint n, struct PixelInfo *p, void *data);
+ILuint tsqrt(ILuint s);
+
+char PAL_UNMIX_MISSING_ARGS[] = "Missing parameters.\npal_unmix inPix outPix1 outPix2 [n1 n2]\n";
+
+int subtool_pal_unmix (int argc, char **argv, int argi, char **err)
 {
+	uint_fast16_t id[3] = {0, 1, 2};
+	ILint xyf0[3] = {0, 0, 0};
+	struct IL_full_info info[3];
+	FLAG_TYPE flags[3] = {
+		MUST_BE_INDEXED | NOT_READABLE | CAN_BE_MULTIPLE,
+		MUST_BE_INDEXED | NOT_READABLE | CAN_BE_MULTIPLE,
+		MUST_BE_INDEXED | NOT_WRITABLE | CAN_BE_MULTIPLE
+	};
+	ILubyte new_pal0[0x100 * 4];
+	ILubyte new_pal1[0x100 * 4];
+	ILubyte *pal2;
+	ILubyte *rd, *wr;
+	ILuint n0, n1, n;
+	uint_fast8_t size_defined = 0;
+	ILuint i, j, k;
+	int r;
 	
-	ILubyte *pal, *data1, *data2, *data;
-	ILubyte pal12[16*3];
-	unsigned short i;
-	unsigned long k;
-	ILuint col12, col,  x, y;
-	
-	if (argc<4)
-		return mustard("extract inpix outpix1 outpix2 [q]",0,1);
-	else if (argc>4)
-		q=1;
-	ilInit();
-		
-	ilEnable(IL_ORIGIN_SET);
-	ilEnable(IL_FILE_OVERWRITE);
-	
-	ilGenImages(1,&inpix);
-	ilGenImages(1,&outpix1);
-	ilGenImages(1,&outpix2);
-	
-	ilBindImage(inpix);
-	if(!ilLoadImage(argv[1]))
-		return mustard("inpix load fail.",1,1);
-	if(ilGetInteger(IL_IMAGE_FORMAT)!=IL_COLOUR_INDEX)
-		return mustard("inpix not indexed.",1,1);
-	ilConvertPal(IL_PAL_RGB24);
-	col=ilGetInteger(IL_PALETTE_NUM_COLS);
-	col12=tsqrt(col);
-	if(!col12)
-		return mustard("Palette is not squarish.",1,1);
-	x=ilGetInteger(IL_IMAGE_WIDTH);
-	y=ilGetInteger(IL_IMAGE_HEIGHT);
-	pal=ilGetPalette();
-	data=ilGetData();
-	
-	for(i=0;i<col12;++i)
+	if (argc < argi + 3)
+	{
+		*err = PAL_UNMIX_MISSING_ARGS;
+		return EINVAL;
+	}
+	
+	if (argc >= argi + 5)
+	{
+		sscanf(argv[argi+3],"%u",&(n0));
+		sscanf(argv[argi+4],"%u",&(n1));
+		n = n0 * n1;
+		size_defined = 1;
+	}
+	
+	r = reserve_pictures(3);
+	if (r)
+	{
+		*err = CREATE_FAILED;
+		return r;
+	}
+	
+	r = load_picture(2, argv[argi], &(info[2]), &(flags[2]));
+	if (r)
+	{
+		*err = LOAD_FAILED;
+		return r;
+	}
+	
+	if (size_defined)
+	{
+		if (info[2].palette_num_cols < n)
+		{
+			*err = BAD_PALETTE_SIZE;
+			return EINVAL;
+		}
+	}
+	else
+	{
+		n = info[2].palette_num_cols;
+		n0 = tsqrt(n);
+		if (n0 == 0)
+		{
+			*err = BAD_PALETTE_SIZE;
+			return EINVAL;
+		}
+		n1 = n0;
+	}
+	
+	if (flags[2] & HAS_ALPHA)
 	{
-		pal12[3*i  ]=pal[3*i*(col12+1)  ];
-		pal12[3*i+1]=pal[3*i*(col12+1)+1];
-		pal12[3*i+2]=pal[3*i*(col12+1)+2];
+		flags[0] |= MUST_HAVE_ALPHA;
+		flags[1] |= MUST_HAVE_ALPHA;
+	}
+	else
+	{
+		flags[0] |= CANNOT_HAVE_ALPHA;
+		flags[1] |= CANNOT_HAVE_ALPHA;
+	}
+	
+	r = build_picture_from_info(0, &(info[2]), &(info[0]), &(flags[0]));
+	if (r!=0)
+	{
+		*err = CREATE_FAILED;
+		return EIO;
 	}
 	
-	ilBindImage(outpix1);
-	if(!ilTexImage(x,y,1,1,IL_COLOUR_INDEX,IL_UNSIGNED_BYTE,NULL))
-		return mustard ("outpix1 create fail.",1,1);
-	ilRegisterPal(pal12,col12*3,IL_PAL_RGB24);
-	data1=ilGetData();
+	r = build_picture_from_info(1, &(info[2]), &(info[1]), &(flags[1]));
+	if (r!=0)
+	{
+		*err = CREATE_FAILED;
+		return EIO;
+	}
 	
-	ilBindImage(outpix2);
-	if(!ilTexImage(x,y,1,1,IL_COLOUR_INDEX,IL_UNSIGNED_BYTE,NULL))
-		return mustard ("outpix2 create fail.",1,1);
-	ilRegisterPal(pal12,col12*3,IL_PAL_RGB24);
-	data2=ilGetData();
+	/* create palettes - I didn't define separate action of this type */
 	
-	for(k=0;k<x*y;++k)
+	for (i=0; i<=info[2].num_images; ++i)
 	{
-		data1[k]=data[k]/col12;
-		data2[k]=data[k]%col12;
+		r = get_palette(2, &pal2, i);
+		if (r!=0)
+		{
+			*err = CONVERT_FAILED;
+			return EIO;
+		}
+		
+		wr = new_pal0;
+		for (j=0; j<n0; ++j)
+		{
+			rd = pal2 + ((2*(j*(n-1))+1)/(2*(n0-1))) * info[2].palette_bpp;
+			for (k=0; k<info[2].palette_bpp; ++k)
+			{
+				*wr = *rd;
+				++wr;
+				++rd;
+			}
+		}
+		wr = new_pal1;
+		for (j=0; j<n1; ++j)
+		{
+			rd = pal2 + ((2*(j*(n-1))+1)/(2*(n1-1))) * info[2].palette_bpp;
+			for (k=0; k<info[2].palette_bpp; ++k)
+			{
+				*wr = *rd;
+				++wr;
+				++rd;
+			}
+		}
+		
+		r = set_palette (
+			0,
+			new_pal0,
+			n0 * info[2].palette_bpp,
+			info[2].palette_type,
+			i
+		);
+		if (r!=0)
+		{
+			*err = CONVERT_FAILED;
+			return EIO;
+		}
+		
+		r = set_palette (
+			1,
+			new_pal1,
+			n1 * info[2].palette_bpp,
+			info[2].palette_type,
+			i
+		);
+		if (r!=0)
+		{
+			*err = CONVERT_FAILED;
+			return EIO;
+		}
 	}
 	
-	if(!ilSave(IL_PNG,argv[3]))
-		return mustard("outpix2 save fail",1,1);
-	ilBindImage(outpix1);		   
-	if(!ilSave(IL_PNG,argv[2]))
-		return mustard("outpix1 save fail",1,1);
-				
-	return mustard("Ok",1,0);
+	r = perform_action(
+		3,
+		id,
+		xyf0, xyf0, xyf0,
+		0, 0, 0,
+		&palette_unmix_index,
+		flags,
+		&n1
+	);
+	if (r)
+	{
+		*err = CONVERT_FAILED;
+		return r;
+	}
 	
+	r = save_picture(0, argv[argi+1], flags[0]);
+	if (r!=0)
+	{
+		*err = SAVE_FAILED;
+		return r;
+	}
+	
+	r = save_picture(1, argv[argi+2], flags[1]);
+	if (r!=0)
+	{
+		*err = SAVE_FAILED;
+		return r;
+	}
 	
+	return 0;
 }
 
-int mustard(const char *t, int m,int e)
+int palette_unmix_index (ILuint n, struct PixelInfo *p, void *data)
 {
-	if(!q)puts(t);
-	switch (m)
-  {
-  case 1:
-	ilDeleteImages(1,&inpix);
-		ilDeleteImages(1,&outpix1);
-		ilDeleteImages(1,&outpix2);
-  case 0:
-  default:
-		return e;
-	}
+	ILuint *d = data;
+	
+	if (n < 3)
+		return EIO;
+	
+	p[0].index = p[2].index / *d;
+	p[1].index = p[2].index % *d;
+	
+	return 0;
 }
 
-unsigned short tsqrt(unsigned short s)
+ILuint tsqrt(ILuint s)
 {
 	switch(s)
 	{
@@ -161,10 +272,11 @@ unsigned short tsqrt(unsigned short s)
 		return 2;
 	case 1:
 		return 1;
-	default:
+	default: // not a square - please fail
 		return 0;
 	}
-}       
+}
+
 //unsigned short isqrt(unsigned s)
 //{
 //      unsigned short r;
-- 
2.30.2