Skip to content
Snippets Groups Projects
Commit e829d518 authored by theazgra's avatar theazgra
Browse files

Build in zlib's gzip compression.

parent 299ae7c6
No related branches found
No related tags found
No related merge requests found
...@@ -8,10 +8,10 @@ ...@@ -8,10 +8,10 @@
- [ ] Feed binary data to existing compressors and produce results (tables, graphs) - [ ] Feed binary data to existing compressors and produce results (tables, graphs)
- Try both data in their order and in `Z-order` - Try both data in their order and in `Z-order`
- Compressors to try: - Compressors to try:
- gZip - [x] gZip (zLib, huffman deflate combination)
- bzip2 - [ ] bzip2
- deflate - [ ] deflate
- *B3D cuda library* - [ ] *B3D cuda library*
- [ ] Look at *Image difference* - [ ] Look at *Image difference*
- Negative values can be mapped to odd/even numbers. But the difference must be saved in more than one byte. - Negative values can be mapped to odd/even numbers. But the difference must be saved in more than one byte.
- Save difference in different type than byte (`short`, `uint`, `ulong`) - Save difference in different type than byte (`short`, `uint`, `ulong`)
......
...@@ -20,6 +20,9 @@ endif() ...@@ -20,6 +20,9 @@ endif()
find_package (Threads) find_package (Threads)
target_link_libraries (czi-parser ${CMAKE_THREAD_LIBS_INIT}) target_link_libraries (czi-parser ${CMAKE_THREAD_LIBS_INIT})
find_package(ZLIB)
target_link_libraries(czi-parser ${ZLIB_LIBRARIES})
set(CPACK_PROJECT_NAME ${PROJECT_NAME}) set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION}) set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
include(CPack) include(CPack)
\ No newline at end of file
...@@ -3,10 +3,40 @@ ...@@ -3,10 +3,40 @@
#include "../utilities/vector_utilities.h" #include "../utilities/vector_utilities.h"
#include "../image/z_order.h" #include "../image/z_order.h"
namespace library_zlib
{
#include <zlib.h>
};
enum CompressionMethod enum CompressionMethod
{ {
CompressionMethod_RLE, CompressionMethod_RLE,
CompressionMethod_LZ CompressionMethod_LZ,
CompressionMethod_GZIP
};
struct CompressionResult
{
size_t originalSize;
size_t compressedSize;
float compressionRatio;
float percentageOfOriginalSize;
CompressionResult()
{
originalSize = 0;
compressedSize = 0;
compressionRatio = 0.0f;
percentageOfOriginalSize = 0.0f;
}
void divide(float x)
{
originalSize /= x;
compressedSize /= x;
compressionRatio /= x;
percentageOfOriginalSize /= x;
}
}; };
constexpr size_t MAX_LITERAL_COUNT = 255; constexpr size_t MAX_LITERAL_COUNT = 255;
...@@ -18,6 +48,38 @@ inline float compression_ratio(float uncompressedSize, float compressedSize) ...@@ -18,6 +48,38 @@ inline float compression_ratio(float uncompressedSize, float compressedSize)
return (uncompressedSize / compressedSize); return (uncompressedSize / compressedSize);
} }
ByteArray gzip_encode(const std::vector<byte> &data)
{
size_t compressedSize = library_zlib::compressBound(data.size());
ByteArray compressedBuffer;
// Maybe try reserve or normal array.
compressedBuffer.resize(compressedSize);
//int compressionResult = library_zlib::compress(compressedBuffer.data(), &compressedSize, data.data(), data.size());
int compressionResult = library_zlib::compress2(compressedBuffer.data(), &compressedSize, data.data(), data.size(), Z_BEST_COMPRESSION);
switch (compressionResult)
{
case Z_OK:
break;
case Z_MEM_ERROR:
printf(RED "There wasn't enaugh memory!\n" RESET);
break;
case Z_BUF_ERROR:
printf(RED "Output buffer was too small!\n" RESET);
break;
default:
INVALID_CASE;
}
always_assert(compressionResult == Z_OK);
ByteArray actualCompressedData(compressedBuffer.begin(), compressedBuffer.begin() + compressedSize);
always_assert(actualCompressedData.size() == compressedSize);
return actualCompressedData;
}
// Run-Length encode bytes and return compressed bytes. // Run-Length encode bytes and return compressed bytes.
std::vector<byte> rle_encode(const std::vector<byte> &bytes) std::vector<byte> rle_encode(const std::vector<byte> &bytes)
{ {
...@@ -264,4 +326,31 @@ void comp_test() ...@@ -264,4 +326,31 @@ void comp_test()
bool same = vecUtil::vector_eq(data, uncompressed); bool same = vecUtil::vector_eq(data, uncompressed);
always_assert(same && "Error in compression!"); always_assert(same && "Error in compression!");
} }
\ No newline at end of file
CompressionResult test_compression_method(const ByteArray &data, CompressionMethod method)
{
ByteArray compressedData;
switch (method)
{
case CompressionMethod_RLE:
compressedData = rle_encode(data);
break;
case CompressionMethod_LZ:
compressedData = lz_encode(data);
break;
case CompressionMethod_GZIP:
compressedData = gzip_encode(data);
break;
default:
INVALID_CASE;
}
CompressionResult result = {};
result.originalSize = data.size();
result.compressedSize = compressedData.size();
result.compressionRatio = compression_ratio((float)result.originalSize, (float)result.compressedSize);
result.percentageOfOriginalSize = ((float)result.compressedSize / (float)result.originalSize) * 100.0f;
return result;
}
...@@ -23,6 +23,8 @@ typedef unsigned long ulong; ...@@ -23,6 +23,8 @@ typedef unsigned long ulong;
#define TagType std::string, std::string #define TagType std::string, std::string
typedef std::pair<TagType> Tag; typedef std::pair<TagType> Tag;
typedef std::vector<byte> ByteArray;
// Terminal colors // Terminal colors
#define RESET "\033[0m" #define RESET "\033[0m"
#define RED "\033[31m" /* Red */ #define RED "\033[31m" /* Red */
......
...@@ -411,6 +411,7 @@ void CziFile::dump_image_data(const std::string &baseName) const ...@@ -411,6 +411,7 @@ void CziFile::dump_image_data(const std::string &baseName) const
void CziFile::test_compression(CompressionMethod method, bool verbose) const void CziFile::test_compression(CompressionMethod method, bool verbose) const
{ {
switch (method) switch (method)
{ {
case CompressionMethod_LZ: case CompressionMethod_LZ:
...@@ -419,71 +420,49 @@ void CziFile::test_compression(CompressionMethod method, bool verbose) const ...@@ -419,71 +420,49 @@ void CziFile::test_compression(CompressionMethod method, bool verbose) const
case CompressionMethod_RLE: case CompressionMethod_RLE:
printf("Selected compression: RLE\n"); printf("Selected compression: RLE\n");
break; break;
case CompressionMethod_GZIP:
printf("Selected compression: GZIP (zlib)\n");
break;
default: default:
INVALID_CASE; INVALID_CASE;
return; return;
} }
float dataSize, dataZSize, compressedDataSize, compressedDataZSize, ratio, ratioZ;
float overall = 0;
float overallZ = 0;
size_t totalSize = 0; CompressionResult overallN;
size_t totalRleSize = 0; CompressionResult overallZ;
size_t totalRleSizeZ = 0;
for (size_t i = 0; i < subBlockDirectory.entries.size(); i++) for (size_t i = 0; i < subBlockDirectory.entries.size(); i++)
{ {
auto data = get_image_data(i, false); auto data = get_image_data(i, false);
auto dataZ = get_image_data(i, true); auto dataZ = get_image_data(i, true);
std::vector<byte> compressedData; CompressionResult nResult = test_compression_method(data, method);
std::vector<byte> compressedDataZ; CompressionResult zResult = test_compression_method(dataZ, method);
switch (method) overallN.compressionRatio += nResult.compressionRatio;
{ overallZ.compressionRatio += zResult.compressionRatio;
case CompressionMethod_LZ:
{
compressedData = lz_encode(data);
compressedDataZ = lz_encode(dataZ);
}
break;
case CompressionMethod_RLE:
{
compressedData = rle_encode(data);
compressedDataZ = rle_encode(dataZ);
}
break;
default:
INVALID_CASE;
return;
}
dataSize = (float)data.size();
dataZSize = (float)dataZ.size();
compressedDataSize = (float)compressedData.size();
compressedDataZSize = (float)compressedDataZ.size();
ratio = compression_ratio(dataSize, compressedDataSize); overallN.originalSize += data.size();
ratioZ = compression_ratio(dataZSize, compressedDataZSize); overallN.compressedSize += nResult.compressedSize;
overallZ.compressedSize += zResult.compressedSize;
overall += ratio; overallN.percentageOfOriginalSize += nResult.percentageOfOriginalSize;
overallZ += ratioZ; overallZ.percentageOfOriginalSize += zResult.percentageOfOriginalSize;
totalSize += dataSize;
totalRleSize += compressedDataSize;
totalRleSizeZ += compressedDataZSize;
if (verbose) if (verbose)
{ {
if (ratio > 1 || ratioZ > 1) if (nResult.compressionRatio > 1.0f || zResult.compressionRatio > 1.0f)
printf("Subblock %-3i Compression ratios: Normal: %8f Z-Ordered: %8f\n", (int)i, ratio, ratioZ); printf("Subblock %-3i Compression ratios: Normal: %8f Z-Ordered: %8f; Size(N): %5.3f%%; Size(Z): %5.3f%%\n",
(int)i, nResult.compressionRatio, zResult.compressionRatio, nResult.percentageOfOriginalSize, zResult.percentageOfOriginalSize);
else else
printf("Subblock %-3i Compression ratios: Normal: %8f Z-Ordered: %8f\n", (int)i, ratio, ratioZ); printf(RED "Subblock %-3i Compression ratios: Normal: %8f Z-Ordered: %8f; Size(N): %5.3f%%; Size(Z): %5.3f%%\n" RESET, (int)i, nResult.compressionRatio, zResult.compressionRatio, nResult.percentageOfOriginalSize, zResult.percentageOfOriginalSize);
} }
} }
float dataCount = (float)subBlockDirectory.entries.size(); float dataCount = (float)subBlockDirectory.entries.size();
overall /= dataCount;
overallZ /= dataCount;
printf("Overall compression ratios: Normal %8f Z-Ordered: %8f\n", overall, overallZ); overallN.divide(dataCount);
printf("Original size: %8lu B Rle size: %8lu B RleZOrder size: %8lu B\n", totalSize, totalRleSize, totalRleSizeZ); overallZ.divide(dataCount);
printf("Overall compression ratios: Normal %8f Z-Ordered: %8f\n", overallN.compressionRatio, overallZ.compressionRatio);
printf("Original size: %8lu B Compressed size: %8lu B Compressed Z-Order size: %8lu B\n", overallN.originalSize, overallN.compressedSize, overallZ.compressedSize);
printf("Original size (%%): 100%% Compressed: %5.5f%% Compressed Z-Order: %5.5f%%\n", overallN.percentageOfOriginalSize, overallZ.percentageOfOriginalSize);
} }
\ No newline at end of file
...@@ -23,6 +23,7 @@ int main(int argc, char **argv) ...@@ -23,6 +23,7 @@ int main(int argc, char **argv)
args::Flag verboseOption(optionsGroup, "verbose", "Extend output of method", {'v', "verbose"}); args::Flag verboseOption(optionsGroup, "verbose", "Extend output of method", {'v', "verbose"});
args::Flag rleCompressionOption(compressionGroup, "RLE", "RLE compression", {"rle"}); args::Flag rleCompressionOption(compressionGroup, "RLE", "RLE compression", {"rle"});
args::Flag lzCompressionOption(compressionGroup, "LZ", "LZ compression", {"lz"}); args::Flag lzCompressionOption(compressionGroup, "LZ", "LZ compression", {"lz"});
args::Flag gzipCompressionOption(compressionGroup, "GZIP", "GZIP (zlib) compression", {"gzip"});
try try
{ {
...@@ -36,12 +37,12 @@ int main(int argc, char **argv) ...@@ -36,12 +37,12 @@ int main(int argc, char **argv)
} }
catch (args::ValidationError &e) catch (args::ValidationError &e)
{ {
printf(RED "%s\n" RESET, e.what()); printf(RED "%s Check help with -h or --help.\n" RESET, e.what());
return 1; return 1;
} }
catch (args::ParseError &pe) catch (args::ParseError &pe)
{ {
printf(RED "%s\n" RESET, pe.what()); printf(RED "%s Check help with -h or --help.\n" RESET, pe.what());
return 1; return 1;
} }
...@@ -55,6 +56,8 @@ int main(int argc, char **argv) ...@@ -55,6 +56,8 @@ int main(int argc, char **argv)
if (lzCompressionOption) if (lzCompressionOption)
cm = CompressionMethod_LZ; cm = CompressionMethod_LZ;
else if (gzipCompressionOption)
cm = CompressionMethod_GZIP;
parsedFile.test_compression(cm, verboseOption.Matched()); parsedFile.test_compression(cm, verboseOption.Matched());
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment