| OLD | NEW |
| 1 // Copyright 2012 Google Inc. All Rights Reserved. | 1 // Copyright 2012 Google Inc. All Rights Reserved. |
| 2 // | 2 // |
| 3 // Use of this source code is governed by a BSD-style license | 3 // Use of this source code is governed by a BSD-style license |
| 4 // that can be found in the COPYING file in the root of the source | 4 // that can be found in the COPYING file in the root of the source |
| 5 // tree. An additional intellectual property rights grant can be found | 5 // tree. An additional intellectual property rights grant can be found |
| 6 // in the file PATENTS. All contributing project authors may | 6 // in the file PATENTS. All contributing project authors may |
| 7 // be found in the AUTHORS file in the root of the source tree. | 7 // be found in the AUTHORS file in the root of the source tree. |
| 8 // ----------------------------------------------------------------------------- | 8 // ----------------------------------------------------------------------------- |
| 9 // | 9 // |
| 10 // main entry for the decoder | 10 // main entry for the decoder |
| (...skipping 696 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 707 // Inverse transforms. | 707 // Inverse transforms. |
| 708 // TODO: most transforms only need to operate on the cropped region only. | 708 // TODO: most transforms only need to operate on the cropped region only. |
| 709 memcpy(rows_out, rows_in, cache_pixs * sizeof(*rows_out)); | 709 memcpy(rows_out, rows_in, cache_pixs * sizeof(*rows_out)); |
| 710 while (n-- > 0) { | 710 while (n-- > 0) { |
| 711 VP8LTransform* const transform = &dec->transforms_[n]; | 711 VP8LTransform* const transform = &dec->transforms_[n]; |
| 712 VP8LInverseTransform(transform, start_row, end_row, rows_in, rows_out); | 712 VP8LInverseTransform(transform, start_row, end_row, rows_in, rows_out); |
| 713 rows_in = rows_out; | 713 rows_in = rows_out; |
| 714 } | 714 } |
| 715 } | 715 } |
| 716 | 716 |
| 717 // Special method for paletted alpha data. | |
| 718 static void ApplyInverseTransformsAlpha(VP8LDecoder* const dec, int num_rows, | |
| 719 const uint8_t* const rows) { | |
| 720 const int start_row = dec->last_row_; | |
| 721 const int end_row = start_row + num_rows; | |
| 722 const uint8_t* rows_in = rows; | |
| 723 uint8_t* rows_out = (uint8_t*)dec->io_->opaque + dec->io_->width * start_row; | |
| 724 VP8LTransform* const transform = &dec->transforms_[0]; | |
| 725 assert(dec->next_transform_ == 1); | |
| 726 assert(transform->type_ == COLOR_INDEXING_TRANSFORM); | |
| 727 VP8LColorIndexInverseTransformAlpha(transform, start_row, end_row, rows_in, | |
| 728 rows_out); | |
| 729 } | |
| 730 | |
| 731 // Processes (transforms, scales & color-converts) the rows decoded after the | 717 // Processes (transforms, scales & color-converts) the rows decoded after the |
| 732 // last call. | 718 // last call. |
| 733 static void ProcessRows(VP8LDecoder* const dec, int row) { | 719 static void ProcessRows(VP8LDecoder* const dec, int row) { |
| 734 const uint32_t* const rows = dec->pixels_ + dec->width_ * dec->last_row_; | 720 const uint32_t* const rows = dec->pixels_ + dec->width_ * dec->last_row_; |
| 735 const int num_rows = row - dec->last_row_; | 721 const int num_rows = row - dec->last_row_; |
| 736 | 722 |
| 737 if (num_rows <= 0) return; // Nothing to be done. | 723 assert(row <= dec->io_->crop_bottom); |
| 738 ApplyInverseTransforms(dec, num_rows, rows); | 724 // We can't process more than NUM_ARGB_CACHE_ROWS at a time (that's the size |
| 739 | 725 // of argb_cache_), but we currently don't need more than that. |
| 740 // Emit output. | 726 assert(num_rows <= NUM_ARGB_CACHE_ROWS); |
| 741 { | 727 if (num_rows > 0) { // Emit output. |
| 742 VP8Io* const io = dec->io_; | 728 VP8Io* const io = dec->io_; |
| 743 uint8_t* rows_data = (uint8_t*)dec->argb_cache_; | 729 uint8_t* rows_data = (uint8_t*)dec->argb_cache_; |
| 744 const int in_stride = io->width * sizeof(uint32_t); // in unit of RGBA | 730 const int in_stride = io->width * sizeof(uint32_t); // in unit of RGBA |
| 731 |
| 732 ApplyInverseTransforms(dec, num_rows, rows); |
| 745 if (!SetCropWindow(io, dec->last_row_, row, &rows_data, in_stride)) { | 733 if (!SetCropWindow(io, dec->last_row_, row, &rows_data, in_stride)) { |
| 746 // Nothing to output (this time). | 734 // Nothing to output (this time). |
| 747 } else { | 735 } else { |
| 748 const WebPDecBuffer* const output = dec->output_; | 736 const WebPDecBuffer* const output = dec->output_; |
| 749 if (WebPIsRGBMode(output->colorspace)) { // convert to RGBA | 737 if (WebPIsRGBMode(output->colorspace)) { // convert to RGBA |
| 750 const WebPRGBABuffer* const buf = &output->u.RGBA; | 738 const WebPRGBABuffer* const buf = &output->u.RGBA; |
| 751 uint8_t* const rgba = buf->rgba + dec->last_out_row_ * buf->stride; | 739 uint8_t* const rgba = buf->rgba + dec->last_out_row_ * buf->stride; |
| 752 const int num_rows_out = io->use_scaling ? | 740 const int num_rows_out = io->use_scaling ? |
| 753 EmitRescaledRowsRGBA(dec, rows_data, in_stride, io->mb_h, | 741 EmitRescaledRowsRGBA(dec, rows_data, in_stride, io->mb_h, |
| 754 rgba, buf->stride) : | 742 rgba, buf->stride) : |
| (...skipping 24 matching lines...) Expand all Loading... |
| 779 // call to ReadSymbol() for red/blue/alpha channels. | 767 // call to ReadSymbol() for red/blue/alpha channels. |
| 780 for (i = 0; i < hdr->num_htree_groups_; ++i) { | 768 for (i = 0; i < hdr->num_htree_groups_; ++i) { |
| 781 HuffmanCode** const htrees = hdr->htree_groups_[i].htrees; | 769 HuffmanCode** const htrees = hdr->htree_groups_[i].htrees; |
| 782 if (htrees[RED][0].bits > 0) return 0; | 770 if (htrees[RED][0].bits > 0) return 0; |
| 783 if (htrees[BLUE][0].bits > 0) return 0; | 771 if (htrees[BLUE][0].bits > 0) return 0; |
| 784 if (htrees[ALPHA][0].bits > 0) return 0; | 772 if (htrees[ALPHA][0].bits > 0) return 0; |
| 785 } | 773 } |
| 786 return 1; | 774 return 1; |
| 787 } | 775 } |
| 788 | 776 |
| 789 static void ExtractPalettedAlphaRows(VP8LDecoder* const dec, int row) { | 777 static void AlphaApplyFilter(ALPHDecoder* const alph_dec, |
| 790 const int num_rows = row - dec->last_row_; | 778 int first_row, int last_row, |
| 791 const uint8_t* const in = | 779 uint8_t* out, int stride) { |
| 792 (uint8_t*)dec->pixels_ + dec->width_ * dec->last_row_; | 780 if (alph_dec->filter_ != WEBP_FILTER_NONE) { |
| 793 if (num_rows > 0) { | 781 int y; |
| 794 ApplyInverseTransformsAlpha(dec, num_rows, in); | 782 const uint8_t* prev_line = alph_dec->prev_line_; |
| 783 assert(WebPUnfilters[alph_dec->filter_] != NULL); |
| 784 for (y = first_row; y < last_row; ++y) { |
| 785 WebPUnfilters[alph_dec->filter_](prev_line, out, out, stride); |
| 786 prev_line = out; |
| 787 out += stride; |
| 788 } |
| 789 alph_dec->prev_line_ = prev_line; |
| 795 } | 790 } |
| 796 dec->last_row_ = dec->last_out_row_ = row; | 791 } |
| 792 |
| 793 static void ExtractPalettedAlphaRows(VP8LDecoder* const dec, int last_row) { |
| 794 // For vertical and gradient filtering, we need to decode the part above the |
| 795 // crop_top row, in order to have the correct spatial predictors. |
| 796 ALPHDecoder* const alph_dec = (ALPHDecoder*)dec->io_->opaque; |
| 797 const int top_row = |
| 798 (alph_dec->filter_ == WEBP_FILTER_NONE || |
| 799 alph_dec->filter_ == WEBP_FILTER_HORIZONTAL) ? dec->io_->crop_top |
| 800 : dec->last_row_; |
| 801 const int first_row = (dec->last_row_ < top_row) ? top_row : dec->last_row_; |
| 802 assert(last_row <= dec->io_->crop_bottom); |
| 803 if (last_row > first_row) { |
| 804 // Special method for paletted alpha data. We only process the cropped area. |
| 805 const int width = dec->io_->width; |
| 806 uint8_t* out = alph_dec->output_ + width * first_row; |
| 807 const uint8_t* const in = |
| 808 (uint8_t*)dec->pixels_ + dec->width_ * first_row; |
| 809 VP8LTransform* const transform = &dec->transforms_[0]; |
| 810 assert(dec->next_transform_ == 1); |
| 811 assert(transform->type_ == COLOR_INDEXING_TRANSFORM); |
| 812 VP8LColorIndexInverseTransformAlpha(transform, first_row, last_row, |
| 813 in, out); |
| 814 AlphaApplyFilter(alph_dec, first_row, last_row, out, width); |
| 815 } |
| 816 dec->last_row_ = dec->last_out_row_ = last_row; |
| 797 } | 817 } |
| 798 | 818 |
| 799 //------------------------------------------------------------------------------ | 819 //------------------------------------------------------------------------------ |
| 800 // Helper functions for fast pattern copy (8b and 32b) | 820 // Helper functions for fast pattern copy (8b and 32b) |
| 801 | 821 |
| 802 // cyclic rotation of pattern word | 822 // cyclic rotation of pattern word |
| 803 static WEBP_INLINE uint32_t Rotate8b(uint32_t V) { | 823 static WEBP_INLINE uint32_t Rotate8b(uint32_t V) { |
| 804 #if defined(WORDS_BIGENDIAN) | 824 #if defined(WORDS_BIGENDIAN) |
| 805 return ((V & 0xff000000u) >> 24) | (V << 8); | 825 return ((V & 0xff000000u) >> 24) | (V << 8); |
| 806 #else | 826 #else |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 915 | 935 |
| 916 //------------------------------------------------------------------------------ | 936 //------------------------------------------------------------------------------ |
| 917 | 937 |
| 918 static int DecodeAlphaData(VP8LDecoder* const dec, uint8_t* const data, | 938 static int DecodeAlphaData(VP8LDecoder* const dec, uint8_t* const data, |
| 919 int width, int height, int last_row) { | 939 int width, int height, int last_row) { |
| 920 int ok = 1; | 940 int ok = 1; |
| 921 int row = dec->last_pixel_ / width; | 941 int row = dec->last_pixel_ / width; |
| 922 int col = dec->last_pixel_ % width; | 942 int col = dec->last_pixel_ % width; |
| 923 VP8LBitReader* const br = &dec->br_; | 943 VP8LBitReader* const br = &dec->br_; |
| 924 VP8LMetadata* const hdr = &dec->hdr_; | 944 VP8LMetadata* const hdr = &dec->hdr_; |
| 925 const HTreeGroup* htree_group = GetHtreeGroupForPos(hdr, col, row); | |
| 926 int pos = dec->last_pixel_; // current position | 945 int pos = dec->last_pixel_; // current position |
| 927 const int end = width * height; // End of data | 946 const int end = width * height; // End of data |
| 928 const int last = width * last_row; // Last pixel to decode | 947 const int last = width * last_row; // Last pixel to decode |
| 929 const int len_code_limit = NUM_LITERAL_CODES + NUM_LENGTH_CODES; | 948 const int len_code_limit = NUM_LITERAL_CODES + NUM_LENGTH_CODES; |
| 930 const int mask = hdr->huffman_mask_; | 949 const int mask = hdr->huffman_mask_; |
| 931 assert(htree_group != NULL); | 950 const HTreeGroup* htree_group = |
| 932 assert(pos < end); | 951 (pos < last) ? GetHtreeGroupForPos(hdr, col, row) : NULL; |
| 952 assert(pos <= end); |
| 933 assert(last_row <= height); | 953 assert(last_row <= height); |
| 934 assert(Is8bOptimizable(hdr)); | 954 assert(Is8bOptimizable(hdr)); |
| 935 | 955 |
| 936 while (!br->eos_ && pos < last) { | 956 while (!br->eos_ && pos < last) { |
| 937 int code; | 957 int code; |
| 938 // Only update when changing tile. | 958 // Only update when changing tile. |
| 939 if ((col & mask) == 0) { | 959 if ((col & mask) == 0) { |
| 940 htree_group = GetHtreeGroupForPos(hdr, col, row); | 960 htree_group = GetHtreeGroupForPos(hdr, col, row); |
| 941 } | 961 } |
| 962 assert(htree_group != NULL); |
| 942 VP8LFillBitWindow(br); | 963 VP8LFillBitWindow(br); |
| 943 code = ReadSymbol(htree_group->htrees[GREEN], br); | 964 code = ReadSymbol(htree_group->htrees[GREEN], br); |
| 944 if (code < NUM_LITERAL_CODES) { // Literal | 965 if (code < NUM_LITERAL_CODES) { // Literal |
| 945 data[pos] = code; | 966 data[pos] = code; |
| 946 ++pos; | 967 ++pos; |
| 947 ++col; | 968 ++col; |
| 948 if (col >= width) { | 969 if (col >= width) { |
| 949 col = 0; | 970 col = 0; |
| 950 ++row; | 971 ++row; |
| 951 if (row % NUM_ARGB_CACHE_ROWS == 0) { | 972 if (row <= last_row && (row % NUM_ARGB_CACHE_ROWS == 0)) { |
| 952 ExtractPalettedAlphaRows(dec, row); | 973 ExtractPalettedAlphaRows(dec, row); |
| 953 } | 974 } |
| 954 } | 975 } |
| 955 } else if (code < len_code_limit) { // Backward reference | 976 } else if (code < len_code_limit) { // Backward reference |
| 956 int dist_code, dist; | 977 int dist_code, dist; |
| 957 const int length_sym = code - NUM_LITERAL_CODES; | 978 const int length_sym = code - NUM_LITERAL_CODES; |
| 958 const int length = GetCopyLength(length_sym, br); | 979 const int length = GetCopyLength(length_sym, br); |
| 959 const int dist_symbol = ReadSymbol(htree_group->htrees[DIST], br); | 980 const int dist_symbol = ReadSymbol(htree_group->htrees[DIST], br); |
| 960 VP8LFillBitWindow(br); | 981 VP8LFillBitWindow(br); |
| 961 dist_code = GetCopyDistance(dist_symbol, br); | 982 dist_code = GetCopyDistance(dist_symbol, br); |
| 962 dist = PlaneCodeToDistance(width, dist_code); | 983 dist = PlaneCodeToDistance(width, dist_code); |
| 963 if (pos >= dist && end - pos >= length) { | 984 if (pos >= dist && end - pos >= length) { |
| 964 CopyBlock8b(data + pos, dist, length); | 985 CopyBlock8b(data + pos, dist, length); |
| 965 } else { | 986 } else { |
| 966 ok = 0; | 987 ok = 0; |
| 967 goto End; | 988 goto End; |
| 968 } | 989 } |
| 969 pos += length; | 990 pos += length; |
| 970 col += length; | 991 col += length; |
| 971 while (col >= width) { | 992 while (col >= width) { |
| 972 col -= width; | 993 col -= width; |
| 973 ++row; | 994 ++row; |
| 974 if (row % NUM_ARGB_CACHE_ROWS == 0) { | 995 if (row <= last_row && (row % NUM_ARGB_CACHE_ROWS == 0)) { |
| 975 ExtractPalettedAlphaRows(dec, row); | 996 ExtractPalettedAlphaRows(dec, row); |
| 976 } | 997 } |
| 977 } | 998 } |
| 978 if (pos < last && (col & mask)) { | 999 if (pos < last && (col & mask)) { |
| 979 htree_group = GetHtreeGroupForPos(hdr, col, row); | 1000 htree_group = GetHtreeGroupForPos(hdr, col, row); |
| 980 } | 1001 } |
| 981 } else { // Not reached | 1002 } else { // Not reached |
| 982 ok = 0; | 1003 ok = 0; |
| 983 goto End; | 1004 goto End; |
| 984 } | 1005 } |
| 985 assert(br->eos_ == VP8LIsEndOfStream(br)); | 1006 assert(br->eos_ == VP8LIsEndOfStream(br)); |
| 986 } | 1007 } |
| 987 // Process the remaining rows corresponding to last row-block. | 1008 // Process the remaining rows corresponding to last row-block. |
| 988 ExtractPalettedAlphaRows(dec, row); | 1009 ExtractPalettedAlphaRows(dec, row > last_row ? last_row : row); |
| 989 | 1010 |
| 990 End: | 1011 End: |
| 991 if (!ok || (br->eos_ && pos < end)) { | 1012 if (!ok || (br->eos_ && pos < end)) { |
| 992 ok = 0; | 1013 ok = 0; |
| 993 dec->status_ = br->eos_ ? VP8_STATUS_SUSPENDED | 1014 dec->status_ = br->eos_ ? VP8_STATUS_SUSPENDED |
| 994 : VP8_STATUS_BITSTREAM_ERROR; | 1015 : VP8_STATUS_BITSTREAM_ERROR; |
| 995 } else { | 1016 } else { |
| 996 dec->last_pixel_ = pos; | 1017 dec->last_pixel_ = pos; |
| 997 } | 1018 } |
| 998 return ok; | 1019 return ok; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1018 } | 1039 } |
| 1019 | 1040 |
| 1020 #define SYNC_EVERY_N_ROWS 8 // minimum number of rows between check-points | 1041 #define SYNC_EVERY_N_ROWS 8 // minimum number of rows between check-points |
| 1021 static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data, | 1042 static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data, |
| 1022 int width, int height, int last_row, | 1043 int width, int height, int last_row, |
| 1023 ProcessRowsFunc process_func) { | 1044 ProcessRowsFunc process_func) { |
| 1024 int row = dec->last_pixel_ / width; | 1045 int row = dec->last_pixel_ / width; |
| 1025 int col = dec->last_pixel_ % width; | 1046 int col = dec->last_pixel_ % width; |
| 1026 VP8LBitReader* const br = &dec->br_; | 1047 VP8LBitReader* const br = &dec->br_; |
| 1027 VP8LMetadata* const hdr = &dec->hdr_; | 1048 VP8LMetadata* const hdr = &dec->hdr_; |
| 1028 HTreeGroup* htree_group = GetHtreeGroupForPos(hdr, col, row); | |
| 1029 uint32_t* src = data + dec->last_pixel_; | 1049 uint32_t* src = data + dec->last_pixel_; |
| 1030 uint32_t* last_cached = src; | 1050 uint32_t* last_cached = src; |
| 1031 uint32_t* const src_end = data + width * height; // End of data | 1051 uint32_t* const src_end = data + width * height; // End of data |
| 1032 uint32_t* const src_last = data + width * last_row; // Last pixel to decode | 1052 uint32_t* const src_last = data + width * last_row; // Last pixel to decode |
| 1033 const int len_code_limit = NUM_LITERAL_CODES + NUM_LENGTH_CODES; | 1053 const int len_code_limit = NUM_LITERAL_CODES + NUM_LENGTH_CODES; |
| 1034 const int color_cache_limit = len_code_limit + hdr->color_cache_size_; | 1054 const int color_cache_limit = len_code_limit + hdr->color_cache_size_; |
| 1035 int next_sync_row = dec->incremental_ ? row : 1 << 24; | 1055 int next_sync_row = dec->incremental_ ? row : 1 << 24; |
| 1036 VP8LColorCache* const color_cache = | 1056 VP8LColorCache* const color_cache = |
| 1037 (hdr->color_cache_size_ > 0) ? &hdr->color_cache_ : NULL; | 1057 (hdr->color_cache_size_ > 0) ? &hdr->color_cache_ : NULL; |
| 1038 const int mask = hdr->huffman_mask_; | 1058 const int mask = hdr->huffman_mask_; |
| 1039 assert(htree_group != NULL); | 1059 const HTreeGroup* htree_group = |
| 1040 assert(src < src_end); | 1060 (src < src_last) ? GetHtreeGroupForPos(hdr, col, row) : NULL; |
| 1061 assert(dec->last_row_ < last_row); |
| 1041 assert(src_last <= src_end); | 1062 assert(src_last <= src_end); |
| 1042 | 1063 |
| 1043 while (src < src_last) { | 1064 while (src < src_last) { |
| 1044 int code; | 1065 int code; |
| 1045 if (row >= next_sync_row) { | 1066 if (row >= next_sync_row) { |
| 1046 SaveState(dec, (int)(src - data)); | 1067 SaveState(dec, (int)(src - data)); |
| 1047 next_sync_row = row + SYNC_EVERY_N_ROWS; | 1068 next_sync_row = row + SYNC_EVERY_N_ROWS; |
| 1048 } | 1069 } |
| 1049 // Only update when changing tile. Note we could use this test: | 1070 // Only update when changing tile. Note we could use this test: |
| 1050 // if "((((prev_col ^ col) | prev_row ^ row)) > mask)" -> tile changed | 1071 // if "((((prev_col ^ col) | prev_row ^ row)) > mask)" -> tile changed |
| 1051 // but that's actually slower and needs storing the previous col/row. | 1072 // but that's actually slower and needs storing the previous col/row. |
| 1052 if ((col & mask) == 0) htree_group = GetHtreeGroupForPos(hdr, col, row); | 1073 if ((col & mask) == 0) { |
| 1074 htree_group = GetHtreeGroupForPos(hdr, col, row); |
| 1075 } |
| 1076 assert(htree_group != NULL); |
| 1053 if (htree_group->is_trivial_code) { | 1077 if (htree_group->is_trivial_code) { |
| 1054 *src = htree_group->literal_arb; | 1078 *src = htree_group->literal_arb; |
| 1055 goto AdvanceByOne; | 1079 goto AdvanceByOne; |
| 1056 } | 1080 } |
| 1057 VP8LFillBitWindow(br); | 1081 VP8LFillBitWindow(br); |
| 1058 if (htree_group->use_packed_table) { | 1082 if (htree_group->use_packed_table) { |
| 1059 code = ReadPackedSymbols(htree_group, br, src); | 1083 code = ReadPackedSymbols(htree_group, br, src); |
| 1060 if (code == PACKED_NON_LITERAL_CODE) goto AdvanceByOne; | 1084 if (code == PACKED_NON_LITERAL_CODE) goto AdvanceByOne; |
| 1061 } else { | 1085 } else { |
| 1062 code = ReadSymbol(htree_group->htrees[GREEN], br); | 1086 code = ReadSymbol(htree_group->htrees[GREEN], br); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1073 alpha = ReadSymbol(htree_group->htrees[ALPHA], br); | 1097 alpha = ReadSymbol(htree_group->htrees[ALPHA], br); |
| 1074 if (br->eos_) break; | 1098 if (br->eos_) break; |
| 1075 *src = ((uint32_t)alpha << 24) | (red << 16) | (code << 8) | blue; | 1099 *src = ((uint32_t)alpha << 24) | (red << 16) | (code << 8) | blue; |
| 1076 } | 1100 } |
| 1077 AdvanceByOne: | 1101 AdvanceByOne: |
| 1078 ++src; | 1102 ++src; |
| 1079 ++col; | 1103 ++col; |
| 1080 if (col >= width) { | 1104 if (col >= width) { |
| 1081 col = 0; | 1105 col = 0; |
| 1082 ++row; | 1106 ++row; |
| 1083 if ((row % NUM_ARGB_CACHE_ROWS == 0) && (process_func != NULL)) { | 1107 if (process_func != NULL) { |
| 1084 process_func(dec, row); | 1108 if (row <= last_row && (row % NUM_ARGB_CACHE_ROWS == 0)) { |
| 1109 process_func(dec, row); |
| 1110 } |
| 1085 } | 1111 } |
| 1086 if (color_cache != NULL) { | 1112 if (color_cache != NULL) { |
| 1087 while (last_cached < src) { | 1113 while (last_cached < src) { |
| 1088 VP8LColorCacheInsert(color_cache, *last_cached++); | 1114 VP8LColorCacheInsert(color_cache, *last_cached++); |
| 1089 } | 1115 } |
| 1090 } | 1116 } |
| 1091 } | 1117 } |
| 1092 } else if (code < len_code_limit) { // Backward reference | 1118 } else if (code < len_code_limit) { // Backward reference |
| 1093 int dist_code, dist; | 1119 int dist_code, dist; |
| 1094 const int length_sym = code - NUM_LITERAL_CODES; | 1120 const int length_sym = code - NUM_LITERAL_CODES; |
| 1095 const int length = GetCopyLength(length_sym, br); | 1121 const int length = GetCopyLength(length_sym, br); |
| 1096 const int dist_symbol = ReadSymbol(htree_group->htrees[DIST], br); | 1122 const int dist_symbol = ReadSymbol(htree_group->htrees[DIST], br); |
| 1097 VP8LFillBitWindow(br); | 1123 VP8LFillBitWindow(br); |
| 1098 dist_code = GetCopyDistance(dist_symbol, br); | 1124 dist_code = GetCopyDistance(dist_symbol, br); |
| 1099 dist = PlaneCodeToDistance(width, dist_code); | 1125 dist = PlaneCodeToDistance(width, dist_code); |
| 1100 if (br->eos_) break; | 1126 if (br->eos_) break; |
| 1101 if (src - data < (ptrdiff_t)dist || src_end - src < (ptrdiff_t)length) { | 1127 if (src - data < (ptrdiff_t)dist || src_end - src < (ptrdiff_t)length) { |
| 1102 goto Error; | 1128 goto Error; |
| 1103 } else { | 1129 } else { |
| 1104 CopyBlock32b(src, dist, length); | 1130 CopyBlock32b(src, dist, length); |
| 1105 } | 1131 } |
| 1106 src += length; | 1132 src += length; |
| 1107 col += length; | 1133 col += length; |
| 1108 while (col >= width) { | 1134 while (col >= width) { |
| 1109 col -= width; | 1135 col -= width; |
| 1110 ++row; | 1136 ++row; |
| 1111 if ((row % NUM_ARGB_CACHE_ROWS == 0) && (process_func != NULL)) { | 1137 if (process_func != NULL) { |
| 1112 process_func(dec, row); | 1138 if (row <= last_row && (row % NUM_ARGB_CACHE_ROWS == 0)) { |
| 1139 process_func(dec, row); |
| 1140 } |
| 1113 } | 1141 } |
| 1114 } | 1142 } |
| 1115 // Because of the check done above (before 'src' was incremented by | 1143 // Because of the check done above (before 'src' was incremented by |
| 1116 // 'length'), the following holds true. | 1144 // 'length'), the following holds true. |
| 1117 assert(src <= src_end); | 1145 assert(src <= src_end); |
| 1118 if (col & mask) htree_group = GetHtreeGroupForPos(hdr, col, row); | 1146 if (col & mask) htree_group = GetHtreeGroupForPos(hdr, col, row); |
| 1119 if (color_cache != NULL) { | 1147 if (color_cache != NULL) { |
| 1120 while (last_cached < src) { | 1148 while (last_cached < src) { |
| 1121 VP8LColorCacheInsert(color_cache, *last_cached++); | 1149 VP8LColorCacheInsert(color_cache, *last_cached++); |
| 1122 } | 1150 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1133 goto Error; | 1161 goto Error; |
| 1134 } | 1162 } |
| 1135 assert(br->eos_ == VP8LIsEndOfStream(br)); | 1163 assert(br->eos_ == VP8LIsEndOfStream(br)); |
| 1136 } | 1164 } |
| 1137 | 1165 |
| 1138 if (dec->incremental_ && br->eos_ && src < src_end) { | 1166 if (dec->incremental_ && br->eos_ && src < src_end) { |
| 1139 RestoreState(dec); | 1167 RestoreState(dec); |
| 1140 } else if (!br->eos_) { | 1168 } else if (!br->eos_) { |
| 1141 // Process the remaining rows corresponding to last row-block. | 1169 // Process the remaining rows corresponding to last row-block. |
| 1142 if (process_func != NULL) { | 1170 if (process_func != NULL) { |
| 1143 process_func(dec, row); | 1171 process_func(dec, row > last_row ? last_row : row); |
| 1144 } | 1172 } |
| 1145 dec->status_ = VP8_STATUS_OK; | 1173 dec->status_ = VP8_STATUS_OK; |
| 1146 dec->last_pixel_ = (int)(src - data); // end-of-scan marker | 1174 dec->last_pixel_ = (int)(src - data); // end-of-scan marker |
| 1147 } else { | 1175 } else { |
| 1148 // if not incremental, and we are past the end of buffer (eos_=1), then this | 1176 // if not incremental, and we are past the end of buffer (eos_=1), then this |
| 1149 // is a real bitstream error. | 1177 // is a real bitstream error. |
| 1150 goto Error; | 1178 goto Error; |
| 1151 } | 1179 } |
| 1152 return 1; | 1180 return 1; |
| 1153 | 1181 |
| (...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1431 if (dec->pixels_ == NULL) { | 1459 if (dec->pixels_ == NULL) { |
| 1432 dec->status_ = VP8_STATUS_OUT_OF_MEMORY; | 1460 dec->status_ = VP8_STATUS_OUT_OF_MEMORY; |
| 1433 return 0; | 1461 return 0; |
| 1434 } | 1462 } |
| 1435 return 1; | 1463 return 1; |
| 1436 } | 1464 } |
| 1437 | 1465 |
| 1438 //------------------------------------------------------------------------------ | 1466 //------------------------------------------------------------------------------ |
| 1439 | 1467 |
| 1440 // Special row-processing that only stores the alpha data. | 1468 // Special row-processing that only stores the alpha data. |
| 1441 static void ExtractAlphaRows(VP8LDecoder* const dec, int row) { | 1469 static void ExtractAlphaRows(VP8LDecoder* const dec, int last_row) { |
| 1442 const int num_rows = row - dec->last_row_; | 1470 int cur_row = dec->last_row_; |
| 1443 const uint32_t* const in = dec->pixels_ + dec->width_ * dec->last_row_; | 1471 int num_rows = last_row - cur_row; |
| 1472 const uint32_t* in = dec->pixels_ + dec->width_ * cur_row; |
| 1444 | 1473 |
| 1445 if (num_rows <= 0) return; // Nothing to be done. | 1474 assert(last_row <= dec->io_->crop_bottom); |
| 1446 ApplyInverseTransforms(dec, num_rows, in); | 1475 while (num_rows > 0) { |
| 1447 | 1476 const int num_rows_to_process = |
| 1448 // Extract alpha (which is stored in the green plane). | 1477 (num_rows > NUM_ARGB_CACHE_ROWS) ? NUM_ARGB_CACHE_ROWS : num_rows; |
| 1449 { | 1478 // Extract alpha (which is stored in the green plane). |
| 1479 ALPHDecoder* const alph_dec = (ALPHDecoder*)dec->io_->opaque; |
| 1480 uint8_t* const output = alph_dec->output_; |
| 1450 const int width = dec->io_->width; // the final width (!= dec->width_) | 1481 const int width = dec->io_->width; // the final width (!= dec->width_) |
| 1451 const int cache_pixs = width * num_rows; | 1482 const int cache_pixs = width * num_rows_to_process; |
| 1452 uint8_t* const dst = (uint8_t*)dec->io_->opaque + width * dec->last_row_; | 1483 uint8_t* const dst = output + width * cur_row; |
| 1453 const uint32_t* const src = dec->argb_cache_; | 1484 const uint32_t* const src = dec->argb_cache_; |
| 1454 int i; | 1485 int i; |
| 1486 ApplyInverseTransforms(dec, num_rows_to_process, in); |
| 1455 for (i = 0; i < cache_pixs; ++i) dst[i] = (src[i] >> 8) & 0xff; | 1487 for (i = 0; i < cache_pixs; ++i) dst[i] = (src[i] >> 8) & 0xff; |
| 1488 AlphaApplyFilter(alph_dec, |
| 1489 cur_row, cur_row + num_rows_to_process, dst, width); |
| 1490 num_rows -= num_rows_to_process; |
| 1491 in += num_rows_to_process * dec->width_; |
| 1492 cur_row += num_rows_to_process; |
| 1456 } | 1493 } |
| 1457 dec->last_row_ = dec->last_out_row_ = row; | 1494 assert(cur_row == last_row); |
| 1495 dec->last_row_ = dec->last_out_row_ = last_row; |
| 1458 } | 1496 } |
| 1459 | 1497 |
| 1460 int VP8LDecodeAlphaHeader(ALPHDecoder* const alph_dec, | 1498 int VP8LDecodeAlphaHeader(ALPHDecoder* const alph_dec, |
| 1461 const uint8_t* const data, size_t data_size, | 1499 const uint8_t* const data, size_t data_size) { |
| 1462 uint8_t* const output) { | |
| 1463 int ok = 0; | 1500 int ok = 0; |
| 1464 VP8LDecoder* dec; | 1501 VP8LDecoder* dec = VP8LNew(); |
| 1465 VP8Io* io; | 1502 |
| 1503 if (dec == NULL) return 0; |
| 1504 |
| 1466 assert(alph_dec != NULL); | 1505 assert(alph_dec != NULL); |
| 1467 alph_dec->vp8l_dec_ = VP8LNew(); | 1506 alph_dec->vp8l_dec_ = dec; |
| 1468 if (alph_dec->vp8l_dec_ == NULL) return 0; | |
| 1469 dec = alph_dec->vp8l_dec_; | |
| 1470 | 1507 |
| 1471 dec->width_ = alph_dec->width_; | 1508 dec->width_ = alph_dec->width_; |
| 1472 dec->height_ = alph_dec->height_; | 1509 dec->height_ = alph_dec->height_; |
| 1473 dec->io_ = &alph_dec->io_; | 1510 dec->io_ = &alph_dec->io_; |
| 1474 io = dec->io_; | 1511 dec->io_->opaque = alph_dec; |
| 1475 | 1512 dec->io_->width = alph_dec->width_; |
| 1476 VP8InitIo(io); | 1513 dec->io_->height = alph_dec->height_; |
| 1477 WebPInitCustomIo(NULL, io); // Just a sanity Init. io won't be used. | |
| 1478 io->opaque = output; | |
| 1479 io->width = alph_dec->width_; | |
| 1480 io->height = alph_dec->height_; | |
| 1481 | 1514 |
| 1482 dec->status_ = VP8_STATUS_OK; | 1515 dec->status_ = VP8_STATUS_OK; |
| 1483 VP8LInitBitReader(&dec->br_, data, data_size); | 1516 VP8LInitBitReader(&dec->br_, data, data_size); |
| 1484 | 1517 |
| 1485 if (!DecodeImageStream(alph_dec->width_, alph_dec->height_, 1, dec, NULL)) { | 1518 if (!DecodeImageStream(alph_dec->width_, alph_dec->height_, 1, dec, NULL)) { |
| 1486 goto Err; | 1519 goto Err; |
| 1487 } | 1520 } |
| 1488 | 1521 |
| 1489 // Special case: if alpha data uses only the color indexing transform and | 1522 // Special case: if alpha data uses only the color indexing transform and |
| 1490 // doesn't use color cache (a frequent case), we will use DecodeAlphaData() | 1523 // doesn't use color cache (a frequent case), we will use DecodeAlphaData() |
| 1491 // method that only needs allocation of 1 byte per pixel (alpha channel). | 1524 // method that only needs allocation of 1 byte per pixel (alpha channel). |
| 1492 if (dec->next_transform_ == 1 && | 1525 if (dec->next_transform_ == 1 && |
| 1493 dec->transforms_[0].type_ == COLOR_INDEXING_TRANSFORM && | 1526 dec->transforms_[0].type_ == COLOR_INDEXING_TRANSFORM && |
| 1494 Is8bOptimizable(&dec->hdr_)) { | 1527 Is8bOptimizable(&dec->hdr_)) { |
| 1495 alph_dec->use_8b_decode = 1; | 1528 alph_dec->use_8b_decode_ = 1; |
| 1496 ok = AllocateInternalBuffers8b(dec); | 1529 ok = AllocateInternalBuffers8b(dec); |
| 1497 } else { | 1530 } else { |
| 1498 // Allocate internal buffers (note that dec->width_ may have changed here). | 1531 // Allocate internal buffers (note that dec->width_ may have changed here). |
| 1499 alph_dec->use_8b_decode = 0; | 1532 alph_dec->use_8b_decode_ = 0; |
| 1500 ok = AllocateInternalBuffers32b(dec, alph_dec->width_); | 1533 ok = AllocateInternalBuffers32b(dec, alph_dec->width_); |
| 1501 } | 1534 } |
| 1502 | 1535 |
| 1503 if (!ok) goto Err; | 1536 if (!ok) goto Err; |
| 1504 | 1537 |
| 1505 return 1; | 1538 return 1; |
| 1506 | 1539 |
| 1507 Err: | 1540 Err: |
| 1508 VP8LDelete(alph_dec->vp8l_dec_); | 1541 VP8LDelete(alph_dec->vp8l_dec_); |
| 1509 alph_dec->vp8l_dec_ = NULL; | 1542 alph_dec->vp8l_dec_ = NULL; |
| 1510 return 0; | 1543 return 0; |
| 1511 } | 1544 } |
| 1512 | 1545 |
| 1513 int VP8LDecodeAlphaImageStream(ALPHDecoder* const alph_dec, int last_row) { | 1546 int VP8LDecodeAlphaImageStream(ALPHDecoder* const alph_dec, int last_row) { |
| 1514 VP8LDecoder* const dec = alph_dec->vp8l_dec_; | 1547 VP8LDecoder* const dec = alph_dec->vp8l_dec_; |
| 1515 assert(dec != NULL); | 1548 assert(dec != NULL); |
| 1516 assert(last_row <= dec->height_); | 1549 assert(last_row <= dec->height_); |
| 1517 | 1550 |
| 1518 if (dec->last_pixel_ == dec->width_ * dec->height_) { | 1551 if (dec->last_row_ >= last_row) { |
| 1519 return 1; // done | 1552 return 1; // done |
| 1520 } | 1553 } |
| 1521 | 1554 |
| 1522 // Decode (with special row processing). | 1555 // Decode (with special row processing). |
| 1523 return alph_dec->use_8b_decode ? | 1556 return alph_dec->use_8b_decode_ ? |
| 1524 DecodeAlphaData(dec, (uint8_t*)dec->pixels_, dec->width_, dec->height_, | 1557 DecodeAlphaData(dec, (uint8_t*)dec->pixels_, dec->width_, dec->height_, |
| 1525 last_row) : | 1558 last_row) : |
| 1526 DecodeImageData(dec, dec->pixels_, dec->width_, dec->height_, | 1559 DecodeImageData(dec, dec->pixels_, dec->width_, dec->height_, |
| 1527 last_row, ExtractAlphaRows); | 1560 last_row, ExtractAlphaRows); |
| 1528 } | 1561 } |
| 1529 | 1562 |
| 1530 //------------------------------------------------------------------------------ | 1563 //------------------------------------------------------------------------------ |
| 1531 | 1564 |
| 1532 int VP8LDecodeHeader(VP8LDecoder* const dec, VP8Io* const io) { | 1565 int VP8LDecodeHeader(VP8LDecoder* const dec, VP8Io* const io) { |
| 1533 int width, height, has_alpha; | 1566 int width, height, has_alpha; |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1604 dec->status_ = VP8_STATUS_OUT_OF_MEMORY; | 1637 dec->status_ = VP8_STATUS_OUT_OF_MEMORY; |
| 1605 goto Err; | 1638 goto Err; |
| 1606 } | 1639 } |
| 1607 } | 1640 } |
| 1608 } | 1641 } |
| 1609 dec->state_ = READ_DATA; | 1642 dec->state_ = READ_DATA; |
| 1610 } | 1643 } |
| 1611 | 1644 |
| 1612 // Decode. | 1645 // Decode. |
| 1613 if (!DecodeImageData(dec, dec->pixels_, dec->width_, dec->height_, | 1646 if (!DecodeImageData(dec, dec->pixels_, dec->width_, dec->height_, |
| 1614 dec->height_, ProcessRows)) { | 1647 io->crop_bottom, ProcessRows)) { |
| 1615 goto Err; | 1648 goto Err; |
| 1616 } | 1649 } |
| 1617 | 1650 |
| 1618 params->last_y = dec->last_out_row_; | 1651 params->last_y = dec->last_out_row_; |
| 1619 return 1; | 1652 return 1; |
| 1620 | 1653 |
| 1621 Err: | 1654 Err: |
| 1622 VP8LClear(dec); | 1655 VP8LClear(dec); |
| 1623 assert(dec->status_ != VP8_STATUS_OK); | 1656 assert(dec->status_ != VP8_STATUS_OK); |
| 1624 return 0; | 1657 return 0; |
| 1625 } | 1658 } |
| 1626 | 1659 |
| 1627 //------------------------------------------------------------------------------ | 1660 //------------------------------------------------------------------------------ |
| OLD | NEW |