blob: f652bd9cb4ae00b131065fa65c84df6f4f42e74c [file] [edit]
// Copyright 2026 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 "formats/png/test_utils.h"
#include <cstdint>
#include <string>
#include "absl/status/status.h"
#include "absl/status/status_macros.h"
#include "absl/status/statusor.h"
#include "absl/types/span.h"
#include "riegeli/bytes/string_writer.h"
#include "riegeli/bytes/writer.h"
#include "riegeli/endian/endian_writing.h"
namespace credentio {
absl::Status WritePngHeader(riegeli::Writer& buffer) {
const std::string header = "\x89PNG\x0d\x0a\x1a\x0a";
if (!buffer.Write(header)) {
return buffer.StatusOrAnnotate(
absl::InternalError("Failed to write PNG header"));
}
return absl::OkStatus();
}
absl::Status WritePngChunk(riegeli::Writer& buffer, const Chunk& chunk) {
if (!riegeli::WriteBigEndian<uint32_t>(chunk.payload.size(), buffer)) {
return buffer.StatusOrAnnotate(
absl::InternalError("Failed to write chunk size"));
}
if (!riegeli::WriteBigEndian<uint32_t>(chunk.type, buffer)) {
return buffer.StatusOrAnnotate(
absl::InternalError("Failed to write chunk type"));
}
if (!chunk.payload.empty()) {
if (!buffer.Write(chunk.payload)) {
return buffer.StatusOrAnnotate(
absl::InternalError("Failed to write chunk payload"));
}
}
if (!riegeli::WriteBigEndian<uint32_t>(chunk.crc.value_or(0), buffer)) {
return buffer.StatusOrAnnotate(
absl::InternalError("Failed to write chunk CRC"));
}
return absl::OkStatus();
}
absl::Status WritePngEnd(riegeli::Writer& buffer) {
return WritePngChunk(buffer, Chunk{.type = 'IEND', .payload = ""});
}
absl::StatusOr<std::string> CreatePng(absl::Span<const Chunk> chunks,
bool add_header, bool add_end) {
std::string buffer;
riegeli::StringWriter writer(&buffer);
if (add_header) {
ABSL_RETURN_IF_ERROR(WritePngHeader(writer));
}
for (const Chunk& chunk : chunks) {
ABSL_RETURN_IF_ERROR(WritePngChunk(writer, chunk));
}
if (add_end) {
ABSL_RETURN_IF_ERROR(WritePngEnd(writer));
}
if (!writer.Close()) {
return writer.status();
}
return buffer;
}
} // namespace credentio