From b118d0e0d019e430e6d992fcfcefb57f457d866a Mon Sep 17 00:00:00 2001 From: Alexander Brandt Date: Sun, 8 May 2022 01:59:53 -0300 Subject: [PATCH] Options, new added and others restored --- library/ako-private.h | 6 +++--- library/ako.h | 38 ++++++++++++++++++++------------------ library/encode.c | 8 ++++---- library/format.c | 17 ++++++++--------- library/head.c | 4 ++-- library/lifting.c | 17 +++++++++++++---- library/misc.c | 11 ++++++----- library/quantization.c | 12 +++++++----- tools/akodec.cpp | 27 +++++++++++++++------------ tools/akoenc.cpp | 38 +++++++++++++++++++++++++++----------- 10 files changed, 105 insertions(+), 73 deletions(-) diff --git a/library/ako-private.h b/library/ako-private.h index 48874bc..50da606 100644 --- a/library/ako-private.h +++ b/library/ako-private.h @@ -41,7 +41,7 @@ void akoSavePgmI16(size_t width, size_t height, size_t in_stride, const int16_t* // format.c: -void akoFormatToPlanarI16Yuv(int keep_transparent_pixels, enum akoColor, size_t channels, size_t width, size_t height, +void akoFormatToPlanarI16Yuv(int discard_non_visible, enum akoColor, size_t channels, size_t width, size_t height, size_t in_stride, size_t out_planes_spacing, const uint8_t* in, int16_t* out); void akoFormatToInterleavedU8Rgb(enum akoColor, size_t channels, size_t width, size_t height, size_t in_planes_spacing, size_t out_stride, int16_t* in, @@ -94,8 +94,8 @@ size_t akoImageMaxPlanesSpacingSize(size_t image_w, size_t image_h, size_t tiles // quantization.c: -int16_t akoGate(int factor, size_t tile_w, size_t tile_h, size_t current_w, size_t current_h); -int16_t akoQuantization(int factor, size_t tile_w, size_t tile_h, size_t current_w, size_t current_h); +int16_t akoGate(int factor, int factor_mul, size_t tile_w, size_t tile_h, size_t current_w, size_t current_h); +int16_t akoQuantization(int factor, int factor_mul, size_t tile_w, size_t tile_h, size_t current_w, size_t current_h); // wavelet-cdf53.c: diff --git a/library/ako.h b/library/ako.h index 25bb38f..7c03e01 100644 --- a/library/ako.h +++ b/library/ako.h @@ -40,15 +40,7 @@ enum akoStatus AKO_BROKEN_INPUT, }; -enum akoWrap // Wrap mode -{ - AKO_WRAP_CLAMP = 0, - AKO_WRAP_MIRROR, - AKO_WRAP_REPEAT, - AKO_WRAP_ZERO, -}; - -enum akoWavelet // Wavelet transformation +enum akoWavelet { AKO_WAVELET_DD137 = 0, AKO_WAVELET_CDF53, @@ -56,7 +48,7 @@ enum akoWavelet // Wavelet transformation AKO_WAVELET_NONE, }; -enum akoColor // Color transformation +enum akoColor { AKO_COLOR_YCOCG = 0, AKO_COLOR_SUBTRACT_G, @@ -65,9 +57,18 @@ enum akoColor // Color transformation AKO_COLOR_YCOCG_Q, // Internal }; -enum akoCompression // Compression method +enum akoWrap +{ + AKO_WRAP_CLAMP = 0, + AKO_WRAP_MIRROR, + AKO_WRAP_REPEAT, + AKO_WRAP_ZERO, +}; + +enum akoCompression { - AKO_COMPRESSION_ELIAS_RLE = 0, + AKO_COMPRESSION_KAGARI = 0, + AKO_COMPRESSION_MANBAVARAN, AKO_COMPRESSION_NONE, }; @@ -84,16 +85,17 @@ enum akoEvent struct akoSettings { - enum akoWrap wrap; enum akoWavelet wavelet; enum akoColor color; + enum akoWrap wrap; enum akoCompression compression; size_t tiles_dimension; - int discard_transparent_pixels; - int quantization; int gate; + + int chroma_loss; + int discard_non_visible; }; struct akoCallbacks @@ -116,10 +118,10 @@ struct akoHead uint32_t flags; // bits 0-3 : Channels, 0 = Gray, 1 = Gray + Alpha, 2 = RGB, 3 = RGBA, etc... - // bits 4-5 : Wrap, 0 = Clamp, 1 = Repeat, 2 = Set to zero + // bits 4-5 : Wrap, 0 = Clamp, 1 = Mirror, 2 = Repeat, 3 = Zero // bits 6-7 : Wavelet, 0 = DD137, 1 = CDF53, 2 = Haar, 3 = None - // bits 8-9 : Color, 0 = YCOCG, 1 = YCOCG-R, 2 = Subtract Green, 3 = RGB - // bits 10-11 : Compression, 0 = Elias Coding + Rle, 1 = No compression + // bits 8-9 : Color, 0 = YCOCG, 1 = Subtract Green, 2 = None, 3 = Internal + // bits 10-11 : Compression, 0 = Elias Coding, 1 = rAns, 2 = No compression // bits 12-16 : Tiles dimension, 0 = No tiles, 1 = 8x8, 2 = 16x16, 3 = 32x32, 4 = 64x64, etc... // bits 17-32 : Unused bits (always zero) }; diff --git a/library/encode.c b/library/encode.c index 1505073..a1b6111 100644 --- a/library/encode.c +++ b/library/encode.c @@ -2,7 +2,7 @@ MIT License -Copyright (c) 2021 Alexander Brandt +Copyright (c) 2021-2022 Alexander Brandt Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -131,9 +131,9 @@ AKO_EXPORT size_t akoEncodeExt(const struct akoCallbacks* c, const struct akoSet // 1. Format sEvent(t, tiles_no, AKO_EVENT_FORMAT_START, checked_c.events_data, checked_c.events); { - akoFormatToPlanarI16Yuv(checked_s.discard_transparent_pixels, checked_s.color, channels, tile_w, tile_h, - image_w, planes_spacing, - (const uint8_t*)in + ((image_w * tile_y) + tile_x) * channels, workarea_a); + akoFormatToPlanarI16Yuv(checked_s.discard_non_visible, checked_s.color, channels, tile_w, tile_h, image_w, + planes_spacing, (const uint8_t*)in + ((image_w * tile_y) + tile_x) * channels, + workarea_a); } sEvent(t, tiles_no, AKO_EVENT_FORMAT_END, checked_c.events_data, checked_c.events); diff --git a/library/format.c b/library/format.c index 15fe745..32e0632 100644 --- a/library/format.c +++ b/library/format.c @@ -2,7 +2,7 @@ MIT License -Copyright (c) 2021 Alexander Brandt +Copyright (c) 2021-2022 Alexander Brandt Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -27,10 +27,10 @@ SOFTWARE. #include "ako-private.h" -static inline void sDeinterleave(int discard_transparent_pixels, size_t channels, size_t width, size_t in_stride, +static inline void sDeinterleave(int discard_non_visible, size_t channels, size_t width, size_t in_stride, size_t out_plane, const uint8_t* in, const uint8_t* in_end, int16_t* out) { - if (discard_transparent_pixels != 0) + if (discard_non_visible != 0) { for (; in < in_end; in += in_stride, out += width) for (size_t col = 0; col < width; col++) @@ -61,11 +61,10 @@ static inline void sDeinterleave(int discard_transparent_pixels, size_t channels } -void akoFormatToPlanarI16Yuv(int discard_transparent_pixels, enum akoColor color, size_t channels, size_t width, - size_t height, size_t input_stride, size_t out_planes_spacing, const uint8_t* in, - int16_t* out) +void akoFormatToPlanarI16Yuv(int discard_non_visible, enum akoColor color, size_t channels, size_t width, size_t height, + size_t input_stride, size_t out_planes_spacing, const uint8_t* in, int16_t* out) { - // Deinterleave, convert from u8 to i16, and remove (or not) transparent pixels + // Deinterleave, convert from u8 to i16, and remove (or not) non visible pixels { const size_t in_stride = input_stride * channels; const size_t out_plane = (width * height) + out_planes_spacing; @@ -75,9 +74,9 @@ void akoFormatToPlanarI16Yuv(int discard_transparent_pixels, enum akoColor color if (channels == 3) sDeinterleave(0, 3, width, in_stride, out_plane, in, in_end, out); else if (channels == 4) - sDeinterleave(discard_transparent_pixels, 4, width, in_stride, out_plane, in, in_end, out); + sDeinterleave(discard_non_visible, 4, width, in_stride, out_plane, in, in_end, out); else if (channels == 2) - sDeinterleave(discard_transparent_pixels, 2, width, in_stride, out_plane, in, in_end, out); + sDeinterleave(discard_non_visible, 2, width, in_stride, out_plane, in, in_end, out); else if (channels == 1) sDeinterleave(0, 1, width, in_stride, out_plane, in, in_end, out); else diff --git a/library/head.c b/library/head.c index e7c086d..07b4adc 100644 --- a/library/head.c +++ b/library/head.c @@ -2,7 +2,7 @@ MIT License -Copyright (c) 2021 Alexander Brandt +Copyright (c) 2021-2022 Alexander Brandt Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -56,7 +56,7 @@ static inline enum akoStatus sValidate(size_t channels, size_t width, size_t hei color != AKO_COLOR_NONE) return AKO_INVALID_COLOR_TRANSFORMATION; - if (compression != AKO_COMPRESSION_ELIAS_RLE && compression != AKO_COMPRESSION_NONE) + if (compression != AKO_COMPRESSION_KAGARI && compression != AKO_COMPRESSION_NONE) return AKO_INVALID_COMPRESSION_METHOD; return AKO_OK; diff --git a/library/lifting.c b/library/lifting.c index 9fba0a3..fb3b9f9 100644 --- a/library/lifting.c +++ b/library/lifting.c @@ -2,7 +2,7 @@ MIT License -Copyright (c) 2021 Alexander Brandt +Copyright (c) 2021-2022 Alexander Brandt Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -168,10 +168,19 @@ void akoLift(size_t tile_no, const struct akoSettings* s, size_t channels, size_ // Iterate in Vuy order for (size_t ch = (channels - 1); ch < channels; ch--) // Yes, underflows { - const int16_t q = - akoQuantization(s->quantization * ((ch == 0) ? 1 : 2), tile_w, tile_h, current_w, current_h); + int16_t q = 0; + int16_t g = 0; - const int16_t g = akoGate(s->gate * ((ch == 0) ? 1 : 2), tile_w, tile_h, current_w, current_h); + if (ch == 0) + { + q = akoQuantization(s->quantization, 1, tile_w, tile_h, current_w, current_h); + g = akoGate(s->gate, 1, tile_w, tile_h, current_w, current_h); + } + else + { + q = akoQuantization(s->quantization, s->chroma_loss + 1, tile_w, tile_h, current_w, current_h); + g = akoGate(s->gate, s->chroma_loss + 1, tile_w, tile_h, current_w, current_h); + } // 1. Lift int16_t* lp = in + (tile_w * tile_h + planes_space) * ch; diff --git a/library/misc.c b/library/misc.c index 2286b71..f00f097 100644 --- a/library/misc.c +++ b/library/misc.c @@ -2,7 +2,7 @@ MIT License -Copyright (c) 2021 Alexander Brandt +Copyright (c) 2021-2022 Alexander Brandt Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -31,17 +31,18 @@ AKO_EXPORT struct akoSettings akoDefaultSettings() { struct akoSettings s = {0}; - s.wrap = AKO_WRAP_CLAMP; s.wavelet = AKO_WAVELET_DD137; s.color = AKO_COLOR_YCOCG; - s.compression = AKO_COMPRESSION_ELIAS_RLE; + s.wrap = AKO_WRAP_CLAMP; + s.compression = AKO_COMPRESSION_KAGARI; s.tiles_dimension = 0; - s.discard_transparent_pixels = 0; - s.quantization = 16; s.gate = 0; + s.chroma_loss = 1; + s.discard_non_visible = 0; + return s; } diff --git a/library/quantization.c b/library/quantization.c index 67f7ed1..91d4199 100644 --- a/library/quantization.c +++ b/library/quantization.c @@ -2,7 +2,7 @@ MIT License -Copyright (c) 2021 Alexander Brandt +Copyright (c) 2021-2022 Alexander Brandt Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -64,12 +64,13 @@ static float sExponential(float factor, float tile_w, float tile_h, float curren } -int16_t akoGate(int factor, size_t tile_w, size_t tile_h, size_t current_w, size_t current_h) +int16_t akoGate(int factor, int factor_mul, size_t tile_w, size_t tile_h, size_t current_w, size_t current_h) { if (factor <= 0) return 0; - float g = sExponential((float)factor, (float)tile_w, (float)tile_h, (float)current_w, (float)current_h); + float g = sExponential((float)factor * (float)factor_mul, (float)tile_w, (float)tile_h, (float)current_w, + (float)current_h); if (g < 0.0F) g = 0.0F; @@ -80,12 +81,13 @@ int16_t akoGate(int factor, size_t tile_w, size_t tile_h, size_t current_w, size } -int16_t akoQuantization(int factor, size_t tile_w, size_t tile_h, size_t current_w, size_t current_h) +int16_t akoQuantization(int factor, int factor_mul, size_t tile_w, size_t tile_h, size_t current_w, size_t current_h) { if (factor <= 0) return 1; - float q = sExponential((float)factor, (float)tile_w, (float)tile_h, (float)current_w, (float)current_h); + float q = sExponential((float)factor * (float)factor_mul, (float)tile_w, (float)tile_h, (float)current_w, + (float)current_h); if (q < 1.0F) q = 1.0F; diff --git a/tools/akodec.cpp b/tools/akodec.cpp index 530ea37..4f85e01 100644 --- a/tools/akodec.cpp +++ b/tools/akodec.cpp @@ -2,7 +2,7 @@ MIT License -Copyright (c) 2021 Alexander Brandt +Copyright (c) 2021-2022 Alexander Brandt Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -77,9 +77,10 @@ class AkoImage size_t channels; void* data; - enum akoWrap wrap; - enum akoWavelet wavelet; - enum akoColor color; + akoWavelet wavelet; + akoColor color; + akoWrap wrap; + akoCompression compression; size_t blob_size; public: @@ -89,10 +90,11 @@ class AkoImage size_t get_channels() const { return channels; }; const void* get_data() const { return (const void*)(data); }; - enum akoWrap get_wrap() const { return wrap; }; - enum akoWavelet get_wavelet() const { return wavelet; }; - enum akoColor get_color() const { return color; }; - size_t get_blob_size() const { return blob_size; }; + akoWavelet get_wavelet() const { return wavelet; }; + akoColor get_color() const { return color; }; + akoWrap get_wrap() const { return wrap; }; + akoCompression get_compression() const { return compression; }; + size_t get_blob_size() const { return blob_size; }; // clang-format on AkoImage(const std::string& filename, bool quiet, bool benchmark) @@ -145,9 +147,10 @@ class AkoImage } // Bye! - wrap = settings.wrap; wavelet = settings.wavelet; color = settings.color; + wrap = settings.wrap; + compression = settings.compression; } ~AkoImage() @@ -177,9 +180,9 @@ void AkoDec(const std::string& filename_input, const std::string& filename_outpu const auto ako = AkoImage(filename_input, quiet, benchmark); if (verbose == true) - std::printf("Input data: %zu channels, %zux%zu px, wavelet: %i, color: %i, wrap: %i\n", ako.get_channels(), - ako.get_width(), ako.get_height(), (int)ako.get_wavelet(), (int)ako.get_color(), - (int)ako.get_wrap()); + std::printf("Input data: %zu channels, %zux%zu px, wavelet: %i, color: %i, wrap: %i, compression: %i\n", + ako.get_channels(), ako.get_width(), ako.get_height(), (int)ako.get_wavelet(), (int)ako.get_color(), + (int)ako.get_wrap(), (int)ako.get_compression()); // Checksum data uint32_t input_checksum = 0; diff --git a/tools/akoenc.cpp b/tools/akoenc.cpp index e91a9b6..96dfdfb 100644 --- a/tools/akoenc.cpp +++ b/tools/akoenc.cpp @@ -2,7 +2,7 @@ MIT License -Copyright (c) 2021 Alexander Brandt +Copyright (c) 2021-2022 Alexander Brandt Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -110,10 +110,10 @@ class PngImage size_t EncodePass(bool verbose, int ratio, const akoCallbacks* callbacks, const akoSettings* settings, size_t channels, - size_t width, size_t height, const void* in, void** out, enum akoStatus* out_status) + size_t width, size_t height, const void* in, void** out, akoStatus* out_status) { // One pass, no ratio specified - if (ratio == 0 || settings->wavelet == AKO_WAVELET_NONE) + if (ratio == 0 || settings->wavelet == AKO_WAVELET_NONE || settings->compression == AKO_COMPRESSION_NONE) { return akoEncodeExt(callbacks, settings, channels, width, height, in, out, out_status); } @@ -249,10 +249,12 @@ void AkoEnc(const akoSettings& settings, const std::string& filename_input, cons { std::printf("Encoding...\n"); - std::printf("[Color: %i", (int)settings.color); - std::printf(", wavelet: %i", (int)settings.wavelet); + std::printf("[Wavelet: %i", (int)settings.wavelet); + std::printf(", color: %i", (int)settings.color); std::printf(", wrap: %i", (int)settings.wrap); - std::printf(", discard non-visible: %i]\n", (int)settings.discard_transparent_pixels); + std::printf(", compression %i", (int)settings.compression); + std::printf(", chroma loss: %i", (int)settings.chroma_loss); + std::printf(", discard non-visible: %i]\n", (int)settings.discard_non_visible); } void* blob = NULL; @@ -353,11 +355,11 @@ int main(int argc, const char* argv[]) "Controls loss in the final image and in turn, compression gains. Achieves it by reducing " "wavelet coefficients accuracy accordingly to the provided value. Default and recommended " "loss method. Set it to zero for lossless compression.", - 16, 0, 4096, encoding_category); + 16, 0, 8192, encoding_category); opts.add_integer("-g", "--noise-gate", "Loss method similar to '--quantization', however it removes wavelet coefficients under a " "threshold set by the provided value. Set it to zero for lossless compression.", - 0, 0, 4096, encoding_category); + 0, 0, 8192, encoding_category); opts.add_string("-w", "--wavelet", "Wavelet transformation to apply. Options are: DD137, CDF53, HAAR and NONE. For lossy " "compression DD137 provides better results, for lossless CDF53.", @@ -371,16 +373,27 @@ int main(int argc, const char* argv[]) "all them analog to texture-wrapping options in OpenGL. Two common choices are CLAMP that " "perform no wrap, and REPEAT for images intended to serve as tiled textures.", "CLAMP", "CLAMP MIRROR REPEAT ZERO", encoding_category); + opts.add_integer("-chroma-loss", "--chroma-loss", + "Subsampling thingie. Zero to disable it. Only applies if either '--quantization' or " + "'--noise-gate' is set.", + 1, 0, 8192, encoding_category); opts.add_bool("-d", "--discard-non-visible", "Discard pixels that do not contribute to the final image (those in transparent areas). For " "lossless compression do not set this option.", encoding_category); - opts.add_integer("-r", "--ratio", "", 0, 0, 4096, encoding_category); const auto extra_category = opts.add_category("EXTRA TOOLS"); opts.add_bool("-b", "--benchmark", "", extra_category); opts.add_bool("-ch", "--checksum", "", extra_category); + const auto experimental_category = opts.add_category("EXPERIMENTAL"); + opts.add_integer("-dev-r", "--dev-ratio", "", 0, 0, 4096, experimental_category); + opts.add_string("-dev-compression", "--dev-compression", + "Compression method, options are: KAGARI, MANBAVARAN and NONE. Be caution of the last two as " + "they can crash your computer, corrupt files, produce invalid data, misbrew your colombian " + "coffee and everything in between.", + "KAGARI", "KAGARI MANBAVARAN NONE", experimental_category); + if (opts.parse_arguments(argc, argv) != 0) return 1; @@ -416,7 +429,6 @@ int main(int argc, const char* argv[]) input_filename = opts.get_string("--input"); output_filename = opts.get_string("--output"); - ratio = opts.get_integer("--ratio"); verbose = opts.get_bool("--verbose"); quiet = opts.get_bool("--quiet"); benchmark = opts.get_bool("--benchmark"); @@ -424,10 +436,14 @@ int main(int argc, const char* argv[]) settings.quantization = opts.get_integer("--quantization"); settings.gate = opts.get_integer("--noise-gate"); - settings.discard_transparent_pixels = opts.get_bool("--discard-non-visible"); + settings.discard_non_visible = opts.get_bool("--discard-non-visible"); settings.wavelet = (akoWavelet)opts.get_string_index("--wavelet"); settings.color = (akoColor)opts.get_string_index("--color"); settings.wrap = (akoWrap)opts.get_string_index("--wrap"); + settings.chroma_loss = opts.get_integer("--chroma-loss"); + + ratio = opts.get_integer("--dev-ratio"); + settings.compression = (akoCompression)opts.get_string_index("--dev-compression"); } // Encode!