Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(103)

Side by Side Diff: third_party/libwebp/dec/vp8l.c

Issue 12942006: libwebp: update snapshot to v0.3.0-rc6 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: local webkit layout expectations Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2012 Google Inc. All Rights Reserved. 1 // Copyright 2012 Google Inc. All Rights Reserved.
2 // 2 //
3 // This code is licensed under the same terms as WebM: 3 // This code is licensed under the same terms as WebM:
4 // Software License Agreement: http://www.webmproject.org/license/software/ 4 // Software License Agreement: http://www.webmproject.org/license/software/
5 // Additional IP Rights Grant: http://www.webmproject.org/license/additional/ 5 // Additional IP Rights Grant: http://www.webmproject.org/license/additional/
6 // ----------------------------------------------------------------------------- 6 // -----------------------------------------------------------------------------
7 // 7 //
8 // main entry for the decoder 8 // main entry for the decoder
9 // 9 //
10 // Authors: Vikas Arora (vikaas.arora@gmail.com) 10 // Authors: Vikas Arora (vikaas.arora@gmail.com)
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
142 const int yoffset = dist_code >> 4; 142 const int yoffset = dist_code >> 4;
143 const int xoffset = 8 - (dist_code & 0xf); 143 const int xoffset = 8 - (dist_code & 0xf);
144 const int dist = yoffset * xsize + xoffset; 144 const int dist = yoffset * xsize + xoffset;
145 return (dist >= 1) ? dist : 1; 145 return (dist >= 1) ? dist : 1;
146 } 146 }
147 } 147 }
148 148
149 //------------------------------------------------------------------------------ 149 //------------------------------------------------------------------------------
150 // Decodes the next Huffman code from bit-stream. 150 // Decodes the next Huffman code from bit-stream.
151 // FillBitWindow(br) needs to be called at minimum every second call 151 // FillBitWindow(br) needs to be called at minimum every second call
152 // to ReadSymbolUnsafe. 152 // to ReadSymbol, in order to pre-fetch enough bits.
153 static int ReadSymbolUnsafe(const HuffmanTree* tree, VP8LBitReader* const br) { 153 static WEBP_INLINE int ReadSymbol(const HuffmanTree* tree,
154 VP8LBitReader* const br) {
154 const HuffmanTreeNode* node = tree->root_; 155 const HuffmanTreeNode* node = tree->root_;
156 int num_bits = 0;
157 uint32_t bits = VP8LPrefetchBits(br);
155 assert(node != NULL); 158 assert(node != NULL);
156 while (!HuffmanTreeNodeIsLeaf(node)) { 159 while (!HuffmanTreeNodeIsLeaf(node)) {
157 node = HuffmanTreeNextNode(node, VP8LReadOneBitUnsafe(br)); 160 node = HuffmanTreeNextNode(node, bits & 1);
161 bits >>= 1;
162 ++num_bits;
158 } 163 }
164 VP8LDiscardBits(br, num_bits);
159 return node->symbol_; 165 return node->symbol_;
160 } 166 }
161 167
162 static WEBP_INLINE int ReadSymbol(const HuffmanTree* tree,
163 VP8LBitReader* const br) {
164 const int read_safe = (br->pos_ + 8 > br->len_);
165 if (!read_safe) {
166 return ReadSymbolUnsafe(tree, br);
167 } else {
168 const HuffmanTreeNode* node = tree->root_;
169 assert(node != NULL);
170 while (!HuffmanTreeNodeIsLeaf(node)) {
171 node = HuffmanTreeNextNode(node, VP8LReadOneBit(br));
172 }
173 return node->symbol_;
174 }
175 }
176
177 static int ReadHuffmanCodeLengths( 168 static int ReadHuffmanCodeLengths(
178 VP8LDecoder* const dec, const int* const code_length_code_lengths, 169 VP8LDecoder* const dec, const int* const code_length_code_lengths,
179 int num_symbols, int* const code_lengths) { 170 int num_symbols, int* const code_lengths) {
180 int ok = 0; 171 int ok = 0;
181 VP8LBitReader* const br = &dec->br_; 172 VP8LBitReader* const br = &dec->br_;
182 int symbol; 173 int symbol;
183 int max_symbol; 174 int max_symbol;
184 int prev_code_len = DEFAULT_CODE_LENGTH; 175 int prev_code_len = DEFAULT_CODE_LENGTH;
185 HuffmanTree tree; 176 HuffmanTree tree;
186 177
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
320 const int huffman_ysize = VP8LSubSampleSize(ysize, huffman_precision); 311 const int huffman_ysize = VP8LSubSampleSize(ysize, huffman_precision);
321 const int huffman_pixs = huffman_xsize * huffman_ysize; 312 const int huffman_pixs = huffman_xsize * huffman_ysize;
322 if (!DecodeImageStream(huffman_xsize, huffman_ysize, 0, dec, 313 if (!DecodeImageStream(huffman_xsize, huffman_ysize, 0, dec,
323 &huffman_image)) { 314 &huffman_image)) {
324 dec->status_ = VP8_STATUS_BITSTREAM_ERROR; 315 dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
325 goto Error; 316 goto Error;
326 } 317 }
327 hdr->huffman_subsample_bits_ = huffman_precision; 318 hdr->huffman_subsample_bits_ = huffman_precision;
328 for (i = 0; i < huffman_pixs; ++i) { 319 for (i = 0; i < huffman_pixs; ++i) {
329 // The huffman data is stored in red and green bytes. 320 // The huffman data is stored in red and green bytes.
330 const int index = (huffman_image[i] >> 8) & 0xffff; 321 const int group = (huffman_image[i] >> 8) & 0xffff;
331 huffman_image[i] = index; 322 huffman_image[i] = group;
332 if (index >= num_htree_groups) { 323 if (group >= num_htree_groups) {
333 num_htree_groups = index + 1; 324 num_htree_groups = group + 1;
334 } 325 }
335 } 326 }
336 } 327 }
337 328
338 if (br->error_) goto Error; 329 if (br->error_) goto Error;
339 330
340 assert(num_htree_groups <= 0x10000); 331 assert(num_htree_groups <= 0x10000);
341 htree_groups = 332 htree_groups =
342 (HTreeGroup*)WebPSafeCalloc((uint64_t)num_htree_groups, 333 (HTreeGroup*)WebPSafeCalloc((uint64_t)num_htree_groups,
343 sizeof(*htree_groups)); 334 sizeof(*htree_groups));
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after
608 hdr->huffman_subsample_bits_, x, y); 599 hdr->huffman_subsample_bits_, x, y);
609 assert(meta_index < hdr->num_htree_groups_); 600 assert(meta_index < hdr->num_htree_groups_);
610 return hdr->htree_groups_ + meta_index; 601 return hdr->htree_groups_ + meta_index;
611 } 602 }
612 603
613 //------------------------------------------------------------------------------ 604 //------------------------------------------------------------------------------
614 // Main loop, with custom row-processing function 605 // Main loop, with custom row-processing function
615 606
616 typedef void (*ProcessRowsFunc)(VP8LDecoder* const dec, int row); 607 typedef void (*ProcessRowsFunc)(VP8LDecoder* const dec, int row);
617 608
618 static void ApplyTransforms(VP8LDecoder* const dec, int num_rows, 609 static void ApplyInverseTransforms(VP8LDecoder* const dec, int num_rows,
619 const uint32_t* const rows) { 610 const uint32_t* const rows) {
620 int n = dec->next_transform_; 611 int n = dec->next_transform_;
621 const int cache_pixs = dec->width_ * num_rows; 612 const int cache_pixs = dec->width_ * num_rows;
622 uint32_t* rows_data = dec->argb_cache_;
623 const int start_row = dec->last_row_; 613 const int start_row = dec->last_row_;
624 const int end_row = start_row + num_rows; 614 const int end_row = start_row + num_rows;
615 const uint32_t* rows_in = rows;
616 uint32_t* const rows_out = dec->argb_cache_;
625 617
626 // Inverse transforms. 618 // Inverse transforms.
627 // TODO: most transforms only need to operate on the cropped region only. 619 // TODO: most transforms only need to operate on the cropped region only.
628 memcpy(rows_data, rows, cache_pixs * sizeof(*rows_data)); 620 memcpy(rows_out, rows_in, cache_pixs * sizeof(*rows_out));
629 while (n-- > 0) { 621 while (n-- > 0) {
630 VP8LTransform* const transform = &dec->transforms_[n]; 622 VP8LTransform* const transform = &dec->transforms_[n];
631 VP8LInverseTransform(transform, start_row, end_row, rows, rows_data); 623 VP8LInverseTransform(transform, start_row, end_row, rows_in, rows_out);
624 rows_in = rows_out;
632 } 625 }
633 } 626 }
634 627
635 // Processes (transforms, scales & color-converts) the rows decoded after the 628 // Processes (transforms, scales & color-converts) the rows decoded after the
636 // last call. 629 // last call.
637 static void ProcessRows(VP8LDecoder* const dec, int row) { 630 static void ProcessRows(VP8LDecoder* const dec, int row) {
638 const uint32_t* const rows = dec->argb_ + dec->width_ * dec->last_row_; 631 const uint32_t* const rows = dec->argb_ + dec->width_ * dec->last_row_;
639 const int num_rows = row - dec->last_row_; 632 const int num_rows = row - dec->last_row_;
640 633
641 if (num_rows <= 0) return; // Nothing to be done. 634 if (num_rows <= 0) return; // Nothing to be done.
642 ApplyTransforms(dec, num_rows, rows); 635 ApplyInverseTransforms(dec, num_rows, rows);
643 636
644 // Emit output. 637 // Emit output.
645 { 638 {
646 VP8Io* const io = dec->io_; 639 VP8Io* const io = dec->io_;
647 const uint32_t* rows_data = dec->argb_cache_; 640 const uint32_t* rows_data = dec->argb_cache_;
648 if (!SetCropWindow(io, dec->last_row_, row, &rows_data, io->width)) { 641 if (!SetCropWindow(io, dec->last_row_, row, &rows_data, io->width)) {
649 // Nothing to output (this time). 642 // Nothing to output (this time).
650 } else { 643 } else {
651 const WebPDecBuffer* const output = dec->output_; 644 const WebPDecBuffer* const output = dec->output_;
652 const int in_stride = io->width * sizeof(*rows_data); 645 const int in_stride = io->width * sizeof(*rows_data);
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
790 } 783 }
791 784
792 // ----------------------------------------------------------------------------- 785 // -----------------------------------------------------------------------------
793 // VP8LTransform 786 // VP8LTransform
794 787
795 static void ClearTransform(VP8LTransform* const transform) { 788 static void ClearTransform(VP8LTransform* const transform) {
796 free(transform->data_); 789 free(transform->data_);
797 transform->data_ = NULL; 790 transform->data_ = NULL;
798 } 791 }
799 792
800 static void ApplyInverseTransforms(VP8LDecoder* const dec, int start_idx,
801 uint32_t* const decoded_data) {
802 int n = dec->next_transform_;
803 assert(start_idx >= 0);
804 while (n-- > start_idx) {
805 VP8LTransform* const transform = &dec->transforms_[n];
806 VP8LInverseTransform(transform, 0, transform->ysize_,
807 decoded_data, decoded_data);
808 ClearTransform(transform);
809 }
810 dec->next_transform_ = start_idx;
811 }
812
813 // For security reason, we need to remap the color map to span 793 // For security reason, we need to remap the color map to span
814 // the total possible bundled values, and not just the num_colors. 794 // the total possible bundled values, and not just the num_colors.
815 static int ExpandColorMap(int num_colors, VP8LTransform* const transform) { 795 static int ExpandColorMap(int num_colors, VP8LTransform* const transform) {
816 int i; 796 int i;
817 const int final_num_colors = 1 << (8 >> transform->bits_); 797 const int final_num_colors = 1 << (8 >> transform->bits_);
818 uint32_t* const new_color_map = 798 uint32_t* const new_color_map =
819 (uint32_t*)WebPSafeMalloc((uint64_t)final_num_colors, 799 (uint32_t*)WebPSafeMalloc((uint64_t)final_num_colors,
820 sizeof(*new_color_map)); 800 sizeof(*new_color_map));
821 if (new_color_map == NULL) { 801 if (new_color_map == NULL) {
822 return 0; 802 return 0;
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
956 936
957 static int DecodeImageStream(int xsize, int ysize, 937 static int DecodeImageStream(int xsize, int ysize,
958 int is_level0, 938 int is_level0,
959 VP8LDecoder* const dec, 939 VP8LDecoder* const dec,
960 uint32_t** const decoded_data) { 940 uint32_t** const decoded_data) {
961 int ok = 1; 941 int ok = 1;
962 int transform_xsize = xsize; 942 int transform_xsize = xsize;
963 int transform_ysize = ysize; 943 int transform_ysize = ysize;
964 VP8LBitReader* const br = &dec->br_; 944 VP8LBitReader* const br = &dec->br_;
965 VP8LMetadata* const hdr = &dec->hdr_; 945 VP8LMetadata* const hdr = &dec->hdr_;
966 uint32_t* data = NULL; 946 uint32_t* data = NULL;
fbarchard 2013/03/22 18:56:44 shouldnt we be using uint32* etc?
jzern 2013/03/22 19:10:36 no. we use posix types in this (C) project
967 const int transform_start_idx = dec->next_transform_;
968 int color_cache_bits = 0; 947 int color_cache_bits = 0;
969 948
970 // Read the transforms (may recurse). 949 // Read the transforms (may recurse).
971 if (is_level0) { 950 if (is_level0) {
972 while (ok && VP8LReadBits(br, 1)) { 951 while (ok && VP8LReadBits(br, 1)) {
973 ok = ReadTransform(&transform_xsize, &transform_ysize, dec); 952 ok = ReadTransform(&transform_xsize, &transform_ysize, dec);
974 } 953 }
975 } 954 }
976 955
977 // Color cache 956 // Color cache
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1017 dec->status_ = VP8_STATUS_OUT_OF_MEMORY; 996 dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
1018 ok = 0; 997 ok = 0;
1019 goto End; 998 goto End;
1020 } 999 }
1021 } 1000 }
1022 1001
1023 // Use the Huffman trees to decode the LZ77 encoded data. 1002 // Use the Huffman trees to decode the LZ77 encoded data.
1024 ok = DecodeImageData(dec, data, transform_xsize, transform_ysize, NULL); 1003 ok = DecodeImageData(dec, data, transform_xsize, transform_ysize, NULL);
1025 ok = ok && !br->error_; 1004 ok = ok && !br->error_;
1026 1005
1027 // Apply transforms on the decoded data.
1028 if (ok) ApplyInverseTransforms(dec, transform_start_idx, data);
1029
1030 End: 1006 End:
1031 1007
1032 if (!ok) { 1008 if (!ok) {
1033 free(data); 1009 free(data);
1034 ClearMetadata(hdr); 1010 ClearMetadata(hdr);
1035 // If not enough data (br.eos_) resulted in BIT_STREAM_ERROR, update the 1011 // If not enough data (br.eos_) resulted in BIT_STREAM_ERROR, update the
1036 // status appropriately. 1012 // status appropriately.
1037 if (dec->status_ == VP8_STATUS_BITSTREAM_ERROR && dec->br_.eos_) { 1013 if (dec->status_ == VP8_STATUS_BITSTREAM_ERROR && dec->br_.eos_) {
1038 dec->status_ = VP8_STATUS_SUSPENDED; 1014 dec->status_ = VP8_STATUS_SUSPENDED;
1039 } 1015 }
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1076 } 1052 }
1077 1053
1078 //------------------------------------------------------------------------------ 1054 //------------------------------------------------------------------------------
1079 // Special row-processing that only stores the alpha data. 1055 // Special row-processing that only stores the alpha data.
1080 1056
1081 static void ExtractAlphaRows(VP8LDecoder* const dec, int row) { 1057 static void ExtractAlphaRows(VP8LDecoder* const dec, int row) {
1082 const int num_rows = row - dec->last_row_; 1058 const int num_rows = row - dec->last_row_;
1083 const uint32_t* const in = dec->argb_ + dec->width_ * dec->last_row_; 1059 const uint32_t* const in = dec->argb_ + dec->width_ * dec->last_row_;
1084 1060
1085 if (num_rows <= 0) return; // Nothing to be done. 1061 if (num_rows <= 0) return; // Nothing to be done.
1086 ApplyTransforms(dec, num_rows, in); 1062 ApplyInverseTransforms(dec, num_rows, in);
1087 1063
1088 // Extract alpha (which is stored in the green plane). 1064 // Extract alpha (which is stored in the green plane).
1089 { 1065 {
1090 const int width = dec->io_->width; // the final width (!= dec->width_) 1066 const int width = dec->io_->width; // the final width (!= dec->width_)
1091 const int cache_pixs = width * num_rows; 1067 const int cache_pixs = width * num_rows;
1092 uint8_t* const dst = (uint8_t*)dec->io_->opaque + width * dec->last_row_; 1068 uint8_t* const dst = (uint8_t*)dec->io_->opaque + width * dec->last_row_;
1093 const uint32_t* const src = dec->argb_cache_; 1069 const uint32_t* const src = dec->argb_cache_;
1094 int i; 1070 int i;
1095 for (i = 0; i < cache_pixs; ++i) dst[i] = (src[i] >> 8) & 0xff; 1071 for (i = 0; i < cache_pixs; ++i) dst[i] = (src[i] >> 8) & 0xff;
1096 } 1072 }
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
1206 VP8LClear(dec); 1182 VP8LClear(dec);
1207 assert(dec->status_ != VP8_STATUS_OK); 1183 assert(dec->status_ != VP8_STATUS_OK);
1208 return 0; 1184 return 0;
1209 } 1185 }
1210 1186
1211 //------------------------------------------------------------------------------ 1187 //------------------------------------------------------------------------------
1212 1188
1213 #if defined(__cplusplus) || defined(c_plusplus) 1189 #if defined(__cplusplus) || defined(c_plusplus)
1214 } // extern "C" 1190 } // extern "C"
1215 #endif 1191 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698