blob: 455ae478049d8e707f673434a9a8fa7e56514c85 [file] [log] [blame]
// Copyright 2019 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.
// -----------------------------------------------------------------------------
//
// Image savers
#include "imageio/image_enc.h"
#include <cstdio>
#include <cstring>
#include "imageio/file_format.h"
#include "imageio/imageio_util.h"
#include "src/utils/csp.h"
#include "src/utils/utils.h"
#include "src/wp2/base.h"
#include "src/wp2/format_constants.h"
namespace WP2 {
//------------------------------------------------------------------------------
WP2Status SaveImage(const ArgbBuffer& buffer, const char* const file_path,
bool overwrite, FileFormat format, size_t* const file_size,
const CSPTransform& transform) {
WP2_CHECK_OK(file_path != nullptr, WP2_STATUS_NULL_PARAMETER);
WP2_CHECK_OK(!buffer.IsEmpty(), WP2_STATUS_INVALID_PARAMETER);
std::FILE* fout = nullptr;
const bool use_stdout = (strcmp(file_path, "-") == 0);
if (use_stdout) { // std::ftell() does not work with pipes.
WP2_CHECK_OK(file_size == nullptr, WP2_STATUS_INVALID_PARAMETER);
}
if (format == FileFormat::AUTO) {
format = use_stdout ? FileFormat::PNG : GetFormatFromExtension(file_path);
}
#ifdef HAVE_WINCODEC_H
if (format != PNG) // NOLINT
#endif
{
const char* const mode = (overwrite ? "wb" : "wxb");
fout =
use_stdout ? IoUtilSetBinaryMode(stdout) : std::fopen(file_path, mode);
WP2_CHECK_OK(fout != nullptr, (!use_stdout && FileExists(file_path))
? WP2_STATUS_BAD_WRITE
: WP2_STATUS_INVALID_PARAMETER);
}
WP2Status status;
if (format == FileFormat::PNG) {
status =
WritePNG(buffer, fout, file_path, use_stdout, overwrite, file_size);
} else if (format == FileFormat::TIFF) {
status = WriteTIFF(buffer, fout);
} else if (format == FileFormat::BMP) {
status = WriteBMP(buffer, fout);
} else if (format == FileFormat::PGM) {
status = WritePGM(buffer, fout, transform);
} else if (format == FileFormat::PPM) {
status = WritePPM(buffer, fout);
} else if (format == FileFormat::PAM) {
status = WritePAM(buffer, fout);
} else if (format == FileFormat::WEBP) {
MemoryWriter writer;
status =
CompressWebP(buffer, /*quality=*/kMaxQuality, /*effort=*/6, &writer);
if (status == WP2_STATUS_OK) {
std::fwrite(writer.mem_, writer.size_, 1, fout);
}
} else if (format == FileFormat::JPEG_XL) {
MemoryWriter writer;
// Do not choose kMaxEffort as this would lead to JPEG XL's level 10.
status =
CompressJXL(buffer, /*quality=*/kMaxQuality, /*effort=*/6, &writer);
if (status == WP2_STATUS_OK) {
std::fwrite(writer.mem_, writer.size_, 1, fout);
}
} else {
status = WP2_STATUS_UNSUPPORTED_FEATURE;
}
if (fout != nullptr) {
if (file_size != nullptr) *file_size = std::ftell(fout);
if (fout != stdout) std::fclose(fout);
}
return status;
}
//------------------------------------------------------------------------------
} // namespace WP2