static SquashStatus squash_lz4_compress_buffer_unsafe (SquashCodec* codec, size_t* compressed_size, uint8_t compressed[SQUASH_ARRAY_PARAM(*compressed_size)], size_t uncompressed_size, const uint8_t uncompressed[SQUASH_ARRAY_PARAM(uncompressed_size)], SquashOptions* options) { int level = squash_codec_get_option_int_index (codec, options, SQUASH_LZ4_OPT_LEVEL); #if INT_MAX < SIZE_MAX if (SQUASH_UNLIKELY(INT_MAX < uncompressed_size) || SQUASH_UNLIKELY(INT_MAX < *compressed_size)) return squash_error (SQUASH_RANGE); #endif assert (*compressed_size >= LZ4_COMPRESSBOUND(uncompressed_size)); int lz4_r; if (level == 7) { lz4_r = LZ4_compress ((char*) uncompressed, (char*) compressed, (int) uncompressed_size); } else if (level < 7) { lz4_r = LZ4_compress_fast ((const char*) uncompressed, (char*) compressed, (int) uncompressed_size, (int) *compressed_size, squash_lz4_level_to_fast_mode (level)); } else { lz4_r = LZ4_compressHC2 ((char*) uncompressed, (char*) compressed, (int) uncompressed_size, squash_lz4_level_to_hc_level (level)); } #if SIZE_MAX < INT_MAX if (SQUASH_UNLIKELY(SIZE_MAX < lz4_r)) return squash_error (SQUASH_RANGE); #endif *compressed_size = lz4_r; return (lz4_r == 0) ? SQUASH_BUFFER_FULL : SQUASH_OK; }
size_t lz4Compress(std::shared_ptr<uint8_t> src, size_t uncompressedBytes, std::shared_ptr<uint8_t>& dst, uint32_t compressionLevel) { if (uncompressedBytes > size_t(LZ4_MAX_INPUT_SIZE)) throw std::runtime_error("Input data too big for LZ4 (max LZ4_MAX_INPUT_SIZE)"); int const inputSize = static_cast<int>(uncompressedBytes); int const upperBound = LZ4_compressBound(inputSize); if (upperBound < 0) throw std::runtime_error("Input data too big for LZ4 (max LZ4_MAX_INPUT_SIZE)"); dst.reset(new uint8_t[size_t(upperBound)], nonstd::DeleteArray<uint8_t>()); if (compressionLevel > 17) compressionLevel = 17; else if (compressionLevel < 1) compressionLevel = 1; int compressedBytes = 0; switch (compressionLevel) { case 1: compressedBytes = LZ4_compress((const char*)src.get(), (char*)dst.get(), inputSize); break; default: // compression level 0 is default mode which seems to equal level 9 and HC compressedBytes = LZ4_compressHC2((const char*)src.get(), (char*)dst.get(), inputSize, compressionLevel - 1); break; } assert(compressedBytes >= 0); if (compressedBytes <= 0) throw std::runtime_error(std::string("LZ4_compress[HC] failed, returned value: ") + SysTools::ToString(compressedBytes)); return compressedBytes; }
bool JobTicket::DoJob(const wxRect &rect) { unsigned char *bit_array[10]; for(int i=0 ; i < 10 ; i++) bit_array[i] = 0; wxRect ncrect(rect); bit_array[0] = level0_bits; level0_bits = NULL; if(!bit_array[0]) { // Grab a copy of the level0 chart bits // we could alternately subsample grabbing leveln chart bits // directly here to speed things up... ChartBase *pchart; int index; if(ChartData){ index = ChartData->FinddbIndex( m_ChartPath ); pchart = ChartData->OpenChartFromDBAndLock(index, FULL_INIT ); if(pchart && ChartData->IsChartLocked( index )){ ChartBaseBSB *pBSBChart = dynamic_cast<ChartBaseBSB*>( pchart ); if( pBSBChart ) { bit_array[0] = (unsigned char *) malloc( ncrect.width * ncrect.height * 4 ); pBSBChart->GetChartBits( ncrect, bit_array[0], 1 ); } ChartData->UnLockCacheChart(index); } else bit_array[0] = NULL; } } //OK, got the bits? int ssize, dim; if(!bit_array[0] ) return false; // Fill in the rest of the private uncompressed array dim = g_GLOptions.m_iTextureDimension; dim /= 2; for( int i = 1 ; i < g_mipmap_max_level+1 ; i++ ){ size_t nmalloc = wxMax(dim * dim * 3, 4*4*3); bit_array[i] = (unsigned char *) malloc( nmalloc ); MipMap_24( 2*dim, 2*dim, bit_array[i - 1], bit_array[i] ); dim /= 2; } int texture_level = 0; for( int level = level_min_request; level < g_mipmap_max_level+1 ; level++ ){ int dim = TextureDim(level); int size = TextureTileSize(level, true); unsigned char *tex_data = (unsigned char*)malloc(size); if(g_raster_format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT) { // color range fit is worse quality but twice as fast int flags = squish::kDxt1 | squish::kColourRangeFit; if( g_GLOptions.m_bTextureCompressionCaching) { /* use slower cluster fit since we are building the cache for * better quality, this takes roughly 25% longer and uses about * 10% more disk space (result doesn't compress as well with lz4) */ flags = squish::kDxt1 | squish::kColourClusterFit; } OCPNStopWatch sww; squish::CompressImageRGBpow2_Flatten_Throttle_Abort( bit_array[level], dim, dim, tex_data, flags, true, b_throttle ? throttle_func : 0, &sww, b_abort ); } else if(g_raster_format == GL_ETC1_RGB8_OES) CompressDataETC(bit_array[level], dim, size, tex_data, b_abort); else if(g_raster_format == GL_COMPRESSED_RGB_FXT1_3DFX) { if(!CompressUsingGPU(bit_array[level], dim, size, tex_data, texture_level, binplace)) { b_abort = true; break; } if(binplace) g_tex_mem_used += size; texture_level++; } comp_bits_array[level] = tex_data; if(b_abort){ for( int i = 0; i < g_mipmap_max_level+1; i++ ){ free( bit_array[i] ); bit_array[i] = 0; } return false; } } // All done with the uncompressed data in the thread for( int i = 0; i < g_mipmap_max_level+1; i++ ) { free( bit_array[i] ); bit_array[i] = 0; } if(b_throttle) wxThread::Sleep(1); if(b_abort) return false; if(bpost_zip_compress) { int max_compressed_size = LZ4_COMPRESSBOUND(g_tile_size); for(int level = level_min_request; level < g_mipmap_max_level+1 ; level++){ if(b_abort) return false; unsigned char *compressed_data = (unsigned char *)malloc(max_compressed_size); int csize = TextureTileSize(level, true); char *src = (char *)comp_bits_array[level]; int compressed_size = LZ4_compressHC2( src, (char *)compressed_data, csize, 4); // shrink buffer to actual size. // This will greatly reduce ram usage, ratio usually 10:1 // there might be a more efficient way than realloc... compressed_data = (unsigned char*)realloc(compressed_data, compressed_size); compcomp_bits_array[level] = compressed_data; compcomp_size_array[level] = compressed_size; } } return true; }