Skip to content
This repository has been archived by the owner on Dec 29, 2022. It is now read-only.

Commit

Permalink
Initial version of astc-codec for open source release
Browse files Browse the repository at this point in the history
Contains an implementation of an ASTC decoder that is able to pass the
dEQP ASTC LDR tests.

astc-codec has no external dependencies for the main library, only for
test code, and is licensed under the Apache license.

Components:

include/ - Public API that can decode ASTC LDR data into a RGBA UNORM8
buffer.

src/base/ - Base library with common functionality not directly related
to ASTC decoding.  Contains a uint128 implementation, BitStream for
reading/writing bits with a primitive (or uint128 type), Optional
implementation (to not take a dependency on C++17), and more.

src/decoder/ - Internal implementation of the ASTC decoder.

src/base/test/, src/decoder/test/ - Unit tests (and a fuzzing test) for
the astc decoder.

src/decoder/testdata/ - Sample ASTC images and golden image results for
testing.

src/decoder/tools/ - A tool to inspect contents of an ASTC file.

third_party/ - Third party libraries, only used for tests.

Change-Id: Ia98e5a7dc847daa3d3a48c5e62d94b8fb1cb98bd
  • Loading branch information
Jeff McGlynn committed Jun 20, 2018
1 parent ce724a5 commit b56a500
Show file tree
Hide file tree
Showing 112 changed files with 12,548 additions and 1 deletion.
13 changes: 13 additions & 0 deletions BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,16 @@
# limitations under the License.

licenses(["notice"])

cc_library(
name = "api",
hdrs = ["include/astc-codec/astc-codec.h"],
visibility = ["//src/decoder:__pkg__"],
)

cc_library(
name = "astc_codec",
deps = ["//src/decoder:codec"],
includes = ["include"],
visibility = ["//visibility:public"],
)
37 changes: 36 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,41 @@
astc-codec is a software ASTC decoder implementation, which supports the ASTC
LDR profile.

Example usage:

```
#include <astc-codec/astc-codec.h>
// ...
std::vector<uint8_t> astc = LoadMyASTCData();
const size_t width = 640;
const size_t height = 480;
std::vector<uint8_t> result;
result.resize(width * height * 4);
bool result = astc_codec::ASTCDecompressToRGBA(
astc.data(), astc.size(), width, height, astc_codec::FootprintType::k4x4,
result.data(), result.size(), /* stride */ width * 4);
```

## Building

Install [Bazel](https://bazel.build/), and then run:

```
bazel build :astc_codec -c opt
```

astc-codec has been tested on Mac and Linux.

## Run Tests

```
bazel test //...
```

## Contributing

See [CONTRIBUTING.md](CONTRIBUTING.md) for important contributing requirements.
Expand All @@ -12,4 +47,4 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for important contributing requirements.
astc-codec project is licensed under the Apache License Version 2.0. You can
find a copy of it in [LICENSE](LICENSE).

This is not an official Google product.
This is not an officially supported Google product.
75 changes: 75 additions & 0 deletions include/astc-codec/astc-codec.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// 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.

#ifndef ASTC_CODEC_ASTC_CODEC_H_
#define ASTC_CODEC_ASTC_CODEC_H_

#include <cstddef>
#include <cstdint>

namespace astc_codec {

// These are the valid ASTC footprints according to the specification in
// Section C.2.7.
enum class FootprintType {
k4x4,
k5x4,
k5x5,
k6x5,
k6x6,
k8x5,
k8x6,
k10x5,
k10x6,
k8x8,
k10x8,
k10x10,
k12x10,
k12x12,

kCount
};

// Decompresses ASTC LDR image data to a RGBA32 buffer.
//
// Supports formats defined in the KHR_texture_compression_astc_ldr spec and
// returns UNORM8 values. sRGB is not supported, and should be implemented
// by the caller.
//
// |astc_data| - Compressed ASTC image buffer, must be at least |astc_data_size|
// bytes long.
// |astc_data_size| - The size of |astc_data|, in bytes.
// |width| - Image width, in pixels.
// |height| - Image height, in pixels.
// |footprint| - The ASTC footprint (block size) of the compressed image buffer.
// |out_buffer| - Pointer to a buffer where the decompressed image will be
// stored, must be at least |out_buffer_size| bytes long.
// |out_buffer_size| - The size of |out_buffer|, in bytes, at least
// height*out_buffer_stride. If this is too small, this
// function will return false and no data will be
// decompressed.
// |out_buffer_stride| - The stride that should be used to store rows of the
// decoded image, must be at least 4*width bytes.
//
// Returns true if the decompression succeeded, or false if decompression
// failed, or if the astc_data_size was too small for the given width, height,
// and footprint, or if out_buffer_size is too small.
bool ASTCDecompressToRGBA(const uint8_t* astc_data, size_t astc_data_size,
size_t width, size_t height, FootprintType footprint,
uint8_t* out_buffer, size_t out_buffer_size,
size_t out_buffer_stride);

} // namespace astc_codec

#endif // ASTC_CODEC_ASTC_CODEC_H_
4 changes: 4 additions & 0 deletions src/.clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
BasedOnStyle: Google
AllowShortCaseLabelsOnASingleLine: true
AllowShortFunctionsOnASingleLine: Inline
SpaceAfterTemplateKeyword: false
45 changes: 45 additions & 0 deletions src/base/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# 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.

cc_library(
name = "base",
hdrs = [
"bit_stream.h",
"bottom_n.h",
"math_utils.h",
"optional.h",
"string_utils.h",
"type_traits.h",
"uint128.h",
],
visibility = ["//src/decoder:__pkg__"],
)

cc_test(
name = "base_test",
srcs = [
"test/bit_stream_test.cpp",
"test/bottom_n_test.cpp",
"test/math_utils_test.cpp",
"test/optional_test.cpp",
"test/string_utils_test.cpp",
"test/type_traits_test.cpp",
"test/uint128_test.cpp",
],
deps = [
"@gtest//:gtest_main",
":base",
],
)

77 changes: 77 additions & 0 deletions src/base/bit_stream.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// 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.

#ifndef ASTC_CODEC_BASE_BIT_STREAM_H_
#define ASTC_CODEC_BASE_BIT_STREAM_H_

#include <cassert>
#include <cstdint>

namespace astc_codec {
namespace base {

// Represents a stream of bits that can be read or written in arbitrary-sized
// chunks.
template<typename IntType = uint64_t>
class BitStream {
public:
// Creates an empty BitStream.
BitStream() = default;
BitStream(IntType data, uint32_t data_size)
: data_(data), data_size_(data_size) {
assert(data_size_ <= sizeof(data_) * 8);
}

// Return the number of bits in the stream.
uint32_t Bits() const { return data_size_; }

// Put |size| bits into the stream.
// Fails if there is not enough space in the buffer to store the bits.
template<typename ResultType>
void PutBits(ResultType x, uint32_t size) {
assert(data_size_ + size <= sizeof(data_) * 8);

data_ |= (IntType(x) & MaskFor(size)) << data_size_;
data_size_ += size;
}

// Get |count| bits from the stream.
// Returns true if |count| bits were successfully retrieved.
template<typename ResultType>
bool GetBits(uint32_t count, ResultType* result) {
if (count <= data_size_) {
*result = static_cast<ResultType>(data_ & MaskFor(count));
data_ = data_ >> count;
data_size_ -= count;
return true;
} else {
*result = 0;
return false;
}
}

private:
IntType MaskFor(uint32_t bits) const {
return (bits == sizeof(IntType) * 8) ? ~IntType(0)
: (IntType(1) << bits) - 1;
}

IntType data_ = 0;
uint32_t data_size_ = 0;
};

} // namespace base
} // namespace astc_codec

#endif // ASTC_CODEC_BASE_BIT_STREAM_H_
78 changes: 78 additions & 0 deletions src/base/bottom_n.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// 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.

#ifndef ASTC_CODEC_BASE_BOTTOM_N_H_
#define ASTC_CODEC_BASE_BOTTOM_N_H_

#include <algorithm>
#include <functional>
#include <vector>

namespace astc_codec {
namespace base {

// Used to aggregate the lowest N values of data supplied.
template<typename T, typename CompareFn = std::less<T>>
class BottomN {
public:
typedef std::vector<T> ContainerType;

// Creates an empty BottomN with limit |max_size|.
BottomN(size_t max_size) : max_size_(max_size) { }

bool Empty() const { return data_.empty(); }
size_t Size() const { return data_.size(); }

const T& Top() const { return data_.front(); }

void Push(const T& value) {
if (data_.size() < max_size_ || compare_(value, Top())) {
data_.push_back(value);
std::push_heap(data_.begin(), data_.end(), compare_);

if (Size() > max_size_) {
PopTop();
}
}
}

std::vector<T> Pop() {
const size_t len = Size();
std::vector<T> result(len);

for (size_t i = 0; i < len; ++i) {
result[len - i - 1] = PopTop();
}

return result;
}

private:
T PopTop() {
std::pop_heap(data_.begin(), data_.end(), compare_);
T result = data_.back();
data_.pop_back();
return result;
}

ContainerType data_;
CompareFn compare_;

const size_t max_size_;
};

} // namespace base
} // namespace astc_codec

#endif // ASTC_CODEC_BASE_BOTTOM_N_H_
Loading

0 comments on commit b56a500

Please sign in to comment.