1 // Copyright 2018 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef ASTC_CODEC_DECODER_LOGICAL_ASTC_BLOCK_H_
16 #define ASTC_CODEC_DECODER_LOGICAL_ASTC_BLOCK_H_
17 
18 #include "src/base/optional.h"
19 #include "src/decoder/footprint.h"
20 #include "src/decoder/intermediate_astc_block.h"
21 #include "src/decoder/partition.h"
22 #include "src/decoder/physical_astc_block.h"
23 
24 #include <array>
25 #include <utility>
26 #include <vector>
27 
28 namespace astc_codec {
29 
30 // A logical ASTC block holds the endpoints, indices, and partition information
31 // of a compressed block. These values generally do not adhere to any
32 // quality-for-bitrate-imposed limits and are solely logical entities for
33 // determining the best representation of a given block.
34 class LogicalASTCBlock {
35  public:
36   LogicalASTCBlock(const LogicalASTCBlock&) = default;
37   LogicalASTCBlock(LogicalASTCBlock&&) = default;
38 
39   // Unpack an intermediate block into a logical one.
40   LogicalASTCBlock(const Footprint& footprint,
41                    const IntermediateBlockData& block);
42 
43   // Unpack a void extent intermediate block into a logical one.
44   LogicalASTCBlock(const Footprint& footprint, const VoidExtentData& block);
45 
46   // Create a new, empty ASTC block
47   explicit LogicalASTCBlock(const Footprint& footprint);
48 
49   // Returns the footprint associated with this block. The footprint is defined
50   // via the partition, because the partition definition is dependent on the
51   // footprint.
GetFootprint()52   const Footprint& GetFootprint() const { return partition_.footprint; }
53 
54   // Returns the unquantized and infilled weight in the range [0, 64] for the
55   // given texel location. Assumes that the block is a single-plane block,
56   // meaning that weights are used equally across all channels.
57   void SetWeightAt(int x, int y, int weight);
58   int WeightAt(int x, int y) const;
59 
60   // Returns the unquantized and infilled weight in the range [0, 64] for the
61   // given channel at the given texel location. If the block does not have a
62   // dual-plane channel then the reference-returning version will fail, as it
63   // cannot return a reference to a value that (potentially) doesn't exist.
64   void SetDualPlaneWeightAt(int channel, int x, int y, int weight);
65   int DualPlaneWeightAt(int channel, int x, int y) const;
66 
67   // Returns the color as it would be in the given pixel coordinates of the
68   // block. Fails if the coordinates are outside of the range of the block
69   // footprint
70   RgbaColor ColorAt(int x, int y) const;
71 
72   // Sets the current partition for the block. |p|'s footprint must match the
73   // return value of GetFootprint() or else this call will fail.
74   void SetPartition(const Partition& p);
75 
76   // Sets the endpoints for the given subset.
77   void SetEndpoints(const EndpointPair& eps, int subset);
SetEndpoints(const Endpoint & ep1,const Endpoint & ep2,int subset)78   void SetEndpoints(const Endpoint& ep1, const Endpoint& ep2, int subset) {
79     SetEndpoints(std::make_pair(ep1, ep2), subset);
80   }
81 
82   // Sets the dual plane channel for the block. Value must be within the range
83   // [0, 3]. If a negative value is passed, then the dual-plane data for the
84   // block is removed, and the block is treated as a single-plane block.
85   void SetDualPlaneChannel(int channel);
IsDualPlane()86   bool IsDualPlane() const { return dual_plane_.hasValue(); }
87 
88  private:
89   // A block may have up to four endpoint pairs.
90   std::vector<EndpointPair> endpoints_;
91 
92   // Weights are stored as values in the interval [0, 64].
93   std::vector<int> weights_;
94 
95   // The partition information for this block. This determines the
96   // appropriate subsets that each pixel should belong to.
97   Partition partition_;
98 
99   // Dual plane data holds both the channel and the weights that describe
100   // the dual plane data for the given block. If a block has a dual plane, then
101   // we need to know both the channel and the weights associated with it.
102   struct DualPlaneData {
103     int channel;
104     std::vector<int> weights;
105   };
106 
107   // The dual-plane data is optional from a logical representation of the block.
108   base::Optional<DualPlaneData> dual_plane_;
109 
110   // Calculates the unquantized and interpolated weights from the encoded weight
111   // values and possibly dual-plane weights specified in the passed ASTC block.
112   void CalculateWeights(const Footprint& footprint,
113                         const IntermediateBlockData& block);
114 
115   // Calculates the weights for a VoidExtentBlock.
116   void CalculateWeights(const Footprint& footprint,
117                         const VoidExtentData& block);
118 };
119 
120 // Unpacks the physical ASTC block into a logical block. Returns false if the
121 // physical block is an error encoded block.
122 base::Optional<LogicalASTCBlock> UnpackLogicalBlock(
123     const Footprint& footprint, const PhysicalASTCBlock& pb);
124 
125 }  // namespace astc_codec
126 
127 #endif  // ASTC_CODEC_DECODER_LOGICAL_ASTC_BLOCK_H_
128