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 |