Implement custom resampling command line args

This change implements -resample X Y command line support in addition to
-resample_factor, when a more sophisticated algorithm is needed to
compute the desired image size.

For example, these can be used to round the image to a multiple of 4 or
to a power of 2 for improved compatibility with various graphics APIs.
diff --git a/basisu_tool.cpp b/basisu_tool.cpp
index 2ab0115..2447943 100644
--- a/basisu_tool.cpp
+++ b/basisu_tool.cpp
@@ -127,6 +127,7 @@
 		" -disable_hierarchical_endpoint_codebooks: Disable hierarchical endpoint codebook usage, slower but higher quality on some compression levels\n"
 		" -compare_ssim: Compute and display SSIM of image comparison (slow)\n"
 		" -bench: UASTC benchmark mode, for development only\n"
+		" -resample X Y: Resample all input textures to XxY pixels using a box filter\n"
 		" -resample_factor X: Resample all input textures by scale factor X using a box filter\n"
 		" -no_sse: Forbid all SSE instruction set usage\n"
 		" -validate_etc1s: Validate internal ETC1S compressor's data structures during compression (slower, intended for development).\n"
@@ -392,6 +393,13 @@
 				
 				arg_count++;
 			}
+			else if (strcasecmp(pArg, "-resample") == 0)
+			{
+				REMAINING_ARGS_CHECK(2);
+				m_comp_params.m_resample_width = atoi(arg_v[arg_index + 1]);
+				m_comp_params.m_resample_height = atoi(arg_v[arg_index + 2]);
+				arg_count += 2;
+			}
 			else if (strcasecmp(pArg, "-resample_factor") == 0)
 			{
 				REMAINING_ARGS_CHECK(1);
diff --git a/encoder/basisu_comp.cpp b/encoder/basisu_comp.cpp
index 9a4a1c0..dc4ae11 100644
--- a/encoder/basisu_comp.cpp
+++ b/encoder/basisu_comp.cpp
@@ -145,6 +145,8 @@
 			PRINT_BOOL_VALUE(m_rdo_uastc_favor_simpler_modes_in_rdo_mode)
 			PRINT_BOOL_VALUE(m_rdo_uastc_multithreading);
 
+			PRINT_INT_VALUE(m_resample_width);
+			PRINT_INT_VALUE(m_resample_height);
 			PRINT_FLOAT_VALUE(m_resample_factor);
 			debug_printf("Has global codebooks: %u\n", m_params.m_pGlobal_codebooks ? 1 : 0);
 			if (m_params.m_pGlobal_codebooks)
@@ -541,7 +543,19 @@
 			file_image.resize(64, 64);
 #endif
 
-			if (m_params.m_resample_factor > 0.0f)
+			if (m_params.m_resample_width > 0 && m_params.m_resample_height > 0)
+			{
+				int new_width = basisu::minimum<int>(m_params.m_resample_width, BASISU_MAX_SUPPORTED_TEXTURE_DIMENSION);
+				int new_height = basisu::minimum<int>(m_params.m_resample_height, BASISU_MAX_SUPPORTED_TEXTURE_DIMENSION);
+
+				debug_printf("Resampling to %ix%i\n", new_width, new_height);
+
+				// TODO: A box filter - kaiser looks too sharp on video. Let the caller control this.
+				image temp_img(new_width, new_height);
+				image_resample(file_image, temp_img, m_params.m_perceptual, "box"); // "kaiser");
+				temp_img.swap(file_image);
+			}
+			else if (m_params.m_resample_factor > 0.0f)
 			{
 				int new_width = basisu::minimum<int>(basisu::maximum(1, (int)ceilf(file_image.get_width() * m_params.m_resample_factor)), BASISU_MAX_SUPPORTED_TEXTURE_DIMENSION);
 				int new_height = basisu::minimum<int>(basisu::maximum(1, (int)ceilf(file_image.get_height() * m_params.m_resample_factor)), BASISU_MAX_SUPPORTED_TEXTURE_DIMENSION);
diff --git a/encoder/basisu_comp.h b/encoder/basisu_comp.h
index 748b872..2c3af96 100644
--- a/encoder/basisu_comp.h
+++ b/encoder/basisu_comp.h
@@ -222,6 +222,8 @@
 			m_rdo_uastc_smooth_block_max_std_dev(UASTC_RDO_DEFAULT_MAX_SMOOTH_BLOCK_STD_DEV, .01f, 65536.0f),
 			m_rdo_uastc_max_allowed_rms_increase_ratio(UASTC_RDO_DEFAULT_MAX_ALLOWED_RMS_INCREASE_RATIO, .01f, 100.0f),
 			m_rdo_uastc_skip_block_rms_thresh(UASTC_RDO_DEFAULT_SKIP_BLOCK_RMS_THRESH, .01f, 100.0f),
+			m_resample_width(0, 1, 16384),
+			m_resample_height(0, 1, 16384),
 			m_resample_factor(0.0f, .00125f, 100.0f),
 			m_ktx2_uastc_supercompression(basist::KTX2_SS_NONE),
 			m_ktx2_zstd_supercompression_level(6, INT_MIN, INT_MAX),
@@ -305,6 +307,8 @@
 			m_rdo_uastc_favor_simpler_modes_in_rdo_mode.clear();
 			m_rdo_uastc_multithreading.clear();
 
+			m_resample_width.clear();
+			m_resample_height.clear();
 			m_resample_factor.clear();
 
 			m_pGlobal_codebooks = nullptr;
@@ -437,6 +441,8 @@
 		bool_param<true> m_rdo_uastc_favor_simpler_modes_in_rdo_mode;
 		bool_param<true> m_rdo_uastc_multithreading;
 
+		param<int> m_resample_width;
+		param<int> m_resample_height;
 		param<float> m_resample_factor;
 		const basist::basisu_lowlevel_etc1s_transcoder *m_pGlobal_codebooks;