/* Copyright (C) 2009 Red Hat, Inc. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, see . */ #ifdef HAVE_CONFIG_H #include #endif #define SHORT_PIX_IMAGE_DIST_LEVEL_1 64 //(1 << 6) #define SHORT_PIX_IMAGE_DIST_LEVEL_2 16384 // (1 << 14) #define SHORT_PIX_IMAGE_DIST_LEVEL_3 4194304 // (1 << 22) #define FAR_PIX_IMAGE_DIST_LEVEL_1 256 // (1 << 8) #define FAR_PIX_IMAGE_DIST_LEVEL_2 65536 // (1 << 16) #define FAR_PIX_IMAGE_DIST_LEVEL_3 16777216 // (1 << 24) /* if image_distance = 0, pixel_distance is the distance between the matching pixels. Otherwise, it is the offset from the beginning of the referred image */ #if defined(GLZ_ENCODE_MATCH) /* actually performing the encoding */ static inline void encode_match(Encoder *encoder, uint32_t image_distance, size_t pixel_distance, size_t len) #elif defined(GLZ_ENCODE_SIZE) /* compute the size of the encoding except for the match length*/ static inline int get_encode_ref_size(uint32_t image_distance, size_t pixel_distance) #endif { #if defined(GLZ_ENCODE_SIZE) int encode_size; #endif #if defined(GLZ_ENCODE_MATCH) /* encoding the match length + Long/Short dist bit + 12 LSB pixels of pixel_distance*/ if (len < 7) { if (pixel_distance < MAX_PIXEL_SHORT_DISTANCE) { encode(encoder, (uint8_t)((len << 5) + (pixel_distance & 0x0f))); } else { encode(encoder, (uint8_t)((len << 5) + 16 + (pixel_distance & 0x0f))); } encode(encoder, (uint8_t)((pixel_distance >> 4) & 255)); } else { if (pixel_distance < MAX_PIXEL_SHORT_DISTANCE) { encode(encoder, (uint8_t)((7 << 5) + (pixel_distance & 0x0f))); } else { encode(encoder, (uint8_t)((7 << 5) + 16 + (pixel_distance & 0x0f))); } for (len -= 7; len >= 255; len -= 255) { encode(encoder, 255); } encode(encoder, (uint8_t)len); encode(encoder, (uint8_t)((pixel_distance >> 4) & 255)); } #endif /* encoding the rest of the pixel distance and the image_dist and its 2 control bits */ /* The first 2 MSB bits indicate how many more bytes should be read for image dist */ if (pixel_distance < MAX_PIXEL_SHORT_DISTANCE) { if (image_distance < SHORT_PIX_IMAGE_DIST_LEVEL_1) { #if defined(GLZ_ENCODE_MATCH) encode(encoder, (uint8_t)(image_distance & 0x3f)); #elif defined(GLZ_ENCODE_SIZE) encode_size = 3; #endif } else if (image_distance < SHORT_PIX_IMAGE_DIST_LEVEL_2) { #if defined(GLZ_ENCODE_MATCH) encode(encoder, (uint8_t)((1 << 6) + (image_distance & 0x3f))); encode(encoder, (uint8_t)((image_distance >> 6) & 255)); #elif defined(GLZ_ENCODE_SIZE) encode_size = 4; #endif } else if (image_distance < SHORT_PIX_IMAGE_DIST_LEVEL_3) { #if defined(GLZ_ENCODE_MATCH) encode(encoder, (uint8_t)((1 << 7) + (image_distance & 0x3f))); encode(encoder, (uint8_t)((image_distance >> 6) & 255)); encode(encoder, (uint8_t)((image_distance >> 14) & 255)); #elif defined(GLZ_ENCODE_SIZE) encode_size = 5; #endif } else { #if defined(GLZ_ENCODE_MATCH) encode(encoder, (uint8_t)((1 << 7) + (1 << 6) + (image_distance & 0x3f))); encode(encoder, (uint8_t)((image_distance >> 6) & 255)); encode(encoder, (uint8_t)((image_distance >> 14) & 255)); encode(encoder, (uint8_t)((image_distance >> 22) & 255)); #elif defined(GLZ_ENCODE_SIZE) encode_size = 6; #endif } } else { /* the third MSB bit indicates if the pixel_distance is medium/long*/ uint8_t long_dist_control = (pixel_distance < MAX_PIXEL_MEDIUM_DISTANCE) ? 0 : 32; if (image_distance == 0) { #if defined(GLZ_ENCODE_MATCH) encode(encoder, (uint8_t)(long_dist_control + ((pixel_distance >> 12) & 31))); #elif defined(GLZ_ENCODE_SIZE) encode_size = 3; #endif } else if (image_distance < FAR_PIX_IMAGE_DIST_LEVEL_1) { #if defined(GLZ_ENCODE_MATCH) encode(encoder, (uint8_t)(long_dist_control + (1 << 6) + ((pixel_distance >> 12) & 31))); encode(encoder, (uint8_t)(image_distance & 255)); #elif defined(GLZ_ENCODE_SIZE) encode_size = 4; #endif } else if (image_distance < FAR_PIX_IMAGE_DIST_LEVEL_2) { #if defined(GLZ_ENCODE_MATCH) encode(encoder, (uint8_t)(long_dist_control + (1 << 7) + ((pixel_distance >> 12) & 31))); encode(encoder, (uint8_t)(image_distance & 255)); encode(encoder, (uint8_t)((image_distance >> 8) & 255)); #elif defined(GLZ_ENCODE_SIZE) encode_size = 5; #endif } else { #if defined(GLZ_ENCODE_MATCH) encode(encoder, (uint8_t)(long_dist_control + (1 << 7) + (1 << 6) + ((pixel_distance >> 12) & 31))); encode(encoder, (uint8_t)(image_distance & 255)); encode(encoder, (uint8_t)((image_distance >> 8) & 255)); encode(encoder, (uint8_t)((image_distance >> 16) & 255)); #elif defined(GLZ_ENCODE_SIZE) encode_size = 6; #endif } if (long_dist_control) { #if defined(GLZ_ENCODE_MATCH) encode(encoder, (uint8_t)((pixel_distance >> 17) & 255)); #elif defined(GLZ_ENCODE_SIZE) encode_size++; #endif } } #if defined(GLZ_ENCODE_SIZE) return encode_size; #endif } #undef GLZ_ENCODE_SIZE #undef GLZ_ENCODE_MATCH