Module: Applitools::Utils::ImageDeltaCompressor
- Extended by:
- ImageDeltaCompressor
- Included in:
- ImageDeltaCompressor
- Defined in:
- lib/applitools/utils/image_delta_compressor.rb
Defined Under Namespace
Classes: CompareAndCopyBlockChannelDataResult, Dimension
Constant Summary collapse
- BLOCK_SIZE =
10
Instance Method Summary collapse
-
#compress_by_raw_blocks(target, target_encoded, source, block_size = BLOCK_SIZE) ⇒ Object
Compresses the target image based on the source image.
Instance Method Details
#compress_by_raw_blocks(target, target_encoded, source, block_size = BLOCK_SIZE) ⇒ Object
Compresses the target image based on the source image.
target
-
ChunkyPNG::Canvas
The image to compress based on the source image. target_encoded
-
Array
The uncompressed image as binary string. source
-
ChunkyPNG::Canvas
The source image used as a base for compressing the target image. block_size
-
Integer
The width/height of each block.
Returns String
The binary result (either the compressed image, or the uncompressed image if the compression is greater in length).
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/applitools/utils/image_delta_compressor.rb', line 18 def compress_by_raw_blocks(target, target_encoded, source, block_size = BLOCK_SIZE) # If we can't compress for any reason, return the target image as is. if source.nil? || (source.height != target.height) || (source.width != target.width) # Returning a COPY of the target binary string. return String.new(target_encoded) end # Preparing the variables we need. target_pixels = target.to_rgb_stream.unpack('C*') source_pixels = source.to_rgb_stream.unpack('C*') image_size = Dimension.new(target.width, target.height) block_columns_count = (target.width / block_size) + ((target.width % block_size).zero? ? 0 : 1) block_rows_count = (target.height / block_size) + ((target.height % block_size).zero? ? 0 : 1) # IMPORTANT: The "-Zlib::MAX_WBITS" tells ZLib to create raw deflate compression, without the # "Zlib headers" (this isn't documented in the Zlib page, I found this in some internet forum). compressor = Zlib::Deflate.new(Zlib::BEST_COMPRESSION, -Zlib::MAX_WBITS) compression_result = '' # Writing the data header. compression_result += PREAMBLE.encode('UTF-8') compression_result += [FORMAT_RAW_BLOCKS].pack('C') compression_result += [0].pack('S>') # Source id, Big Endian compression_result += [block_size].pack('S>') # Big Endian # We perform the compression for each channel. 3.times do |channel| block_number = 0 block_rows_count.times do |block_row| block_columns_count.times do |block_column| actual_channel_index = 2 - channel # Since the image bytes are BGR and the server expects RGB... compare_result = compare_and_copy_block_channel_data(source_pixels, target_pixels, image_size, 3, block_size, block_column, block_row, actual_channel_index) unless compare_result.identical channel_bytes = compare_result.channel_bytes string_to_compress = [channel].pack('C') string_to_compress += [block_number].pack('L>') string_to_compress += channel_bytes.pack('C*') compression_result += compressor.deflate(string_to_compress) # If the compressed data so far is greater than the uncompressed representation of the target, just return # the target. if compression_result.length > target_encoded.length compressor.finish compressor.close # Returning a copy of the target bytes. return String.new(target_encoded) end end block_number += 1 end end end # Compress and flush any remaining uncompressed data in the input buffer. compression_result += compressor.finish compressor.close # Returning the compressed result as a byte array. compression_result end |