From 5f6ae4c4170f2c92b153bd5f2acacc78a0bafb52 Mon Sep 17 00:00:00 2001
From: b <rowerynaksiezycu@gmail.com>
Date: Sat, 12 Nov 2022 16:02:00 +0100
Subject: [PATCH] window for frame, getopt, function select

---
 core.c     | 643 +++++++++++++++++++++++++++--------------------------
 core.h     |  13 +-
 enhance.c  |  10 +-
 info.c     | 175 +--------------
 info.h     |   4 +-
 nofading.c | 372 ++++++++++++-------------------
 nofading.h |   4 +-
 7 files changed, 496 insertions(+), 725 deletions(-)

diff --git a/core.c b/core.c
index faf7dcc..a146279 100644
--- a/core.c
+++ b/core.c
@@ -1,7 +1,7 @@
 /*
 core.c
 The tool with multiple enhancements and manipulations of pictures
-11.11.2022
+12.11.2022
 
 Copyright (C) 2014, 2015, 2022  Balthasar Szczepański
 
@@ -387,19 +387,33 @@ int convert_picture (uint_fast16_t id, FLAG_TYPE flags)
 
 int load_picture (uint_fast16_t id, char *path, FLAG_TYPE flags)
 {
-	ILboolean r;
-	
 	if (id >= n_pictures)
 		return EINVAL;
 	
 	ilBindImage(picture[id].handle);
-	r = ilLoadImage(path);
-	if (!r)
+	if (!ilLoadImage(path))
 		return EIO;
 	
 	return convert_picture(id, flags);
 }
 
+int save_picture (uint_fast16_t id, char *path, FLAG_TYPE flags)
+{
+	int r;
+	
+	if (id >= n_pictures)
+		return EINVAL;
+	
+	ilBindImage(picture[id].handle);
+	r = convert_picture(id, flags);
+	if (r)
+		return r;
+	
+	if (!ilSaveImage(path))
+		return EIO;
+	return 0;
+}
+
 int get_info (uint_fast16_t id, struct IL_full_info *info, ILint frame)
 {
 	int r = 0;
@@ -464,14 +478,13 @@ int get_info (uint_fast16_t id, struct IL_full_info *info, ILint frame)
 
 int action_1picture (
 	uint_fast16_t id,
-	ILint x0, ILint y0, ILint width, ILint height,
+	ILint x0, ILint y0, ILint f0, ILint width, ILint height, ILint frames,
 	ACTION_F *function,
 	FLAG_TYPE flags,
 	void *data
 )
 {
-	ILint f;
-	ILint frames;
+	ILint actual_frames;
 	struct PixelInfo p;
 	int r = 0;
 	
@@ -485,354 +498,360 @@ int action_1picture (
 	
 	if (p.info.num_images > 0)
 		p.flags |= IS_MULTIPLE;
-	frames = (p.flags & CAN_BE_MULTIPLE) ? (p.info.num_images+1) : 1;
+	actual_frames = (p.flags & CAN_BE_MULTIPLE) ? (p.info.num_images+1) : 1;
+	
+	if (!(flags & IN_WINDOW))
+	{
+		f0 = 0;
+		frames = actual_frames;
+	}
 	
 	for (
-		f = 0;
-		(f < frames) && (r == 0);
-		++f
+		p.f_window = 0, p.f_pict = f0;
+		(p.f_window  < frames) && (r == 0);
+		++(p.f_window), ++(p.f_pict)
 	){
-		p.f_window = f;
-		p.f_pict = f;
-		
-		ilBindImage(picture[id].handle);
-		ilActiveImage(f);
-		p.data = ilGetData();
-		p.flags &= ~(IS_GRAY|IS_INDEXED|IS_OVER_8BIT|IS_PALETTE_ONLY);
-		
-		p.alpha_offset = 0;
-		p.value_offset = 0;
-		p.index_offset = 0;
-		p.red_offset = 0;
-		p.green_offset = 0;
-		p.blue_offset = 0;
-		
-		switch (p.info.image_format)
+		if ((p.f_pict >= 0) && (p.f_pict <= p.info.num_images))
 		{
-		case IL_COLOUR_INDEX:
-			p.flags |= IS_INDEXED;
-			p.palette = ilGetPalette();
-			switch (p.info.palette_type)
+			ilBindImage(picture[id].handle);
+			ilActiveImage(p.f_pict);
+			p.data = ilGetData();
+			p.flags &= ~(IS_GRAY|IS_INDEXED|IS_OVER_8BIT|IS_PALETTE_ONLY);
+			
+			p.alpha_offset = 0;
+			p.value_offset = 0;
+			p.index_offset = 0;
+			p.red_offset = 0;
+			p.green_offset = 0;
+			p.blue_offset = 0;
+			
+			switch (p.info.image_format)
 			{
-			case IL_PAL_BGR32:
-			case IL_PAL_RGB32:
-				p.flags |= IS_OVER_8BIT;
+			case IL_COLOUR_INDEX:
+				p.flags |= IS_INDEXED;
+				p.palette = ilGetPalette();
+				switch (p.info.palette_type)
+				{
+				case IL_PAL_BGR32:
+				case IL_PAL_RGB32:
+					p.flags |= IS_OVER_8BIT;
+					break;
+				case IL_PAL_BGRA32:
+					p.flags |= HAS_ALPHA;
+					p.alpha_offset = 3;
+				case IL_PAL_BGR24:
+					p.red_offset = 2;
+					p.green_offset = 1;
+					p.blue_offset = 0;
+					break;
+				case IL_PAL_RGBA32:
+					p.flags |= HAS_ALPHA;
+					p.alpha_offset = 3;
+				case IL_PAL_RGB24:
+				default:
+					p.red_offset = 0;
+					p.green_offset = 1;
+					p.blue_offset = 2;
+					break;
+				}
 				break;
-			case IL_PAL_BGRA32:
+			case IL_LUMINANCE_ALPHA:
 				p.flags |= HAS_ALPHA;
-				p.alpha_offset = 3;
-			case IL_PAL_BGR24:
-				p.red_offset = 2;
-				p.green_offset = 1;
-				p.blue_offset = 0;
+				p.alpha_offset = 1 * p.info.image_bpc;
+			case IL_LUMINANCE:
+				p.flags |= IS_GRAY;
+				p.value_offset = 0 * p.info.image_bpc;
 				break;
-			case IL_PAL_RGBA32:
+			case IL_BGRA:
 				p.flags |= HAS_ALPHA;
-				p.alpha_offset = 3;
-			case IL_PAL_RGB24:
+				p.alpha_offset = 3 * p.info.image_bpc;
+			case IL_BGR:
+				p.red_offset = 2 * p.info.image_bpc;
+				p.green_offset = 1 * p.info.image_bpc;
+				p.blue_offset = 0 * p.info.image_bpc;
+				break;
+			case IL_RGBA:
+				p.flags |= HAS_ALPHA;
+				p.alpha_offset = 3 * p.info.image_bpc;
+			case IL_RGB:
 			default:
-				p.red_offset = 0;
-				p.green_offset = 1;
-				p.blue_offset = 2;
+				p.red_offset = 0 * p.info.image_bpc;
+				p.green_offset = 1 * p.info.image_bpc;
+				p.blue_offset = 2 * p.info.image_bpc;
 				break;
 			}
-			break;
-		case IL_LUMINANCE_ALPHA:
-			p.flags |= HAS_ALPHA;
-			p.alpha_offset = 1 * p.info.image_bpc;
-		case IL_LUMINANCE:
-			p.flags |= IS_GRAY;
-			p.value_offset = 0 * p.info.image_bpc;
-			break;
-		case IL_BGRA:
-			p.flags |= HAS_ALPHA;
-			p.alpha_offset = 3 * p.info.image_bpc;
-		case IL_BGR:
-			p.red_offset = 2 * p.info.image_bpc;
-			p.green_offset = 1 * p.info.image_bpc;
-			p.blue_offset = 0 * p.info.image_bpc;
-			break;
-		case IL_RGBA:
-			p.flags |= HAS_ALPHA;
-			p.alpha_offset = 3 * p.info.image_bpc;
-		case IL_RGB:
-		default:
-			p.red_offset = 0 * p.info.image_bpc;
-			p.green_offset = 1 * p.info.image_bpc;
-			p.blue_offset = 2 * p.info.image_bpc;
-			break;
-		}
-		if (p.info.image_bpc > 1)
-			p.flags |= IS_OVER_8BIT;
-		
-		if ((p.flags & IS_INDEXED) && (p.flags & OK_PALETTE_ONLY))
-		{
-			p.flags |= IS_PALETTE_ONLY;
-			for (
-				p.index = 0, p.pal_offset=0;
-				(p.index < p.info.palette_num_cols) && (r == 0);
-				++p.index, p.pal_offset += p.info.palette_bpp
-			){
-				if (!(p.flags & NOT_READABLE))
-				{
-					p.red   = (ILuint)(*((ILubyte*)(p.palette + p.pal_offset + p.red_offset)));
-					p.green = (ILuint)(*((ILubyte*)(p.palette + p.pal_offset + p.green_offset)));
-					p.blue  = (ILuint)(*((ILubyte*)(p.palette + p.pal_offset + p.blue_offset)));
-					if (p.flags & HAS_ALPHA)
+			if (p.info.image_bpc > 1)
+				p.flags |= IS_OVER_8BIT;
+			
+			if ((p.flags & IS_INDEXED) && (p.flags & OK_PALETTE_ONLY))
+			{
+				p.flags |= IS_PALETTE_ONLY;
+				for (
+					p.index = 0, p.pal_offset=0;
+					(p.index < p.info.palette_num_cols) && (r == 0);
+					++p.index, p.pal_offset += p.info.palette_bpp
+				){
+					if (!(p.flags & NOT_READABLE))
 					{
-						if (p.flags & CANNOT_HAVE_ALPHA)
+						p.red   = (ILuint)(*((ILubyte*)(p.palette + p.pal_offset + p.red_offset)));
+						p.green = (ILuint)(*((ILubyte*)(p.palette + p.pal_offset + p.green_offset)));
+						p.blue  = (ILuint)(*((ILubyte*)(p.palette + p.pal_offset + p.blue_offset)));
+						if (p.flags & HAS_ALPHA)
+						{
+							if (p.flags & CANNOT_HAVE_ALPHA)
+								p.alpha = 0xFF;
+							else
+								p.alpha = (ILuint)(*((ILubyte*)(p.palette + p.pal_offset + p.alpha_offset)));
+						}
+						else if (p.flags & MUST_HAVE_ALPHA)
 							p.alpha = 0xFF;
-						else
-							p.alpha = (ILuint)(*((ILubyte*)(p.palette + p.pal_offset + p.alpha_offset)));
+						if (p.flags & MUST_BE_GRAY)
+							p.value = (p.red + p.green + p.blue) / 3;
 					}
-					else if (p.flags & MUST_HAVE_ALPHA)
-						p.alpha = 0xFF;
-					if (p.flags & MUST_BE_GRAY)
-						p.value = (p.red + p.green + p.blue) / 3;
-				}
-				
-				r = function(1, &p, data);
-				if (r)
-					break;
-				
-				if (!(p.flags & NOT_READABLE))
-				{
-					if (p.flags & MUST_BE_GRAY)
-					{
-						p.red   = p.value;
-						p.green = p.value;
-						p.blue  = p.value;
-					}
-					if (p.flags & HAS_ALPHA)
+					
+					r = function(1, &p, data);
+					if (r)
+						break;
+					
+					if (!(p.flags & NOT_READABLE))
 					{
-						if (p.flags & CANNOT_HAVE_ALPHA)
-							p.alpha = 0xFF;
-						*((ILubyte*)(p.palette + p.pal_offset + p.alpha_offset)) = (ILubyte)p.alpha;
+						if (p.flags & MUST_BE_GRAY)
+						{
+							p.red   = p.value;
+							p.green = p.value;
+							p.blue  = p.value;
+						}
+						if (p.flags & HAS_ALPHA)
+						{
+							if (p.flags & CANNOT_HAVE_ALPHA)
+								p.alpha = 0xFF;
+							*((ILubyte*)(p.palette + p.pal_offset + p.alpha_offset)) = (ILubyte)p.alpha;
+						}
+						*((ILubyte*)(p.palette + p.pal_offset + p.red_offset))   = (ILubyte)p.red;
+						*((ILubyte*)(p.palette + p.pal_offset + p.green_offset)) = (ILubyte)p.green;
+						*((ILubyte*)(p.palette + p.pal_offset + p.blue_offset))  = (ILubyte)p.blue;
 					}
-					*((ILubyte*)(p.palette + p.pal_offset + p.red_offset))   = (ILubyte)p.red;
-					*((ILubyte*)(p.palette + p.pal_offset + p.green_offset)) = (ILubyte)p.green;
-					*((ILubyte*)(p.palette + p.pal_offset + p.blue_offset))  = (ILubyte)p.blue;
 				}
 			}
-		}
-		else
-		{
-			p.line_bytes = p.info.image_bytes_per_pixel * p.info.image_width;
-			p.frame_bytes = p.line_bytes * p.info.image_height;
-			
-			if (p.info.origin_mode == IL_ORIGIN_LOWER_LEFT)
-			{
-				p.line_start = p.frame_bytes - p.line_bytes;
-				p.line_bytes = 0 - p.line_bytes;
-			}
 			else
-				p.line_start = 0;
-			
-			if (!(flags & IN_WINDOW))
 			{
-				x0 = 0;
-				y0 = 0;
-				width = p.info.image_width;
-				height = p.info.image_height;
-			}
-
-			for (
-				p.y_window = 0, p.y_pict = y0, p.line_offset = p.line_start + (p.y_pict * p.line_bytes);
-				(p.y_window < height) && (r == 0);
-				++p.y_window, ++p.y_pict, p.line_offset += p.line_bytes
-			){
-				if ((p.y_pict >= 0) && (p.y_pict < p.info.image_height))
+				p.line_bytes = p.info.image_bytes_per_pixel * p.info.image_width;
+				p.frame_bytes = p.line_bytes * p.info.image_height;
+				
+				if (p.info.image_origin == IL_ORIGIN_LOWER_LEFT)
 				{
-					for (
-						p.x_window = 0, p.x_pict = x0, p.pixel_offset = p.line_offset + (p.x_pict * p.info.image_bytes_per_pixel);
-						(p.x_window < width) && (r == 0);
-						++p.x_window, ++p.x_pict, p.pixel_offset += p.info.image_bytes_per_pixel
-					){
-						if ((p.x_pict >=0) && (p.x_pict < p.info.image_width))
-						{
-							if (!(p.flags & NOT_READABLE))
+					p.line_start = p.frame_bytes - p.line_bytes;
+					p.line_bytes = 0 - p.line_bytes;
+				}
+				else
+					p.line_start = 0;
+				
+				if (!(flags & IN_WINDOW))
+				{
+					x0 = 0;
+					y0 = 0;
+					width = p.info.image_width;
+					height = p.info.image_height;
+				}
+
+				for (
+					p.y_window = 0, p.y_pict = y0, p.line_offset = p.line_start + (p.y_pict * p.line_bytes);
+					(p.y_window < height) && (r == 0);
+					++p.y_window, ++p.y_pict, p.line_offset += p.line_bytes
+				){
+					if ((p.y_pict >= 0) && (p.y_pict < p.info.image_height))
+					{
+						for (
+							p.x_window = 0, p.x_pict = x0, p.pixel_offset = p.line_offset + (p.x_pict * p.info.image_bytes_per_pixel);
+							(p.x_window < width) && (r == 0);
+							++p.x_window, ++p.x_pict, p.pixel_offset += p.info.image_bytes_per_pixel
+						){
+							if ((p.x_pict >=0) && (p.x_pict < p.info.image_width))
 							{
-								/* can this be done better? think about it */
-								switch (p.info.image_type)
+								if (!(p.flags & NOT_READABLE))
 								{
-								case IL_INT:
-								case IL_UNSIGNED_INT:
-									if(p.flags & IS_INDEXED)
-										p.index = *((ILuint*)(p.data + p.pixel_offset + p.index_offset));
-									else
+									/* can this be done better? think about it */
+									switch (p.info.image_type)
 									{
-										if(p.flags & IS_GRAY)
-											p.value = *((ILuint*)(p.data + p.pixel_offset + p.value_offset));
+									case IL_INT:
+									case IL_UNSIGNED_INT:
+										if(p.flags & IS_INDEXED)
+											p.index = *((ILuint*)(p.data + p.pixel_offset + p.index_offset));
 										else
 										{
-											p.red   = *((ILuint*)(p.data + p.pixel_offset + p.red_offset));
-											p.green = *((ILuint*)(p.data + p.pixel_offset + p.green_offset));
-											p.blue  = *((ILuint*)(p.data + p.pixel_offset + p.blue_offset));
+											if(p.flags & IS_GRAY)
+												p.value = *((ILuint*)(p.data + p.pixel_offset + p.value_offset));
+											else
+											{
+												p.red   = *((ILuint*)(p.data + p.pixel_offset + p.red_offset));
+												p.green = *((ILuint*)(p.data + p.pixel_offset + p.green_offset));
+												p.blue  = *((ILuint*)(p.data + p.pixel_offset + p.blue_offset));
+											}
+											if(p.flags & HAS_ALPHA)
+												p.alpha = *((ILuint*)(p.data + p.pixel_offset + p.alpha_offset));
 										}
-										if(p.flags & HAS_ALPHA)
-											p.alpha = *((ILuint*)(p.data + p.pixel_offset + p.alpha_offset));
-									}
-									break;
-								case IL_SHORT:
-								case IL_UNSIGNED_SHORT:
-									if(p.flags & IS_INDEXED)
-										p.index = (ILuint)(*((ILushort*)(p.data + p.pixel_offset + p.index_offset)));
-									else
-									{
-										if(p.flags & IS_GRAY)
-											p.value = (ILuint)(*((ILushort*)(p.data + p.pixel_offset + p.value_offset)));
+										break;
+									case IL_SHORT:
+									case IL_UNSIGNED_SHORT:
+										if(p.flags & IS_INDEXED)
+											p.index = (ILuint)(*((ILushort*)(p.data + p.pixel_offset + p.index_offset)));
+										else
+										{
+											if(p.flags & IS_GRAY)
+												p.value = (ILuint)(*((ILushort*)(p.data + p.pixel_offset + p.value_offset)));
+											else
+											{
+												p.red   = (ILuint)(*((ILushort*)(p.data + p.pixel_offset + p.red_offset)));
+												p.green = (ILuint)(*((ILushort*)(p.data + p.pixel_offset + p.green_offset)));
+												p.blue  = (ILuint)(*((ILushort*)(p.data + p.pixel_offset + p.blue_offset)));
+											}
+											if(p.flags & HAS_ALPHA)
+												p.alpha = (ILuint)(*((ILushort*)(p.data + p.pixel_offset + p.alpha_offset)));
+										}
+										break;
+									case IL_BYTE:
+									case IL_UNSIGNED_BYTE:
+										if(p.flags & IS_INDEXED)
+											p.index = (ILuint)(*((ILubyte*)(p.data + p.pixel_offset + p.index_offset)));
 										else
 										{
-											p.red   = (ILuint)(*((ILushort*)(p.data + p.pixel_offset + p.red_offset)));
-											p.green = (ILuint)(*((ILushort*)(p.data + p.pixel_offset + p.green_offset)));
-											p.blue  = (ILuint)(*((ILushort*)(p.data + p.pixel_offset + p.blue_offset)));
+											if(p.flags & IS_GRAY)
+												p.value = (ILuint)(*((ILubyte*)(p.data + p.pixel_offset + p.value_offset)));
+											else
+											{
+												p.red   = (ILuint)(*((ILubyte*)(p.data + p.pixel_offset + p.red_offset)));
+												p.green = (ILuint)(*((ILubyte*)(p.data + p.pixel_offset + p.green_offset)));
+												p.blue  = (ILuint)(*((ILubyte*)(p.data + p.pixel_offset + p.blue_offset)));
+											}
+											if(p.flags & HAS_ALPHA)
+												p.alpha = (ILuint)(*((ILubyte*)(p.data + p.pixel_offset + p.alpha_offset)));
 										}
-										if(p.flags & HAS_ALPHA)
-											p.alpha = (ILuint)(*((ILushort*)(p.data + p.pixel_offset + p.alpha_offset)));
+										break;
+									default:
+										break;
 									}
-									break;
-								case IL_BYTE:
-								case IL_UNSIGNED_BYTE:
-									if(p.flags & IS_INDEXED)
-										p.index = (ILuint)(*((ILubyte*)(p.data + p.pixel_offset + p.index_offset)));
-									else
+									
+									if ((p.flags & IS_INDEXED) && (p.flags & CANNOT_BE_INDEXED))
 									{
-										if(p.flags & IS_GRAY)
-											p.value = (ILuint)(*((ILubyte*)(p.data + p.pixel_offset + p.value_offset)));
-										else
+										if (p.index < p.info.palette_num_cols)
 										{
-											p.red   = (ILuint)(*((ILubyte*)(p.data + p.pixel_offset + p.red_offset)));
-											p.green = (ILuint)(*((ILubyte*)(p.data + p.pixel_offset + p.green_offset)));
-											p.blue  = (ILuint)(*((ILubyte*)(p.data + p.pixel_offset + p.blue_offset)));
+											p.pal_offset = p.index * p.info.palette_bpp;
+											p.red   = (ILuint)(*((ILubyte*)(p.palette + p.pal_offset + p.red_offset)));
+											p.green = (ILuint)(*((ILubyte*)(p.palette + p.pal_offset + p.green_offset)));
+											p.blue  = (ILuint)(*((ILubyte*)(p.palette + p.pal_offset + p.blue_offset)));
+											if (p.flags & HAS_ALPHA)
+												p.alpha = (ILuint)(*((ILubyte*)(p.palette + p.pal_offset + p.alpha_offset)));
 										}
-										if(p.flags & HAS_ALPHA)
-											p.alpha = (ILuint)(*((ILubyte*)(p.data + p.pixel_offset + p.alpha_offset)));
 									}
-									break;
-								default:
-									break;
-								}
-								
-								if ((p.flags & IS_INDEXED) && (p.flags & CANNOT_BE_INDEXED))
-								{
-									if (p.index < p.info.palette_num_cols)
+									
+									if ((p.flags & IS_GRAY) && (p.flags & CANNOT_BE_GRAY))
 									{
-										p.pal_offset = p.index * p.info.palette_bpp;
-										p.red   = (ILuint)(*((ILubyte*)(p.palette + p.pal_offset + p.red_offset)));
-										p.green = (ILuint)(*((ILubyte*)(p.palette + p.pal_offset + p.green_offset)));
-										p.blue  = (ILuint)(*((ILubyte*)(p.palette + p.pal_offset + p.blue_offset)));
-										if (p.flags & HAS_ALPHA)
-											p.alpha = (ILuint)(*((ILubyte*)(p.palette + p.pal_offset + p.alpha_offset)));
+										p.red   = p.value;
+										p.green = p.value;
+										p.blue  = p.value;
+									}
+									else if (!(p.flags & IS_GRAY) && (p.flags & MUST_BE_GRAY))
+										p.value = (p.red + p.green + p.blue) / 3;
+									
+									if (((!(p.flags & HAS_ALPHA)) && (p.flags & MUST_HAVE_ALPHA)) || ((p.flags & HAS_ALPHA) && (p.flags & CANNOT_HAVE_ALPHA)))
+									{
+										switch (p.info.image_type)
+										{
+										case IL_INT:
+										case IL_UNSIGNED_INT:
+											p.alpha = 0xFFFFFFFF;
+											break;
+										case IL_SHORT:
+										case IL_UNSIGNED_SHORT:
+											p.alpha = 0xFFFF;
+											break;
+										case IL_BYTE:
+										case IL_UNSIGNED_BYTE:
+											p.alpha = 0xFF;
+											break;
+										default:
+											break;
+										}
 									}
 								}
 								
-								if ((p.flags & IS_GRAY) && (p.flags & CANNOT_BE_GRAY))
-								{
-									p.red   = p.value;
-									p.green = p.value;
-									p.blue  = p.value;
-								}
-								else if (!(p.flags & IS_GRAY) && (p.flags & MUST_BE_GRAY))
-									p.value = (p.red + p.green + p.blue) / 3;
+								r = function(1, &p, data);
+								if (r)
+									break;
 								
-								if (((!(p.flags & HAS_ALPHA)) && (p.flags & MUST_HAVE_ALPHA)) || ((p.flags & HAS_ALPHA) && (p.flags & CANNOT_HAVE_ALPHA)))
+								if (!(p.flags & NOT_WRITABLE))
 								{
+									if ((p.flags & HAS_ALPHA) && (p.flags & CANNOT_HAVE_ALPHA))
+										p.alpha = 0xFFFFFFFF;
+									
+									else if (!(p.flags & IS_GRAY) && (p.flags & MUST_BE_GRAY))
+									{
+										p.red   = p.value;
+										p.green = p.value;
+										p.blue  = p.value;
+									}
+									else if ((p.flags & IS_GRAY) && (p.flags & CANNOT_BE_GRAY))
+										p.value = (p.red + p.green + p.blue) / 3;
+									
 									switch (p.info.image_type)
 									{
 									case IL_INT:
 									case IL_UNSIGNED_INT:
-										p.alpha = 0xFFFFFFFF;
-										break;
-									case IL_SHORT:
-									case IL_UNSIGNED_SHORT:
-										p.alpha = 0xFFFF;
-										break;
-									case IL_BYTE:
-									case IL_UNSIGNED_BYTE:
-										p.alpha = 0xFF;
-										break;
-									default:
-										break;
-									}
-								}
-							}
-							
-							r = function(1, &p, data);
-							if (r)
-								break;
-							
-							if (!(p.flags & NOT_WRITABLE))
-							{
-								if ((p.flags & HAS_ALPHA) && (p.flags & CANNOT_HAVE_ALPHA))
-									p.alpha = 0xFFFFFFFF;
-								
-								else if (!(p.flags & IS_GRAY) && (p.flags & MUST_BE_GRAY))
-								{
-									p.red   = p.value;
-									p.green = p.value;
-									p.blue  = p.value;
-								}
-								else if ((p.flags & IS_GRAY) && (p.flags & CANNOT_BE_GRAY))
-									p.value = (p.red + p.green + p.blue) / 3;
-								
-								switch (p.info.image_type)
-								{
-								case IL_INT:
-								case IL_UNSIGNED_INT:
-									if(p.flags & IS_INDEXED)
-										*((ILuint*)(p.data + p.pixel_offset + p.index_offset)) = p.index;
-									else
-									{
-										if(p.flags & IS_GRAY)
-											*((ILuint*)(p.data + p.pixel_offset + p.value_offset)) = p.value;
+										if(p.flags & IS_INDEXED)
+											*((ILuint*)(p.data + p.pixel_offset + p.index_offset)) = p.index;
 										else
 										{
-											*((ILuint*)(p.data + p.pixel_offset + p.red_offset))   = p.red;
-											*((ILuint*)(p.data + p.pixel_offset + p.green_offset)) = p.green;
-											*((ILuint*)(p.data + p.pixel_offset + p.blue_offset))  = p.blue;
+											if(p.flags & IS_GRAY)
+												*((ILuint*)(p.data + p.pixel_offset + p.value_offset)) = p.value;
+											else
+											{
+												*((ILuint*)(p.data + p.pixel_offset + p.red_offset))   = p.red;
+												*((ILuint*)(p.data + p.pixel_offset + p.green_offset)) = p.green;
+												*((ILuint*)(p.data + p.pixel_offset + p.blue_offset))  = p.blue;
+											}
+											if(p.flags & HAS_ALPHA)
+												*((ILuint*)(p.data + p.pixel_offset + p.alpha_offset)) = (ILubyte)p.alpha;
 										}
-										if(p.flags & HAS_ALPHA)
-											*((ILuint*)(p.data + p.pixel_offset + p.alpha_offset)) = (ILubyte)p.alpha;
-									}
-									break;
-								case IL_SHORT:
-								case IL_UNSIGNED_SHORT:
-									if(p.flags & IS_INDEXED)
-										*((ILushort*)(p.data + p.pixel_offset + p.index_offset)) = (ILushort)p.index;
-									else
-									{
-										if(p.flags & IS_GRAY)
-											*((ILushort*)(p.data + p.pixel_offset + p.value_offset)) = (ILushort)p.value;
+										break;
+									case IL_SHORT:
+									case IL_UNSIGNED_SHORT:
+										if(p.flags & IS_INDEXED)
+											*((ILushort*)(p.data + p.pixel_offset + p.index_offset)) = (ILushort)p.index;
 										else
 										{
-											*((ILushort*)(p.data + p.pixel_offset + p.red_offset))   = (ILushort)p.red;
-											*((ILushort*)(p.data + p.pixel_offset + p.green_offset)) = (ILushort)p.green;
-											*((ILushort*)(p.data + p.pixel_offset + p.blue_offset))  = (ILushort)p.blue;
+											if(p.flags & IS_GRAY)
+												*((ILushort*)(p.data + p.pixel_offset + p.value_offset)) = (ILushort)p.value;
+											else
+											{
+												*((ILushort*)(p.data + p.pixel_offset + p.red_offset))   = (ILushort)p.red;
+												*((ILushort*)(p.data + p.pixel_offset + p.green_offset)) = (ILushort)p.green;
+												*((ILushort*)(p.data + p.pixel_offset + p.blue_offset))  = (ILushort)p.blue;
+											}
+											if(p.flags & HAS_ALPHA)
+												*((ILushort*)(p.data + p.pixel_offset + p.alpha_offset)) = (ILushort)p.alpha;
 										}
-										if(p.flags & HAS_ALPHA)
-											*((ILushort*)(p.data + p.pixel_offset + p.alpha_offset)) = (ILushort)p.alpha;
-									}
-									break;
-								case IL_BYTE:
-								case IL_UNSIGNED_BYTE:
-									if(p.flags & IS_INDEXED)
-										*((ILubyte*)(p.data + p.pixel_offset + p.index_offset)) = (ILubyte)p.index;
-									else
-									{
-										if(p.flags & IS_GRAY)
-											*((ILubyte*)(p.data + p.pixel_offset + p.value_offset)) = (ILubyte)p.value;
+										break;
+									case IL_BYTE:
+									case IL_UNSIGNED_BYTE:
+										if(p.flags & IS_INDEXED)
+											*((ILubyte*)(p.data + p.pixel_offset + p.index_offset)) = (ILubyte)p.index;
 										else
 										{
-											*((ILubyte*)(p.data + p.pixel_offset + p.red_offset))   = (ILubyte)p.red;
-											*((ILubyte*)(p.data + p.pixel_offset + p.green_offset)) = (ILubyte)p.green;
-											*((ILubyte*)(p.data + p.pixel_offset + p.blue_offset))  = (ILubyte)p.blue;
+											if(p.flags & IS_GRAY)
+												*((ILubyte*)(p.data + p.pixel_offset + p.value_offset)) = (ILubyte)p.value;
+											else
+											{
+												*((ILubyte*)(p.data + p.pixel_offset + p.red_offset))   = (ILubyte)p.red;
+												*((ILubyte*)(p.data + p.pixel_offset + p.green_offset)) = (ILubyte)p.green;
+												*((ILubyte*)(p.data + p.pixel_offset + p.blue_offset))  = (ILubyte)p.blue;
+											}
+											if(p.flags & HAS_ALPHA)
+												*((ILubyte*)(p.data + p.pixel_offset + p.alpha_offset)) = (ILubyte)p.alpha;
 										}
-										if(p.flags & HAS_ALPHA)
-											*((ILubyte*)(p.data + p.pixel_offset + p.alpha_offset)) = (ILubyte)p.alpha;
+										break;
+									default:
+										break;
 									}
-									break;
-								default:
-									break;
 								}
 							}
 						}
@@ -844,16 +863,16 @@ int action_1picture (
 	
 	return r;
 }
-int action(
-	ILuint n, struct PixelInfo *info, void *data
-)
-{
-	printf(
-		"%04lu %04lu %04lu: %03lu %03lu %03lu %03lu  %03lu %03lu\n",
-		(unsigned long)(info->x_pict), (unsigned long)(info->y_pict), (unsigned long)(info->f_pict),
-		(unsigned long)(info->red), (unsigned long)(info->green), (unsigned long)(info->blue),
-		(unsigned long)(info->alpha), (unsigned long)(info->value), (unsigned long)(info->index)
-	);
-	return 0;
-}
 
+// int action(
+	// ILuint n, struct PixelInfo *info, void *data
+// )
+// {
+	// printf(
+		// "%04lu %04lu %04lu: %03lu %03lu %03lu %03lu  %03lu %03lu\n",
+		// (unsigned long)(info->x_pict), (unsigned long)(info->y_pict), (unsigned long)(info->f_pict),
+		// (unsigned long)(info->red), (unsigned long)(info->green), (unsigned long)(info->blue),
+		// (unsigned long)(info->alpha), (unsigned long)(info->value), (unsigned long)(info->index)
+	// );
+	// return 0;
+// }
diff --git a/core.h b/core.h
index 0eff002..726ff3a 100644
--- a/core.h
+++ b/core.h
@@ -1,7 +1,7 @@
  /*
 core.h
 The tool with multiple enhancements and manipulations of pictures
-09.11.2022
+12.11.2022
 
 Copyright (C) 2022  Balthasar Szczepański
 
@@ -154,9 +154,11 @@ struct PixelInfo
 	struct IL_full_info info;
 };
 
-typedef int (ACTION_F)(
-	ILuint n, struct PixelInfo *info, void *data
-);
+typedef int (ACTION_F)(ILuint n, struct PixelInfo *info, void *data);
+
+
+typedef int (SUBTOOL_F)(int argc, char **argv, int argi, char **err);
+	
 
 
 
@@ -172,11 +174,12 @@ void clear_pictures (void);
 int reserve_pictures (uint_fast16_t n);
 int convert_picture (uint_fast16_t id, FLAG_TYPE flags);
 int load_picture (uint_fast16_t id, char *path, FLAG_TYPE flags);
+int save_picture (uint_fast16_t id, char *path, FLAG_TYPE flags);
 int get_info (uint_fast16_t id, struct IL_full_info *info, ILint frame);
 
 int action_1picture (
 	uint_fast16_t id,
-	ILint x0, ILint y0, ILint width, ILint height,
+	ILint x0, ILint y0, ILint f0, ILint width, ILint height, ILint frames,
 	ACTION_F *function,
 	FLAG_TYPE flags,
 	void *f_data
diff --git a/enhance.c b/enhance.c
index 0f8eca6..0808b9d 100644
--- a/enhance.c
+++ b/enhance.c
@@ -1,7 +1,7 @@
 /*
 enhance.c
 The tool with multiple enhancements and manipulations of pictures
-06.11.2022
+12.11.2022
 
 Copyright (C) 2022  Balthasar Szczepański
 
@@ -36,6 +36,8 @@ int main (int argc, char **argv)
 {
 	int r;
 	char *error_text = NO_STR;
+	SUBTOOL_F *f;
+	
 	
 	if (argc < 2)
 		finish(EINVAL, "No mode selected.\n");
@@ -45,12 +47,14 @@ int main (int argc, char **argv)
 		finish(r, INIT_FAILED);
 	
 	if (strcmp(argv[1], "nofading")==0)
-		r = nofading(argc-2, argv+2, &error_text);
+		f = &subtool_nofading;
 	else if (strcmp(argv[1], "info")==0)
-		r = info(argc-2, argv+2, &error_text);
+		f = &subtool_info;
 	else
 		finish(EINVAL, "Unknown mode.\n");
 	
+	r = f(argc, argv, 2, &error_text);
+	
 	if (r!=0)
 		finish(r, error_text);
 	
diff --git a/info.c b/info.c
index 1817104..05a40d4 100644
--- a/info.c
+++ b/info.c
@@ -1,7 +1,7 @@
 /*
 info.c
 Get information
-06.11.2022
+12.11.2022
 
 Copyright (C) 2022  Balthasar Szczepański
 
@@ -160,7 +160,7 @@ void print_info_palettetype (char *name, long unsigned value)
 	fputs("\n", stdout);
 }
 
-int info (int argc, char **argv, char **err)
+int subtool_info (int argc, char **argv, int argi, char **err)
 {
 	int r;
 	int i;
@@ -168,7 +168,7 @@ int info (int argc, char **argv, char **err)
 	ILint frames=1;
 	struct IL_full_info info;
 	
-	if (argc<1)
+	if (argc <= argi)
 	{
 		*err = INFO_MISSING_ARGS;
 		return EINVAL;
@@ -181,7 +181,7 @@ int info (int argc, char **argv, char **err)
 		return r;
 	}
 	
-	for (i=0; i<argc; ++i)
+	for (i=argi; i<argc; ++i)
 	{
 		fprintf(stdout,"\n>>> %s <<<\n",argv[i]);
 		r = load_picture(0, argv[i],
@@ -247,170 +247,3 @@ int info (int argc, char **argv, char **err)
 	return 0;
 }
 
-/*
-
-#define INPIX_MUSTARD 1
-#define OUTPIX_MUSTARD 2
-
-#define ARGUMENT_MUSTARD 4
-
-#define ANIMATED_MUSTARD 6
-#define FAIL 900
-#define OK 0
-
-#define CR newdata[4*(i+inX*j)+0]
-#define CG newdata[4*(i+inX*j)+1]
-#define CB newdata[4*(i+inX*j)+2]
-
-#define RA ((long)(*ra))
-#define RB ((long)(*rb))
-#define GA ((long)(*ga))
-#define GB ((long)(*gb))
-#define BA ((long)(*ba))
-#define BB ((long)(*bb))
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <IL/il.h>
-
-void mustard(int mustard);
-
-ILubyte enhance(ILubyte x, long r, long s, long t);
-int main (int argc, const char *argv[]);
-
-ILuint pix;
-ILboolean q=true;
-ILboolean pixOpen=false;
-ILboolean allchannels=false;
-
-ILubyte enhance(ILubyte x, long A, long B)
-{
-	if(A==B)
-		return x;
-	long y=(((long)x)-A)*255/(B-A);
-	return (ILubyte)((y>255)?255:((y<0)?0:y));
-}
-
-int main (int argc, const char *argv[])
-{
-	ILubyte rav, rbv, gav, gbv, bav, bbv;
-	ILubyte *ra, *rb, *ga, *gb, *ba, *bb;
-	ILuint inX, inY, frame;
-	ILubyte *newdata;
-	
-	if(argc<3)
-		mustard(ARGUMENT_MUSTARD);
-	if (argc>=4)
-	{
-		sscanf(argv[3],"%u",&frame);
-	}
-	else
-		frame=0;
-	if (argc>=5)
-	{
-		if (argv[4][0]=='q' || argv[4][0]=='Q')
-			q=false;
-	}
-	if (argc>=6)
-	{
-		if (argv[5][0]=='a' || argv[5][0]=='A')
-			allchannels=true;
-	}
-	
-	ra=&rav;
-	rb=&rbv;
-	if(allchannels)
-	{
-		ga=&gav;
-		gb=&gbv;
-		ba=&bav;
-		bb=&bbv;
-	}
-	else
-	{
-		ga=&rav;
-		gb=&rbv;
-		ba=&rav;
-		bb=&rbv;
-	}
-	
-	ilInit();
-	if(!ilEnable(IL_ORIGIN_SET))mustard(FAIL);
-	if(!ilEnable(IL_FILE_OVERWRITE))mustard(FAIL);
-	ilClearColour(255,255,0,0);
-	ilGenImages(1, &pix);
-	pixOpen=true;
-	ilBindImage(pix);
-	if(!ilLoadImage(argv[1]))mustard(INPIX_MUSTARD);
-	if(!ilConvertImage(IL_RGBA,IL_UNSIGNED_BYTE))mustard(INPIX_MUSTARD);
-	
-	inX=ilGetInteger(IL_IMAGE_WIDTH);
-	inY=ilGetInteger(IL_IMAGE_HEIGHT);
-	if(ilGetInteger(IL_NUM_IMAGES)>1)
-		mustard(ANIMATED_MUSTARD);
-	
-	newdata=ilGetData();
-	
-	*ra=255;
-	*ga=255;
-	*ba=255;
-	*rb=0;
-	*gb=0;
-	*bb=0;
-	
-	for(unsigned long i=frame;i<inX-frame;++i)
-	{
-		for(unsigned long j=frame;j<inY-frame;++j)
-		{
-			if(CR<*ra)
-				*ra=CR;
-			if(CR>*rb)
-				*rb=CR;
-			if(CG<*ga)
-				*ga=CG;
-			if(CG>*gb)
-				*gb=CG;
-			if(CB<*ba)
-				*ba=CB;
-			if(CB>*bb)
-				*bb=CB;
-		}
-	}
-			
-	for(unsigned long i=frame;i<inX-frame;++i)
-	{
-		for(unsigned long j=frame;j<inY-frame;++j)
-		{
-			
-			CR=enhance(CR,RA,RB);
-			CG=enhance(CG,GA,GB);
-			CB=enhance(CB,BA,BB);
-		}
-	}
-	if(!ilSave(IL_PNG,argv[2]))mustard(OUTPIX_MUSTARD);
-	// no mustard
-	mustard(0);
-}
-
-void mustard(int mustard)
-{
-	switch(mustard)
-	{
-	case 0:
-		if(q) printf("ENHANCED!\n");break;
-	case ARGUMENT_MUSTARD:
-		if(q) printf("nofadig inPix outPix [framesize] [q] [a]\n");break;
-	case INPIX_MUSTARD:
-		if(q) printf("inPIX mustard.\n");break;
-	case OUTPIX_MUSTARD:
-		if(q) printf("outPIX mustard.\n");break;
-	case ANIMATED_MUSTARD:
-		if(q) printf("Animation is mustard.\n");break;
-	default:
-		if (q) printf("Ch*rpin* mustard mustaard!\n");
-	}
-	if(pixOpen)
-		ilDeleteImages(1, &pix);
-	exit(mustard);
-}
-*/
diff --git a/info.h b/info.h
index afc04bc..86110b5 100644
--- a/info.h
+++ b/info.h
@@ -1,7 +1,7 @@
  /*
 info.h
 Get information
-01.11.2022
+12.11.2022
 
 Copyright (C) 2022  Balthasar Szczepański
 
@@ -25,4 +25,4 @@ on Pentium III libdevil must be recompiled with
 (https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=572954)
 */
 
-int info (int argc, char **argv, char **err);
+SUBTOOL_F subtool_info;
diff --git a/nofading.c b/nofading.c
index 535acae..803a1f5 100644
--- a/nofading.c
+++ b/nofading.c
@@ -1,7 +1,7 @@
 /*
 nofading.c
 The tool to remove fading from an image
-11.11.2022
+12.11.2022
 
 Copyright (C) 2015, 2022  Balthasar Szczepański
 
@@ -27,8 +27,10 @@ on Pentium III libdevil must be recompiled with
 */
 
 #include <stdint.h>
+#include <getopt.h>
 #include <inttypes.h>
 #include <errno.h>
+#include <unistd.h>
 
 #include "core.h"
 #include "nofading.h"
@@ -41,28 +43,46 @@ on Pentium III libdevil must be recompiled with
 		(high) = (val); \
 }
 
-char NOFADING_MISSING_ARGS[] = "Missing parameters.\nnofading inPix outPix [a] [framesize]\n";
+char NOFADING_MISSING_ARGS[] = "Missing parameters.\nnofading [-a -c -f] [framesize]\n";
 
 struct nofading_data
 {
 	uint_fast8_t individual_channels;
+	uint_fast8_t individual_frames;
+	uint_fast8_t enhance_alpha;
 	ILuint red_low;
 	ILuint red_high;
 	ILuint green_low;
 	ILuint green_high;
 	ILuint blue_low;
 	ILuint blue_high;
+	ILuint alpha_low;
+	ILuint alpha_high;
 	ILuint max;
 };
 
 ILuint enhance_fading_1ch (ILuint val, ILuint low, ILuint high, ILuint max);
-
 int find_fading_range (ILuint n, struct PixelInfo *p, void *data);
 int enhance_fading (ILuint n, struct PixelInfo *p, void *data);
 
+main_nofading (int argc, char **argv)
+{
+	int r;
+	char *error_text = NO_STR;
+	
+	r = init();
+	if r(!=0)
+		finish(r, INIT_FAILED);
+	
+	r = subtool_nofading(argc, argv, 1, &error_text);
+	
+	if (r!=0)
+		finish(r, error_text);
+	
+	finish(0, "");
+}
 
-
-int nofading (int argc, char **argv, char **err)
+int subtool_nofading (int argc, char **argv, int argi, char **err)
 {
 	uint_fast16_t frame_t = 0;
 	uint_fast16_t frame_b = 0;
@@ -72,44 +92,79 @@ int nofading (int argc, char **argv, char **err)
 	ILint y0 = 0;
 	ILint width = 0;
 	ILint height = 0;
-	ILuint handle;
+	ILint frames;
+	ILint loops;
+	ILint f;
 	
 	struct nofading_data data;
 	struct IL_full_info info;
 	
-	FLAG_TYPE flags = CAN_BE_MULTIPLE | CAN_BE_OVER_8BIT;
+	struct option long_options[] = {
+		{"enhance-alpha",       no_argument, NULL, 'a'},
+		{"no-alpha",            no_argument, NULL, 'n'},
+		{"individual-channels", no_argument, NULL, 'c'},
+		{"individual-frames",   no_argument, NULL, 'f'},
+		{"help",                no_argument, NULL, 'h'},
+		{0,                     0,           0,    0}
+	};
+	char short_options[] = "acfh";
 	
+	int opt;
 	int r;
 	
-	if (argc<2)
-	{
-		*err = NOFADING_MISSING_ARGS;
-		return EINVAL;
-	}
+	FLAG_TYPE flags = CAN_BE_MULTIPLE | CAN_BE_OVER_8BIT;
+	
 	data.individual_channels = 0;
-	if (argc>=3)
+	data.individual_frames = 0;
+	data.enhance_alpha = 0;
+	
+	optind = argi;
+	while ((opt = getopt_long(argc, argv, short_options, long_options, NULL)) != -1)
 	{
-		if(argv[2][0]=='a' || argv[3][0]=='A')
+		switch (opt)
+		{
+		case 'a':
+			data.enhance_alpha = 1;
+			break;
+		case 'n':
+			flags |= CANNOT_HAVE_ALPHA;
+			break;
+		case 'c':
 			data.individual_channels = 1;
+			break;
+		case 'f':
+			data.individual_frames = 1;
+			flags |= IN_WINDOW;
+			break;
+		case 'h':
+			/* help */
+			break;
+		}
+	}
+	
+	if (argc < optind + 2)
+	{
+		*err = NOFADING_MISSING_ARGS;
+		return EINVAL;
 	}
 	
-	if (argc>=7)
+	if (argc >= optind + 6)
 	{
-		sscanf(argv[3], "%"SCNuFAST16, &frame_t);
-		sscanf(argv[4], "%"SCNuFAST16, &frame_b);
-		sscanf(argv[5], "%"SCNuFAST16, &frame_l);
-		sscanf(argv[6], "%"SCNuFAST16, &frame_r);
+		sscanf(argv[optind+2], "%"SCNuFAST16, &frame_t);
+		sscanf(argv[optind+3], "%"SCNuFAST16, &frame_b);
+		sscanf(argv[optind+4], "%"SCNuFAST16, &frame_l);
+		sscanf(argv[optind+5], "%"SCNuFAST16, &frame_r);
 	}
-	else if  (argc>=5)
+	else if  (argc >= optind + 4)
 	{
-		sscanf(argv[3], "%"SCNuFAST16, &frame_t);
+		sscanf(argv[optind+2], "%"SCNuFAST16, &frame_t);
 		frame_b = frame_t;
-		sscanf(argv[4], "%"SCNuFAST16, &frame_l);
+		sscanf(argv[optind+3], "%"SCNuFAST16, &frame_l);
 		frame_r = frame_l;
 	}
-	else if  (argc>=4)
+	else if  (argc >= optind + 3)
 	{
-		sscanf(argv[3], "%"SCNuFAST16, &frame_t);
+		sscanf(argv[optind+2], "%"SCNuFAST16, &frame_t);
 		frame_b = frame_t;
 		frame_l = frame_t;
 		frame_r = frame_t;
@@ -134,54 +189,74 @@ int nofading (int argc, char **argv, char **err)
 		return r;
 	}
 	
-	r = load_picture(0, argv[0], flags);
+	r = load_picture(0, argv[optind], flags);
 	if (r)
 	{
 		*err = LOAD_FAILED;
 		return r;
 	}
 	
-	data.red_low   = 0xFFFFFFFF;
-	data.green_low = 0xFFFFFFFF;
-	data.blue_low  = 0xFFFFFFFF;
-	data.red_high  = 0x00000000;
-	data.green_high= 0x00000000;
-	data.blue_high = 0x00000000;
-	
-	get_info(0, &info, 0);
-	
-	data.max = (1<<(info.image_bpc<<3))-1;
-	if (flags & IN_WINDOW)
+	if (data.individual_frames)
 	{
-		x0 = frame_l;
-		y0 = frame_t;
-		width = info.image_width - frame_l - frame_r;
-		height = info.image_height - frame_t - frame_b;
+		loops = info.num_images+1;
+		frames = 1;
+	}
+	else
+	{
+		loops = 1;
+		frames = info.num_images+1;
 	}
 	
-	r = action_1picture (
-		0,
-		x0, y0, width, height,
-		&find_fading_range,
-		flags | NOT_WRITABLE,
-		&data
-	);
-	
-	r = action_1picture (
-		0,
-		x0, y0, width, height,
-		&enhance_fading,
-		flags,
-		&data
-	);
-	
-	handle = get_handle(0);
-	ilBindImage(handle);
+	for (f=0; f<loops; ++f)
+	{
+		data.red_low   = 0xFFFFFFFF;
+		data.green_low = 0xFFFFFFFF;
+		data.blue_low  = 0xFFFFFFFF;
+		data.alpha_low = 0xFFFFFFFF;
+		data.red_high  = 0x00000000;
+		data.green_high= 0x00000000;
+		data.blue_high = 0x00000000;
+		data.alpha_high= 0x00000000;
+		
+		get_info(0, &info, f);
+		data.max = (1<<(info.image_bpc<<3))-1;
+		if (f==0)
+		{
+			if (flags & IN_WINDOW) 
+			{
+				x0 = frame_l;
+				y0 = frame_t;
+				width = info.image_width - frame_l - frame_r;
+				height = info.image_height - frame_t - frame_b;
+			}
+		}
+		
+		r = action_1picture (
+			0,
+			x0, y0, f, width, height, frames,
+			&find_fading_range,
+			flags | NOT_WRITABLE,
+			&data
+		);
+		if (r)
+		{
+			*err = CONVERT_FAILED;
+			return r;
+		}
+		r = action_1picture (
+			0,
+			x0, y0, f, width, height, frames,
+			&enhance_fading,
+			flags,
+			&data
+		);
+	}
 	
-	if(!ilSaveImage(argv[1]))
+	r = save_picture (0, argv[optind+1], flags);
+	if (r)
 	{
 		*err = SAVE_FAILED;
-		return EIO;
+		return r;
 	}
 	
 	return 0;
@@ -209,6 +284,10 @@ int find_fading_range (ILuint n, struct PixelInfo *p, void *data)
 		UPDATE_RANGE(p->green, d->green_low, d->green_high);
 		UPDATE_RANGE(p->blue,  d->green_low, d->green_high);
 	}
+	if ((p->flags & HAS_ALPHA) && (d->enhance_alpha))
+	{
+		UPDATE_RANGE(p->alpha, d->alpha_low, d->alpha_high);
+	}
 	
 	return 0;
 }
@@ -244,175 +323,8 @@ int enhance_fading (ILuint n, struct PixelInfo *p, void *data)
 		p->green = enhance_fading_1ch(p->green, d->green_low, d->green_high, d->max);
 		p->blue  = enhance_fading_1ch(p->blue , d->green_low, d->green_high, d->max);
 	}
-	
-	return 0;
-}
-
-
-/*
-
-#define INPIX_MUSTARD 1
-#define OUTPIX_MUSTARD 2
+	if ((p->flags & HAS_ALPHA) && (d->enhance_alpha))
+		p->alpha = enhance_fading_1ch(p->alpha, d->alpha_low, d->alpha_high, d->max);
 
-#define ARGUMENT_MUSTARD 4
-
-#define ANIMATED_MUSTARD 6
-#define FAIL 900
-#define OK 0
-
-#define CR newdata[4*(i+inX*j)+0]
-#define CG newdata[4*(i+inX*j)+1]
-#define CB newdata[4*(i+inX*j)+2]
-
-#define RA ((long)(*ra))
-#define RB ((long)(*rb))
-#define GA ((long)(*ga))
-#define GB ((long)(*gb))
-#define BA ((long)(*ba))
-#define BB ((long)(*bb))
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <IL/il.h>
-
-void mustard(int mustard);
-
-ILubyte enhance(ILubyte x, long r, long s, long t);
-int main (int argc, const char *argv[]);
-
-ILuint pix;
-ILboolean q=true;
-ILboolean pixOpen=false;
-ILboolean allchannels=false;
-
-ILubyte enhance(ILubyte x, long A, long B)
-{
-	if(A==B)
-		return x;
-	long y=(((long)x)-A)*255/(B-A);
-	return (ILubyte)((y>255)?255:((y<0)?0:y));
-}
-
-int main (int argc, const char *argv[])
-{
-	ILubyte rav, rbv, gav, gbv, bav, bbv;
-	ILubyte *ra, *rb, *ga, *gb, *ba, *bb;
-	ILuint inX, inY, frame;
-	ILubyte *newdata;
-	
-	if(argc<3)
-		mustard(ARGUMENT_MUSTARD);
-	if (argc>=4)
-	{
-		sscanf(argv[3],"%u",&frame);
-	}
-	else
-		frame=0;
-	if (argc>=5)
-	{
-		if (argv[4][0]=='q' || argv[4][0]=='Q')
-			q=false;
-	}
-	if (argc>=6)
-	{
-		if (argv[5][0]=='a' || argv[5][0]=='A')
-			allchannels=true;
-	}
-	
-	ra=&rav;
-	rb=&rbv;
-	if(allchannels)
-	{
-		ga=&gav;
-		gb=&gbv;
-		ba=&bav;
-		bb=&bbv;
-	}
-	else
-	{
-		ga=&rav;
-		gb=&rbv;
-		ba=&rav;
-		bb=&rbv;
-	}
-	
-	ilInit();
-	if(!ilEnable(IL_ORIGIN_SET))mustard(FAIL);
-	if(!ilEnable(IL_FILE_OVERWRITE))mustard(FAIL);
-	ilClearColour(255,255,0,0);
-	ilGenImages(1, &pix);
-	pixOpen=true;
-	ilBindImage(pix);
-	if(!ilLoadImage(argv[1]))mustard(INPIX_MUSTARD);
-	if(!ilConvertImage(IL_RGBA,IL_UNSIGNED_BYTE))mustard(INPIX_MUSTARD);
-	
-	inX=ilGetInteger(IL_IMAGE_WIDTH);
-	inY=ilGetInteger(IL_IMAGE_HEIGHT);
-	if(ilGetInteger(IL_NUM_IMAGES)>1)
-		mustard(ANIMATED_MUSTARD);
-	
-	newdata=ilGetData();
-	
-	*ra=255;
-	*ga=255;
-	*ba=255;
-	*rb=0;
-	*gb=0;
-	*bb=0;
-	
-	for(unsigned long i=frame;i<inX-frame;++i)
-	{
-		for(unsigned long j=frame;j<inY-frame;++j)
-		{
-			if(CR<*ra)
-				*ra=CR;
-			if(CR>*rb)
-				*rb=CR;
-			if(CG<*ga)
-				*ga=CG;
-			if(CG>*gb)
-				*gb=CG;
-			if(CB<*ba)
-				*ba=CB;
-			if(CB>*bb)
-				*bb=CB;
-		}
-	}
-			
-	for(unsigned long i=frame;i<inX-frame;++i)
-	{
-		for(unsigned long j=frame;j<inY-frame;++j)
-		{
-			
-			CR=enhance(CR,RA,RB);
-			CG=enhance(CG,GA,GB);
-			CB=enhance(CB,BA,BB);
-		}
-	}
-	if(!ilSave(IL_PNG,argv[2]))mustard(OUTPIX_MUSTARD);
-	// no mustard
-	mustard(0);
-}
-
-void mustard(int mustard)
-{
-	switch(mustard)
-	{
-	case 0:
-		if(q) printf("ENHANCED!\n");break;
-	case ARGUMENT_MUSTARD:
-		if(q) printf("nofadig inPix outPix [framesize] [q] [a]\n");break;
-	case INPIX_MUSTARD:
-		if(q) printf("inPIX mustard.\n");break;
-	case OUTPIX_MUSTARD:
-		if(q) printf("outPIX mustard.\n");break;
-	case ANIMATED_MUSTARD:
-		if(q) printf("Animation is mustard.\n");break;
-	default:
-		if (q) printf("Ch*rpin* mustard mustaard!\n");
-	}
-	if(pixOpen)
-		ilDeleteImages(1, &pix);
-	exit(mustard);
+	return 0;
 }
-*/
diff --git a/nofading.h b/nofading.h
index 56f4a98..dc13e79 100644
--- a/nofading.h
+++ b/nofading.h
@@ -1,7 +1,7 @@
  /*
 nofading.h
 The tool with multiple enhancements and manipulations of pictures
-01.11.2022
+12.11.2022
 
 Copyright (C) 2022  Balthasar Szczepański
 
@@ -25,4 +25,4 @@ on Pentium III libdevil must be recompiled with
 (https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=572954)
 */
 
-int nofading (int argc, char **argv, char **err);
+SUBTOOL_F subtool_nofading;
-- 
2.30.2