mirror of
https://github.com/bkaradzic/bimg.git
synced 2026-06-08 02:43:48 +00:00
123 lines
3.8 KiB
C++
123 lines
3.8 KiB
C++
// Copyright 2018 Google LLC
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// https://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#include "src/decoder/weight_infill.h"
|
|
#include "src/decoder/integer_sequence_codec.h"
|
|
|
|
#include <array>
|
|
#include <cmath>
|
|
#include <utility>
|
|
|
|
namespace astc_codec {
|
|
|
|
namespace {
|
|
|
|
// The following functions are based on Section C.2.18 of the ASTC specification
|
|
int GetScaleFactorD(int block_dim) {
|
|
return static_cast<int>((1024.f + static_cast<float>(block_dim >> 1)) /
|
|
static_cast<float>(block_dim - 1));
|
|
}
|
|
|
|
std::pair<int, int> GetGridSpaceCoordinates(
|
|
Footprint footprint, int s, int t, int weight_dim_x, int weight_dim_y) {
|
|
const int ds = GetScaleFactorD(footprint.Width());
|
|
const int dt = GetScaleFactorD(footprint.Height());
|
|
|
|
const int cs = ds * s;
|
|
const int ct = dt * t;
|
|
|
|
const int gs = (cs * (weight_dim_x - 1) + 32) >> 6;
|
|
const int gt = (ct * (weight_dim_y - 1) + 32) >> 6;
|
|
|
|
assert(gt < 1 << 8);
|
|
assert(gs < 1 << 8);
|
|
|
|
return std::make_pair(gs, gt);
|
|
}
|
|
|
|
// Returns the weight-grid values that are to be used for bilinearly
|
|
// interpolating the weight to its final value. If the returned value
|
|
// is equal to weight_dim_x * weight_dim_y, it may be ignored.
|
|
std::array<int, 4> BilerpGridPointsForWeight(
|
|
const std::pair<int, int>& grid_space_coords, int weight_dim_x) {
|
|
const int js = grid_space_coords.first >> 4;
|
|
const int jt = grid_space_coords.second >> 4;
|
|
|
|
std::array<int, 4> result;
|
|
result[0] = js + weight_dim_x * jt;
|
|
result[1] = js + weight_dim_x * jt + 1;
|
|
result[2] = js + weight_dim_x * (jt + 1);
|
|
result[3] = js + weight_dim_x * (jt + 1) + 1;
|
|
|
|
return result;
|
|
}
|
|
|
|
std::array<int, 4> BilerpGridPointFactorsForWeight(
|
|
const std::pair<int, int>& grid_space_coords) {
|
|
const int fs = grid_space_coords.first & 0xF;
|
|
const int ft = grid_space_coords.second & 0xF;
|
|
|
|
std::array<int, 4> result;
|
|
result[3] = (fs * ft + 8) >> 4;
|
|
result[2] = ft - result[3];
|
|
result[1] = fs - result[3];
|
|
result[0] = 16 - fs - ft + result[3];
|
|
|
|
assert(result[0] <= 16);
|
|
assert(result[1] <= 16);
|
|
assert(result[2] <= 16);
|
|
assert(result[3] <= 16);
|
|
|
|
return result;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
int CountBitsForWeights(int weight_dim_x, int weight_dim_y,
|
|
int target_weight_range) {
|
|
int num_weights = weight_dim_x * weight_dim_y;
|
|
return IntegerSequenceCodec::
|
|
GetBitCountForRange(num_weights, target_weight_range);
|
|
}
|
|
|
|
std::vector<int> InfillWeights(const std::vector<int>& weights,
|
|
Footprint footprint, int dim_x, int dim_y) {
|
|
std::vector<int> result;
|
|
result.reserve(footprint.NumPixels());
|
|
for (int t = 0; t < footprint.Height(); ++t) {
|
|
for (int s = 0; s < footprint.Width(); ++s) {
|
|
const auto grid_space_coords =
|
|
GetGridSpaceCoordinates(footprint, s, t, dim_x, dim_y);
|
|
const auto grid_pts =
|
|
BilerpGridPointsForWeight(grid_space_coords, dim_x);
|
|
const auto grid_factors =
|
|
BilerpGridPointFactorsForWeight(grid_space_coords);
|
|
|
|
int weight = 0;
|
|
for (int i = 0; i < 4; ++i) {
|
|
if (grid_pts[i] < dim_x * dim_y) {
|
|
weight += weights.at(grid_pts[i]) * grid_factors[i];
|
|
}
|
|
}
|
|
result.push_back((weight + 8) >> 4);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
} // namespace astc_codec
|