Merge pull request #56 from alexelex:master

PiperOrigin-RevId: 346286713
Change-Id: Ib052758d6a7deaa1c62660fd43d8f0e31f42bc09
This commit is contained in:
Copybara-Service 2020-12-08 03:15:32 -08:00
commit 6f8e758177
21 changed files with 1891 additions and 2 deletions

7
.gitmodules vendored
View File

@ -15,7 +15,10 @@
url = https://github.com/OSGeo/gdal/
[submodule "oss-internship-2020/curl/curl_wrapper/curl"]
path = oss-internship-2020/curl/curl_wrapper/curl
url = git@github.com:curl/curl.git
url = https://github.com/curl/curl
[submodule "oss-internship-2020/libuv/libuv"]
path = oss-internship-2020/libuv/libuv
url = git@github.com:libuv/libuv.git
url = https://github.com/libuv/libuv.git
[submodule "oss-internship-2020/libtiff/wrapper/libtiff"]
path = oss-internship-2020/libtiff/wrapper/libtiff
url = https://gitlab.com/libtiff/libtiff

View File

@ -0,0 +1,2 @@
build/
.vscode/

View File

@ -0,0 +1,130 @@
# Copyright 2020 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
#
# http://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.
cmake_minimum_required(VERSION 3.10)
project(sandboxed_libtiff CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
# Set this on the command-line
set(SAPI_ROOT "" CACHE PATH "Path to the Sandboxed API source tree")
# To obtain a full SAPI_ROOT check out its source separately:
# git clone https://github.com/google/sandboxed-api.git $HOME/sapi_root
# Then configure:
# mkdir -p build && cd build
# cmake .. -G Ninja -DSAPI_ROOT=$HOME/sapi_root
option(TIFF_SAPI_ENABLE_EXAMPLES "" ON)
option(TIFF_SAPI_ENABLE_TESTS "" ON)
set(SAPI_ENABLE_EXAMPLES ${TIFF_SAPI_ENABLE_EXAMPLES} CACHE BOOL "" FORCE)
set(SAPI_ENABLE_TESTS ${TIFF_SAPI_ENABLE_TESTS} CACHE BOOL "" FORCE)
add_subdirectory(wrapper)
add_subdirectory(
"${SAPI_ROOT}"
"${CMAKE_BINARY_DIR}/sandboxed-api-build"
# Omit this to have the full Sandboxed API in IDE
EXCLUDE_FROM_ALL
)
add_sapi_library(tiff_sapi
# List of functions that we want to include in the
# generated sandboxed API class
FUNCTIONS TIFFOpen
TIFFClose
TIFFGetField1
TIFFGetField2
TIFFGetField3
TIFFSetFieldUChar1
TIFFSetFieldUChar2
TIFFSetFieldUChar3
TIFFSetFieldSChar1
TIFFSetFieldSChar2
TIFFSetFieldSChar3
TIFFSetFieldU1
TIFFSetFieldU2
TIFFSetFieldU3
TIFFSetFieldS1
TIFFSetFieldS2
TIFFSetFieldS3
TIFFSetFieldUShort1
TIFFSetFieldUShort2
TIFFSetFieldUShort3
TIFFSetFieldSShort1
TIFFSetFieldSShort2
TIFFSetFieldSShort3
TIFFSetFieldULLong1
TIFFSetFieldULLong2
TIFFSetFieldULLong3
TIFFSetFieldSLLong1
TIFFSetFieldSLLong2
TIFFSetFieldSLLong3
TIFFSetFieldFloat1
TIFFSetFieldFloat2
TIFFSetFieldFloat3
TIFFSetFieldDouble1
TIFFSetFieldDouble2
TIFFSetFieldDouble3
TIFFReadRGBATile
TIFFReadEncodedTile
TIFFReadEncodedStrip
TIFFReadFromUserBuffer
TIFFTileSize
TIFFSetDirectory
TIFFFreeDirectory
TIFFCreateDirectory
TIFFForceStrileArrayWriting
TIFFDeferStrileArrayWriting
TIFFWriteCheck
TIFFWriteScanline
TIFFWriteDirectory
TIFFWriteEncodedTile
TIFFWriteEncodedStrip
TIFFGetStrileOffsetWithErr
TIFFGetStrileByteCountWithErr
TIFFCreateEXIFDirectory
TIFFWriteCustomDirectory
INPUTS wrapper/libtiff/libtiff/tiffio.h
wrapper/func.h
# Header files or .cc files that should be parsed
LIBRARY wrapped_tiff # Library dependency from the add_library() above
LIBRARY_NAME Tiff # Name prefix for the generated header. Will be
# suffixed with "Api" and "Sandbox" as needed.
NAMESPACE "" # Optional C++ namespace to wrap the generated code
)
target_include_directories(tiff_sapi INTERFACE
"${PROJECT_BINARY_DIR}" # To find the generated SAPI header
)
if (TIFF_SAPI_ENABLE_EXAMPLES)
add_subdirectory(example)
endif()
if (TIFF_SAPI_ENABLE_TESTS)
add_subdirectory(test)
endif()

View File

@ -0,0 +1,22 @@
# sapi-libtiff
Copyright 2020 Google LLC.
## Start use
You should make sure the libtiff submodule is cloned.
`git clone --recursive https://github.com/alexelex/sapi-libtiff`
## Usage
#### build:
`mkdir -p build && cd build && cmake .. -DSAPI_ROOT=$HOME/sapi_root -DBUILD_SHARED_LIBS=OFF`
`make -j 8`
#### to run the sandboxed example:
`./example/sandboxed absolute/path/to/project/dir`
#### to run tests:
`./test/tests`
you also can use sandbox flags `sandbox2_danger_danger_permit_all` and `sandbox2_danger_danger_permit_all_and_log`

View File

@ -0,0 +1,24 @@
# Copyright 2020 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
#
# http://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.
add_executable(sandboxed
main_sandboxed.cc
../sandboxed.h
)
target_link_libraries(sandboxed PRIVATE
tiff_sapi
sapi::sapi
sandbox2::temp_file
)

View File

@ -0,0 +1,281 @@
// Copyright 2020 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
//
// http://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 <array>
#include <cstdint>
#include <cstring>
#include <iostream>
#include <vector>
#include "../sandboxed.h" // NOLINT(build/include)
#include "sandboxed_api/sandbox2/util/fileops.h"
#include "sandboxed_api/sandbox2/util/path.h"
#include "tiffio.h" // NOLINT(build/include)
// sapi functions:
// TIFFTileSize
// TIFFOpen
// TIFFReadEncodedTile
// TIFFSetField
// TIFFClose
// TIFFReadRGBATile
// TIFFGetField
namespace {
constexpr std::array<uint8_t, 6> kCluster0 = {0, 0, 2, 0, 138, 139};
constexpr std::array<uint8_t, 6> kCluster64 = {0, 0, 9, 6, 134, 119};
constexpr std::array<uint8_t, 6> kCluster128 = {44, 40, 63, 59, 230, 95};
int CheckCluster(int cluster, const sapi::v::Array<uint8_t>& buffer,
const std::vector<uint8_t>& expected_cluster) {
uint8_t* target = buffer.GetData() + cluster * 6;
if (!std::memcmp(target, expected_cluster.data(), 6)) {
return 0;
}
std::cerr << "Cluster " << cluster << " did not match expected results.\n"
<< "Expect: " << expected_cluster[0] << "\t" << expected_cluster[1]
<< "\t" << expected_cluster[4] << "\t" << expected_cluster[5]
<< "\t" << expected_cluster[2] << "\t" << expected_cluster[3]
<< "\n"
<< "Got: " << target[0] << "\t" << target[1] << "\t" << target[4]
<< "\t" << target[5] << "\t" << target[2] << "\t" << target[3]
<< '\n';
return 1;
}
int CheckRgbPixel(int pixel, int min_red, int max_red, int min_green,
int max_green, int min_blue, int max_blue,
const sapi::v::Array<uint8_t>& buffer) {
uint8_t* rgb = buffer.GetData() + 3 * pixel;
if (rgb[0] >= min_red && rgb[0] <= max_red && rgb[1] >= min_green &&
rgb[1] <= max_green && rgb[2] >= min_blue && rgb[2] <= max_blue) {
return 0;
}
std::cerr << "Pixel " << pixel << " did not match expected results.\n"
<< "Got R=" << rgb[0] << " (expected " << min_red << ".." << max_red
<< "), G=" << rgb[1] << " (expected " << min_green << ".."
<< max_green << "), B=" << rgb[2] << " (expected " << min_blue
<< ".." << max_blue << ")\n";
return 1;
}
int CheckRgbaPixel(int pixel, int min_red, int max_red, int min_green,
int max_green, int min_blue, int max_blue, int min_alpha,
int max_alpha, const sapi::v::Array<uint32_t>& buffer) {
// RGBA images are upside down - adjust for normal ordering
int adjusted_pixel = pixel % 128 + (127 - (pixel / 128)) * 128;
uint32_t rgba = buffer[adjusted_pixel];
if (TIFFGetR(rgba) >= static_cast<uint32_t>(min_red) &&
TIFFGetR(rgba) <= static_cast<uint32_t>(max_red) &&
TIFFGetG(rgba) >= static_cast<uint32_t>(min_green) &&
TIFFGetG(rgba) <= static_cast<uint32_t>(max_green) &&
TIFFGetB(rgba) >= static_cast<uint32_t>(min_blue) &&
TIFFGetB(rgba) <= static_cast<uint32_t>(max_blue) &&
TIFFGetA(rgba) >= static_cast<uint32_t>(min_alpha) &&
TIFFGetA(rgba) <= static_cast<uint32_t>(max_alpha)) {
return 0;
}
std::cerr << "Pixel " << pixel << " did not match expected results.\n"
<< "Got R=" << TIFFGetR(rgba) << " (expected " << min_red << ".."
<< max_red << "), G=" << TIFFGetG(rgba) << " (expected "
<< min_green << ".." << max_green << "), B=" << TIFFGetB(rgba)
<< " (expected " << min_blue << ".." << max_blue
<< "), A=" << TIFFGetA(rgba) << " (expected " << min_alpha << ".."
<< max_alpha << ")\n";
return 1;
}
std::string GetFilePath(const std::string& dir, const std::string& filename) {
return sandbox2::file::JoinPath(dir, "test", "images", filename);
}
std::string GetCWD() {
char cwd[PATH_MAX];
getcwd(cwd, sizeof(cwd));
return cwd;
}
std::string GetFilePath(const std::string filename) {
std::string cwd = GetCWD();
auto find = cwd.rfind("build");
std::string project_path;
if (find == std::string::npos) {
std::cerr << "Something went wrong: CWD don't contain build dir. "
<< "Please run tests from build dir or send project dir as a "
<< "parameter: ./sandboxed /absolute/path/to/project/dir \n";
project_path = cwd;
} else {
project_path = cwd.substr(0, find);
}
return sandbox2::file::JoinPath(project_path, "test", "images", filename);
}
} // namespace
int main(int argc, char** argv) {
gflags::ParseCommandLineFlags(&argc, &argv, true);
std::string srcfile;
// "test/images/quad-tile.jpg.tiff"
std::string srcfilerel = "quad-tile.jpg.tiff";
if (argc < 2) {
srcfile = GetFilePath(srcfilerel);
} else {
srcfile = GetFilePath(argv[1], srcfilerel);
}
// without addDir to sandbox. to add dir use
// sandbox(absolute_path_to_dir, srcfile) or
// sandbox(absolute_path_to_dir). file and dir should be exists.
// srcfile must also be absolute_path_to_file
TiffSapiSandbox sandbox("", srcfile);
// initialize sapi vars after constructing TiffSapiSandbox
sapi::v::UShort h, v;
sapi::StatusOr<TIFF*> status_or_tif;
sapi::StatusOr<int> status_or_int;
sapi::StatusOr<tmsize_t> status_or_long;
auto status = sandbox.Init();
if (!status.ok()) {
fprintf(stderr, "Couldn't initialize Sandboxed API: %s\n", status);
}
TiffApi api(&sandbox);
sapi::v::ConstCStr srcfile_var(srcfile.c_str());
sapi::v::ConstCStr r_var("r");
status_or_tif = api.TIFFOpen(srcfile_var.PtrBefore(), r_var.PtrBefore());
if (!status_or_tif.ok()) {
std::cerr << "Could not open " << srcfile << ", TIFFError\n";
return 1;
}
sapi::v::RemotePtr tif(status_or_tif.value());
if (!tif.GetValue()) {
// tif is NULL
std::cerr << "Could not open " << srcfile << "\n";
return 1;
}
status_or_int = api.TIFFGetField2(&tif, TIFFTAG_YCBCRSUBSAMPLING, h.PtrBoth(),
v.PtrBoth());
if (!status_or_int.ok() || status_or_int.value() == 0 || h.GetValue() != 2 ||
v.GetValue() != 2) {
std::cerr << "Could not retrieve subsampling tag\n";
return 1;
}
status_or_long = api.TIFFTileSize(&tif);
if (!status_or_int.ok() || status_or_long.value() != 24576) {
std::cerr << "tiles are " << status_or_long.value() << " bytes\n";
exit(1);
}
tsize_t sz = status_or_long.value();
sapi::v::Array<uint8_t> buffer_(sz);
status_or_long = api.TIFFReadEncodedTile(&tif, 9, buffer_.PtrBoth(), sz);
if (!status_or_long.ok() || status_or_long.value() != sz) {
std::cerr << "Did not get expected result code from"
<< "TIFFReadEncodedTile(): (" << status_or_long.value()
<< " instead of " << sz << ")\n";
return 1;
}
if (CheckCluster(0, buffer_, kCluster0) ||
CheckCluster(64, buffer_, kCluster64) ||
CheckCluster(128, buffer_, kCluster128)) {
return 1;
}
status_or_int =
api.TIFFSetFieldU1(&tif, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
if (!status_or_int.ok() || !status_or_int.value()) {
std::cerr << "TIFFSetFieldU1 not available\n";
}
status_or_long = api.TIFFTileSize(&tif);
if (!status_or_long.ok() || status_or_long.value() != 128 * 128 * 3) {
std::cerr << "tiles are " << status_or_long.value() << " bytes\n";
return 1;
}
sz = status_or_long.value();
sapi::v::Array<uint8_t> buffer2_(sz);
status_or_long = api.TIFFReadEncodedTile(&tif, 9, buffer2_.PtrBoth(), sz);
if (!status_or_long.ok() || status_or_long.value() != sz) {
std::cerr << "Did not get expected result code from "
<< "TIFFReadEncodedTile(): (" << status_or_long.value()
<< " instead of " << sz << ")\n";
return 1;
}
uint32_t pixel_status = 0;
pixel_status |= CheckRgbPixel(0, 15, 18, 0, 0, 18, 41, buffer2_);
pixel_status |= CheckRgbPixel(64, 0, 0, 0, 0, 0, 2, buffer2_);
pixel_status |= CheckRgbPixel(512, 5, 6, 34, 36, 182, 196, buffer2_);
if (!api.TIFFClose(&tif).ok()) {
std::cerr << "TIFFClose error\n";
}
status_or_tif = api.TIFFOpen(srcfile_var.PtrBefore(), r_var.PtrBefore());
if (!status_or_tif.ok()) {
std::cerr << "Could not reopen " << srcfile << "\n";
return 1;
}
sapi::v::RemotePtr tif2(status_or_tif.value());
if (!tif2.GetValue()) { // tif is NULL
std::cerr << "Could not reopen " << srcfile << "\n";
return 1;
}
sapi::v::Array<uint32> rgba_buffer_(128 * 128);
status_or_int =
api.TIFFReadRGBATile(&tif2, 1 * 128, 2 * 128, rgba_buffer_.PtrBoth());
if (!status_or_int.ok() || !status_or_int.value()) {
fprintf(stderr, "TIFFReadRGBATile() returned failure code.\n");
return 1;
}
pixel_status |=
CheckRgbaPixel(0, 15, 18, 0, 0, 18, 41, 255, 255, rgba_buffer_);
pixel_status |= CheckRgbaPixel(64, 0, 0, 0, 0, 0, 2, 255, 255, rgba_buffer_);
pixel_status |=
CheckRgbaPixel(512, 5, 6, 34, 36, 182, 196, 255, 255, rgba_buffer_);
if (!api.TIFFClose(&tif2).ok()) {
std::cerr << "TIFFClose erro\n";
}
if (pixel_status) {
std::cerr << "pixel_status is true, expected false";
return 1;
}
return 0;
}

View File

@ -0,0 +1,70 @@
// Copyright 2020 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
//
// http://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 LIBTIFF_SANDBOXED_H_
#define LIBTIFF_SANDBOXED_H_
#include <linux/futex.h>
#include <syscall.h>
#include <utility>
#include "sandboxed_api/util/flag.h"
#include "tiff_sapi.sapi.h" // NOLINT(build/include)
ABSL_DECLARE_FLAG(string, sandbox2_danger_danger_permit_all);
ABSL_DECLARE_FLAG(string, sandbox2_danger_danger_permit_all_and_log);
class TiffSapiSandbox : public TiffSandbox {
public:
explicit TiffSapiSandbox(std::string dir = "", std::string file = "")
: dir_(std::move(dir)), file_(std::move(file)) {}
private:
std::unique_ptr<sandbox2::Policy> ModifyPolicy(
sandbox2::PolicyBuilder*) override {
auto builder = sandbox2::PolicyBuilder()
.AllowRead()
.AllowStaticStartup()
.AllowWrite()
.AllowOpen()
.AllowExit()
.AllowStat()
.AllowSystemMalloc()
.AllowSyscalls({
__NR_futex,
__NR_close,
__NR_lseek,
__NR_gettid,
__NR_sysinfo,
__NR_mmap,
__NR_munmap,
});
if (!dir_.empty()) {
builder.AddDirectory(dir_, /*is_ro=*/false);
}
if (!file_.empty()) {
builder.AddFile(file_, /*is_ro=*/false);
}
return builder.BuildOrDie();
}
std::string dir_;
std::string file_;
};
#endif // LIBTIFF_SANDBOXED_H_

View File

@ -0,0 +1,37 @@
# Copyright 2020 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
#
# http://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(GoogleTest)
add_executable(tests
check_tag.h
check_tag.cc
defer_strile_writing.cc
long_tag.cc
raw_decode.cc
short_tag.cc
helper.h
helper.cc
)
target_link_libraries(tests PRIVATE
tiff_sapi
sapi::sapi
sandbox2::temp_file
gtest
gmock
gtest_main
)
gtest_discover_tests(tests)

View File

@ -0,0 +1,71 @@
// Copyright 2020 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
//
// http://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 "check_tag.h" // NOLINT(build/include)
using ::sapi::IsOk;
using ::testing::Eq;
using ::testing::IsFalse;
using ::testing::IsTrue;
// sapi functions:
// TIFFGetField
namespace {
void CheckShortField(TiffApi& api, sapi::v::RemotePtr& tif, const ttag_t field,
const uint16_t value) {
sapi::v::UShort tmp(123);
sapi::StatusOr<int> status_or_int;
status_or_int = api.TIFFGetField1(&tif, field, tmp.PtrBoth());
ASSERT_THAT(status_or_int, IsOk()) << "TIFFGetField1 fatal error";
EXPECT_THAT(status_or_int.value(), IsTrue())
<< "Problem fetching tag " << field;
EXPECT_THAT(tmp.GetValue(), Eq(value))
<< "Wrong SHORT value fetched for tag " << field;
}
void CheckShortPairedField(TiffApi& api, sapi::v::RemotePtr& tif,
const ttag_t field,
const std::array<uint16_t, 2>& values) {
sapi::v::UShort tmp0(123);
sapi::v::UShort tmp1(456);
sapi::StatusOr<int> status_or_int;
status_or_int =
api.TIFFGetField2(&tif, field, tmp0.PtrBoth(), tmp1.PtrBoth());
ASSERT_THAT(status_or_int, IsOk()) << "TIFFGetField2 fatal error";
EXPECT_THAT(status_or_int.value(), IsTrue())
<< "Problem fetching tag " << field;
EXPECT_THAT(tmp0.GetValue(), Eq(values[0]))
<< "Wrong SHORT PAIR[0] fetched for tag " << field;
EXPECT_THAT(tmp1.GetValue(), Eq(values[1]))
<< "Wrong SHORT PAIR[1] fetched for tag " << field;
}
void CheckLongField(TiffApi& api, sapi::v::RemotePtr& tif, const ttag_t field,
const uint32_t value) {
sapi::v::UInt tmp(123);
sapi::StatusOr<int> status_or_int;
status_or_int = api.TIFFGetField1(&tif, field, tmp.PtrBoth());
ASSERT_THAT(status_or_int, IsOk()) << "TIFFGetField1 fatal error";
EXPECT_THAT(status_or_int.value(), IsTrue())
<< "Problem fetching tag " << field;
EXPECT_THAT(tmp.GetValue(), Eq(value))
<< "Wrong LONG value fetched for tag " << field;
}
} // namespace

View File

@ -0,0 +1,31 @@
// Copyright 2020 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
//
// http://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 LIBTIFF_TEST_CHECK_TAG_H_
#define LIBTIFF_TEST_CHECK_TAG_H_
#include <cstdint>
#include "helper.h" // NOLINT(build/include)
#include "tiffio.h" // NOLINT(build/include)
void CheckShortField(TiffApi&, sapi::v::RemotePtr& tif, const ttag_t field,
const uint16_t value);
void CheckShortPairedField(TiffApi& api, sapi::v::RemotePtr& tif,
const ttag_t field,
const std::array<uint16_t, 2>& values);
void CheckLongField(TiffApi&, sapi::v::RemotePtr& tif, const ttag_t field,
const uint32_t value);
#endif // LIBTIFF_TEST_CHECK_TAG_H_

View File

@ -0,0 +1,332 @@
// Copyright 2020 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
//
// http://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 <cstdint>
#include "helper.h" // NOLINT(build/include)
#include "tiffio.h" // NOLINT(build/include)
using ::sapi::IsOk;
using ::testing::Eq;
using ::testing::IsTrue;
using ::testing::NotNull;
// sapi functions:
// TIFFOpen
// TIFFClose
// TIFFGetField
// TIFFSetField
// TIFFWriteCheck
// TIFFSetDirectory
// TIFFFreeDirectory
// TIFFWriteScanline
// TIFFWriteDirectory
// TIFFCreateDirectory
// TIFFReadEncodedTile
// TIFFReadEncodedStrip
// TIFFWriteEncodedTile
// TIFFWriteEncodedStrip
// TIFFDeferStrileArrayWriting
// TIFFForceStrileArrayWriting
namespace {
constexpr int kTileBufferSize = 256;
constexpr int kWidth = 1;
constexpr int kBps = 8;
constexpr int kRowsPerStrip = 1;
constexpr int kSamplePerPixel = 1;
void TestWriting(const char* mode, int tiled, int height) {
sapi::StatusOr<std::string> status_or_path =
sandbox2::CreateNamedTempFileAndClose("defer_strile_writing.tif");
ASSERT_THAT(status_or_path, IsOk()) << "Could not create temp file";
std::string srcfile = sandbox2::file::JoinPath(
sandbox2::file_util::fileops::GetCWD(), status_or_path.value());
sapi::StatusOr<int> status_or_int;
sapi::StatusOr<int64_t> status_or_long;
sapi::StatusOr<TIFF*> status_or_tif;
TiffSapiSandbox sandbox("", srcfile);
ASSERT_THAT(sandbox.Init(), IsOk()) << "Couldn't initialize Sandboxed API";
TiffApi api(&sandbox);
sapi::v::ConstCStr srcfile_var(srcfile.c_str());
sapi::v::ConstCStr mode_var(mode);
status_or_tif = api.TIFFOpen(srcfile_var.PtrBefore(), mode_var.PtrBefore());
ASSERT_THAT(status_or_tif, IsOk()) << "Could not open " << srcfile;
sapi::v::RemotePtr tif(status_or_tif.value());
ASSERT_THAT(tif.GetValue(), NotNull())
<< "Can't create test TIFF file " << srcfile;
status_or_int =
api.TIFFSetFieldU1(&tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
ASSERT_THAT(status_or_int, IsOk()) << "TIFFSetFieldU1 fatal error";
EXPECT_THAT(status_or_int.value(), IsTrue())
<< "Can't set CompressionNone tag";
status_or_int = api.TIFFSetFieldU1(&tif, TIFFTAG_IMAGEWIDTH, kWidth);
ASSERT_THAT(status_or_int, IsOk()) << "TIFFSetFieldU1 fatal error";
EXPECT_THAT(status_or_int.value(), IsTrue()) << "Can't set ImageWidth tag";
status_or_int = api.TIFFSetFieldU1(&tif, TIFFTAG_IMAGELENGTH, height);
ASSERT_THAT(status_or_int, IsOk()) << "TIFFSetFieldU1 fatal error";
EXPECT_THAT(status_or_int.value(), IsTrue()) << "Can't set ImageLenght tag";
status_or_int = api.TIFFSetFieldU1(&tif, TIFFTAG_BITSPERSAMPLE, kBps);
ASSERT_THAT(status_or_int, IsOk()) << "TIFFSetFieldU1 fatal error";
EXPECT_THAT(status_or_int.value(), IsTrue()) << "Can't set BitsPerSample tag";
status_or_int =
api.TIFFSetFieldU1(&tif, TIFFTAG_SAMPLESPERPIXEL, kSamplePerPixel);
ASSERT_THAT(status_or_int, IsOk()) << "TIFFSetFieldU1 fatal error";
EXPECT_THAT(status_or_int.value(), IsTrue())
<< "Can't set SamplesPerPixel tag";
status_or_int =
api.TIFFSetFieldU1(&tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
ASSERT_THAT(status_or_int, IsOk()) << "TIFFSetFieldU1 fatal error";
EXPECT_THAT(status_or_int.value(), IsTrue())
<< "Can't set PlanarConfiguration tag";
if (tiled) {
status_or_int = api.TIFFSetFieldU1(&tif, TIFFTAG_TILEWIDTH, 16);
ASSERT_THAT(status_or_int, IsOk()) << "TIFFSetFieldU1 fatal error";
EXPECT_THAT(status_or_int.value(), IsTrue()) << "Can't set TileWidth tag";
status_or_int = api.TIFFSetFieldU1(&tif, TIFFTAG_TILELENGTH, 16);
ASSERT_THAT(status_or_int, IsOk()) << "TIFFSetFieldU1 fatal error";
EXPECT_THAT(status_or_int.value(), IsTrue()) << "Can't set TileLenght tag";
} else {
status_or_int =
api.TIFFSetFieldU1(&tif, TIFFTAG_ROWSPERSTRIP, kRowsPerStrip);
ASSERT_THAT(status_or_int, IsOk()) << "TIFFSetFieldU1 fatal error";
EXPECT_THAT(status_or_int.value(), IsTrue())
<< "Can't set RowsPerStrip tag";
}
status_or_int = api.TIFFDeferStrileArrayWriting(&tif);
ASSERT_THAT(status_or_int, IsOk())
<< "TIFFDeferStrileArrayWriting fatal error";
EXPECT_THAT(status_or_int.value(), IsTrue())
<< "TIFFDeferStrileArrayWriting return unexpected value";
sapi::v::ConstCStr test_var("test");
status_or_int = api.TIFFWriteCheck(&tif, tiled, test_var.PtrBefore());
ASSERT_THAT(status_or_int, IsOk()) << "TIFFWriteCheck fatal error";
EXPECT_THAT(status_or_int.value(), IsTrue())
<< "TIFFWriteCheck return unexpected value "
<< "void test(" << mode << ", " << tiled << ", " << height << ")";
status_or_int = api.TIFFWriteDirectory(&tif);
ASSERT_THAT(status_or_int, IsOk())
<< "TIFFDeferStrileArrayWriting fatal error";
EXPECT_THAT(status_or_int.value(), IsTrue())
<< "TIFFDeferStrileArrayWriting return unexpected value";
// Create other directory
ASSERT_THAT(api.TIFFFreeDirectory(&tif), IsOk())
<< "TIFFFreeDirectory fatal error";
ASSERT_THAT(api.TIFFCreateDirectory(&tif), IsOk())
<< "TIFFCreateDirectory fatal error";
status_or_int = api.TIFFSetFieldU1(&tif, TIFFTAG_SUBFILETYPE, FILETYPE_PAGE);
ASSERT_THAT(status_or_int, IsOk()) << "TIFFSetFieldU1 fatal error";
EXPECT_THAT(status_or_int.value(), IsTrue()) << "Can't set SubFileType tag";
status_or_int =
api.TIFFSetFieldU1(&tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
ASSERT_THAT(status_or_int, IsOk()) << "TIFFSetFieldU1 fatal error";
EXPECT_THAT(status_or_int.value(), IsTrue())
<< "Can't set CompressionNone tag";
status_or_int = api.TIFFSetFieldU1(&tif, TIFFTAG_IMAGEWIDTH, kWidth);
ASSERT_THAT(status_or_int, IsOk()) << "TIFFSetFieldU1 fatal error";
EXPECT_THAT(status_or_int.value(), IsTrue()) << "Can't set ImageWidth tag";
status_or_int = api.TIFFSetFieldU1(&tif, TIFFTAG_IMAGELENGTH, 1);
ASSERT_THAT(status_or_int, IsOk()) << "TIFFSetFieldU1 fatal error";
EXPECT_THAT(status_or_int.value(), IsTrue()) << "Can't set ImageLenght tag";
status_or_int = api.TIFFSetFieldU1(&tif, TIFFTAG_BITSPERSAMPLE, kBps);
ASSERT_THAT(status_or_int, IsOk()) << "TIFFSetFieldU1 fatal error";
EXPECT_THAT(status_or_int.value(), IsTrue()) << "Can't set BitsPerSample tag";
status_or_int =
api.TIFFSetFieldU1(&tif, TIFFTAG_SAMPLESPERPIXEL, kSamplePerPixel);
ASSERT_THAT(status_or_int, IsOk()) << "TIFFSetFieldU1 fatal error";
EXPECT_THAT(status_or_int.value(), IsTrue())
<< "Can't set SamplesPerPixel tag";
status_or_int =
api.TIFFSetFieldU1(&tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
ASSERT_THAT(status_or_int, IsOk()) << "TIFFSetFieldU1 fatal error";
EXPECT_THAT(status_or_int.value(), IsTrue())
<< "Can't set PlanarConfiguration tag";
status_or_int = api.TIFFSetFieldU1(&tif, TIFFTAG_ROWSPERSTRIP, kRowsPerStrip);
ASSERT_THAT(status_or_int, IsOk()) << "TIFFSetFieldU1 fatal error";
EXPECT_THAT(status_or_int.value(), IsTrue()) << "Can't set RowsPerStrip tag";
status_or_int = api.TIFFDeferStrileArrayWriting(&tif);
ASSERT_THAT(status_or_int, IsOk())
<< "TIFFDeferStrileArrayWriting fatal error";
EXPECT_THAT(status_or_int.value(), IsTrue())
<< "TIFFDeferStrileArrayWriting return unexpected value";
status_or_int = api.TIFFWriteCheck(&tif, 0, test_var.PtrBefore());
ASSERT_THAT(status_or_int, IsOk()) << "TIFFWriteCheck fatal error";
EXPECT_THAT(status_or_int.value(), IsTrue())
<< "TIFFWriteCheck return unexpected value";
status_or_int = api.TIFFWriteDirectory(&tif);
ASSERT_THAT(status_or_int, IsOk()) << "TIFFWriteDirectory fatal error";
EXPECT_THAT(status_or_int.value(), IsTrue())
<< "TIFFWriteDirectory return unexpected value";
// Force writing of strile arrays
status_or_int = api.TIFFSetDirectory(&tif, 0);
ASSERT_THAT(status_or_int, IsOk()) << "TIFFSetDirectory fatal error";
EXPECT_THAT(status_or_int.value(), IsTrue())
<< "TIFFSetDirectory return unexpected value";
status_or_int = api.TIFFForceStrileArrayWriting(&tif);
ASSERT_THAT(status_or_int, IsOk())
<< "TIFFForceStrileArrayWriting fatal error";
EXPECT_THAT(status_or_int.value(), IsTrue())
<< "TIFFForceStrileArrayWriting return unexpected value";
status_or_int = api.TIFFSetDirectory(&tif, 1);
ASSERT_THAT(status_or_int, IsOk()) << "TIFFSetDirectory fatal error";
EXPECT_THAT(status_or_int.value(), IsTrue())
<< "TIFFSetDirectory return unexpected value";
status_or_int = api.TIFFForceStrileArrayWriting(&tif);
ASSERT_THAT(status_or_int, IsOk())
<< "TIFFForceStrileArrayWriting fatal error";
EXPECT_THAT(status_or_int.value(), IsTrue())
<< "TIFFForceStrileArrayWriting return unexpected value";
// Now write data on frist directory
status_or_int = api.TIFFSetDirectory(&tif, 0);
ASSERT_THAT(status_or_int, IsOk()) << "TIFFSetDirectory fatal error";
EXPECT_THAT(status_or_int.value(), IsTrue())
<< "TIFFSetDirectory return unexpected value";
if (tiled) {
for (int i = 0; i < (height + 15) / 16; ++i) {
std::array<uint8_t, kTileBufferSize> tilebuffer;
tilebuffer.fill(i);
sapi::v::Array<uint8_t> tilebuffer_(tilebuffer.data(), kTileBufferSize);
status_or_int = api.TIFFWriteEncodedTile(&tif, i, tilebuffer_.PtrBoth(),
kTileBufferSize);
ASSERT_THAT(status_or_int, IsOk()) << "TIFFWriteEncodedTile fatal error";
EXPECT_THAT(status_or_int.value(), Eq(kTileBufferSize))
<< "line " << i << ": expected 256, got " << status_or_int.value();
}
} else {
for (int i = 0; i < height; ++i) {
sapi::v::UChar c(i);
status_or_long = api.TIFFWriteEncodedStrip(&tif, i, c.PtrBoth(), 1);
ASSERT_THAT(status_or_long, IsOk())
<< "TIFFWriteEncodedStrip fatal error";
EXPECT_THAT(status_or_int.value(), Eq(1))
<< "line " << i << ": expected 1, got " << status_or_int.value();
if (i == 1 && height > 100000) {
i = height - 2;
}
}
}
ASSERT_THAT(api.TIFFClose(&tif), IsOk()) << "TIFFClose fatal error";
sapi::v::ConstCStr r_var("r");
status_or_tif = api.TIFFOpen(srcfile_var.PtrBefore(), r_var.PtrBefore());
ASSERT_THAT(status_or_tif, IsOk()) << "Could not open " << srcfile;
sapi::v::RemotePtr tif2(status_or_tif.value());
ASSERT_THAT(tif2.GetValue(), NotNull()) << "can't open " << srcfile;
if (tiled) {
for (int i = 0; i < (height + 15) / 16; ++i) {
for (int retry = 0; retry < 2; ++retry) {
std::array<uint8_t, kTileBufferSize> tilebuffer;
auto expected_c = static_cast<uint8_t>(i);
tilebuffer.fill(0);
sapi::v::Array<uint8_t> tilebuffer_(tilebuffer.data(), kTileBufferSize);
status_or_long = api.TIFFReadEncodedTile(
&tif2, i, tilebuffer_.PtrBoth(), kTileBufferSize);
ASSERT_THAT(status_or_long, IsOk())
<< "TIFFReadEncodedTile fatal error";
EXPECT_THAT(status_or_long.value(), Eq(kTileBufferSize))
<< "line " << i << ": expected 256, got " << status_or_long.value();
bool cmp = tilebuffer[0] != expected_c || tilebuffer[255] != expected_c;
EXPECT_THAT(tilebuffer[0], Eq(expected_c))
<< "unexpected value at tile " << i << ": expected " << expected_c
<< ", got " << tilebuffer[0];
EXPECT_THAT(tilebuffer[255], Eq(expected_c))
<< "unexpected value at tile " << i << ": expected " << expected_c
<< ", got " << tilebuffer[255];
if (cmp) {
ASSERT_THAT(api.TIFFClose(&tif2), IsOk()) << "TIFFClose fatal error";
}
}
}
} else {
for (int i = 0; i < height; ++i) {
for (int retry = 0; retry < 2; ++retry) {
sapi::v::UChar c(0);
auto expected_c = static_cast<uint8_t>(i);
status_or_long = api.TIFFReadEncodedStrip(&tif2, i, c.PtrBoth(), 1);
ASSERT_THAT(status_or_long, IsOk())
<< "TIFFReadEncodedStrip fatal error";
EXPECT_THAT(status_or_long.value(), Eq(1))
<< "line " << i << ": expected 1, got " << status_or_long.value();
EXPECT_THAT(c.GetValue(), Eq(expected_c))
<< "unexpected value at line " << i << ": expected " << expected_c
<< ", got " << c.GetValue();
if (c.GetValue() != expected_c) {
ASSERT_THAT(api.TIFFClose(&tif2), IsOk()) << "TIFFClose fatal error";
}
}
}
}
ASSERT_THAT(api.TIFFClose(&tif2), IsOk()) << "TIFFClose fatal error";
unlink(srcfile.c_str());
}
TEST(SandboxTest, DeferStrileWriting) {
for (int tiled = 0; tiled <= 1; ++tiled) {
TestWriting("w", tiled, 1);
TestWriting("w", tiled, 10);
TestWriting("w8", tiled, 1);
TestWriting("wD", tiled, 1);
}
}
} // namespace

View File

@ -0,0 +1,45 @@
// Copyright 2020 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
//
// http://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 "helper.h" // NOLINT(build/include)
#include <iostream>
auto* g_in_dir = new std::string();
std::string GetCWD() {
char cwd[PATH_MAX];
getcwd(cwd, sizeof(cwd));
return cwd;
}
std::string GetImagesDir() {
std::string cwd = GetCWD();
auto find = cwd.rfind("/build");
if (find == std::string::npos) {
std::cerr << "Something went wrong: CWD don't contain build dir. "
<< "Please run tests from build dir, path might be incorrect\n";
return cwd + "/test/images";
}
return cwd.substr(0, find) + "/test/images";
}
std::string GetFilePath(const std::string& filename) {
if (g_in_dir->empty()) {
*g_in_dir = GetImagesDir();
}
return sandbox2::file::JoinPath(*g_in_dir, filename);
}

View File

@ -0,0 +1,29 @@
// Copyright 2020 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
//
// http://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 LIBTIFF_TEST_HELPER_H_
#define LIBTIFF_TEST_HELPER_H_
#include <string>
#include "../sandboxed.h" // NOLINT(build/include)
#include "gtest/gtest.h"
#include "sandboxed_api/sandbox2/util/fileops.h"
#include "sandboxed_api/sandbox2/util/path.h"
#include "sandboxed_api/sandbox2/util/temp_file.h"
#include "sandboxed_api/util/status_matchers.h"
std::string GetFilePath(const std::string& filename);
#endif // LIBTIFF_TEST_HELPER_H_

View File

@ -0,0 +1,143 @@
// Copyright 2020 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
//
// http://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 <array>
#include <vector>
#include "check_tag.h" // NOLINT(build/include)
#include "tiffio.h" // NOLINT(build/include)
using ::sapi::IsOk;
using ::testing::IsTrue;
using ::testing::Ne;
using ::testing::NotNull;
// sapi functions:
// TIFFWriteScanline
// TIFFOpen
// TIFFClose
// TIFFGetField (from check_tag.c)
// TIFFSetField
namespace {
struct LongTag {
ttag_t tag;
int16_t count;
int32_t value;
};
constexpr std::array<LongTag, 1> kLongTags = {
{TIFFTAG_SUBFILETYPE, 1,
FILETYPE_REDUCEDIMAGE | FILETYPE_PAGE | FILETYPE_MASK}};
constexpr int kSamplesPerPixel = 3;
constexpr int kWidth = 1;
constexpr int kLength = 1;
constexpr int kBps = 8;
constexpr int kRowsPerStrip = 1;
TEST(SandboxTest, LongTag) {
sapi::StatusOr<std::string> status_or_path =
sandbox2::CreateNamedTempFileAndClose("long_test.tif");
ASSERT_THAT(status_or_path, IsOk()) << "Could not create temp file";
std::string srcfile = sandbox2::file::JoinPath(
sandbox2::file_util::fileops::GetCWD(), status_or_path.value());
TiffSapiSandbox sandbox("", srcfile);
ASSERT_THAT(sandbox.Init(), IsOk()) << "Couldn't initialize Sandboxed API";
std::array<uint8_t, SPP> buffer = {0, 127, 255};
sapi::v::Array<uint8_t> buffer_(buffer.data(), SPP);
sapi::StatusOr<int> status_or_int;
sapi::StatusOr<TIFF*> status_or_tif;
TiffApi api(&sandbox);
sapi::v::ConstCStr srcfile_var(srcfile.c_str());
sapi::v::ConstCStr w_var("w");
status_or_tif = api.TIFFOpen(srcfile_var.PtrBefore(), w_var.PtrBefore());
ASSERT_THAT(status_or_tif, IsOk()) << "Could not open " << srcfile;
sapi::v::RemotePtr tif(status_or_tif.value());
ASSERT_THAT(tif.GetValue(), NotNull())
<< "Can't create test TIFF file " << srcfile;
status_or_int = api.TIFFSetFieldU1(&tif, TIFFTAG_IMAGEWIDTH, kWidth);
ASSERT_THAT(status_or_int, IsOk()) << "TIFFSetFieldU1 fatal error";
EXPECT_THAT(status_or_int.value(), IsTrue()) << "Can't set ImageWidth tag";
status_or_int = api.TIFFSetFieldU1(&tif, TIFFTAG_IMAGELENGTH, kLength);
ASSERT_THAT(status_or_int, IsOk()) << "TIFFSetFieldU1 fatal error";
EXPECT_THAT(status_or_int.value(), IsTrue()) << "Can't set ImageLength tag";
status_or_int = api.TIFFSetFieldU1(&tif, TIFFTAG_BITSPERSAMPLE, kBps);
ASSERT_THAT(status_or_int, IsOk()) << "TIFFSetFieldU1 fatal error";
EXPECT_THAT(status_or_int.value(), IsTrue()) << "Can't set BitsPerSample tag";
status_or_int = api.TIFFSetFieldU1(&tif, TIFFTAG_SAMPLESPERPIXEL, SPP);
ASSERT_THAT(status_or_int, IsOk()) << "TIFFSetFieldU1 fatal error";
EXPECT_THAT(status_or_int.value(), IsTrue())
<< "Can't set SamplesPerPixel tag";
status_or_int = api.TIFFSetFieldU1(&tif, TIFFTAG_ROWSPERSTRIP, kRowsPerStrip);
ASSERT_THAT(status_or_int, IsOk()) << "TIFFSetFieldU1 fatal error";
EXPECT_THAT(status_or_int.value(), IsTrue()) << "Can't set RowsPerStrip tag";
status_or_int =
api.TIFFSetFieldU1(&tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
ASSERT_THAT(status_or_int, IsOk()) << "TIFFSetFieldU1 fatal error";
EXPECT_THAT(status_or_int.value(), IsTrue())
<< "Can't set PlanarConfiguration tag";
status_or_int =
api.TIFFSetFieldU1(&tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
ASSERT_THAT(status_or_int, IsOk()) << "TIFFSetFieldU1 fatal error";
EXPECT_THAT(status_or_int.value(), IsTrue())
<< "Can't set PhotometricInterpretation tag";
for (auto& tag : kLongTags) {
status_or_int = api.TIFFSetFieldU1(&tif, tag.tag, tag.value);
ASSERT_THAT(status_or_int, IsOk()) << "TIFFSetFieldUShort1 fatal error";
EXPECT_THAT(status_or_int.value(), IsTrue()) << "Can't set tag " << tag.tag;
}
status_or_int = api.TIFFWriteScanline(&tif, buffer_.PtrBoth(), 0, 0);
ASSERT_THAT(status_or_int, IsOk()) << "TIFFWriteScanline fatal error";
ASSERT_THAT(status_or_int.value(), Ne(-1)) << "Can't write image data";
ASSERT_THAT(api.TIFFClose(&tif), IsOk()) << "TIFFClose fatal error";
sapi::v::ConstCStr r_var("r");
status_or_tif = api.TIFFOpen(srcfile_var.PtrBefore(), r_var.PtrBefore());
ASSERT_THAT(status_or_tif, IsOk()) << "Could not open " << srcfile;
sapi::v::RemotePtr tif2(status_or_tif.value());
ASSERT_THAT(tif2.GetValue(), NotNull())
<< "Can't create test TIFF file " << srcfile;
CheckLongField(api, tif2, TIFFTAG_IMAGEWIDTH, kWidth);
CheckLongField(api, tif2, TIFFTAG_IMAGELENGTH, kLength);
CheckLongField(api, tif2, TIFFTAG_ROWSPERSTRIP, kRowsPerStrip);
for (auto& tag : kLongTags) {
CheckLongField(api, tif2, tag.tag, tag.value);
}
ASSERT_THAT(api.TIFFClose(&tif2), IsOk()) << "TIFFClose fatal error";
unlink(srcfile.c_str());
}
} // namespace

View File

@ -0,0 +1,207 @@
// Copyright 2020 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
//
// http://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 <array>
#include <cstdint>
#include <cstring>
#include "helper.h" // NOLINT(build/include)
#include "gtest/gtest.h"
#include "tiffio.h" // NOLINT(build/include)
using ::sapi::IsOk;
using ::testing::Eq;
using ::testing::IsFalse;
using ::testing::IsTrue;
using ::testing::NotNull;
// sapi functions:
// TIFFOpen
// TIFFClose
// TIFFGetField
// TIFFSetField
// TIFFTileSize
// TIFFReadRGBATile
// TIFFReadEncodedTile
namespace {
constexpr std::array<uint8_t, 6> kCluster0 = {0, 0, 2, 0, 138, 139};
constexpr std::array<uint8_t, 6> kCluster64 = {0, 0, 9, 6, 134, 119};
constexpr std::array<uint8_t, 6> kCluster128 = {44, 40, 63, 59, 230, 95};
int CheckCluster(int cluster, const sapi::v::Array<uint8_t> &buffer,
const std::vector<uint8_t> &expected_cluster) {
uint8_t *target = buffer.GetData() + cluster * 6;
bool comp = !(std::memcmp(target, expected_cluster.data(), 6) == 0);
EXPECT_THAT(comp, IsFalse())
<< "Cluster " << cluster << " did not match expected results.\n"
<< "Expect: " << expected_cluster[0] << "\t" << expected_cluster[1]
<< "\t" << expected_cluster[4] << "\t" << expected_cluster[5] << "\t"
<< expected_cluster[2] << "\t" << expected_cluster[3] << "\n"
<< "Got: " << target[0] << "\t" << target[1] << "\t" << target[4] << "\t"
<< target[5] << "\t" << target[2] << "\t" << target[3];
return comp;
}
int CheckRgbPixel(int pixel, int min_red, int max_red, int min_green,
int max_green, int min_blue, int max_blue,
const sapi::v::Array<uint8_t> &buffer) {
uint8_t *rgb = buffer.GetData() + 3 * pixel;
bool comp =
!(rgb[0] >= min_red && rgb[0] <= max_red && rgb[1] >= min_green &&
rgb[1] <= max_green && rgb[2] >= min_blue && rgb[2] <= max_blue);
EXPECT_THAT(comp, IsFalse())
<< "Pixel " << pixel << " did not match expected results.\n"
<< "Got R=" << rgb[0] << " (expected " << min_red << ".." << max_red
<< "), G=" << rgb[1] << " (expected " << min_green << ".." << max_green
<< "), B=" << rgb[2] << " (expected " << min_blue << ".." << max_blue
<< ")";
return comp;
}
int CheckRgbaPixel(int pixel, int min_red, int max_red, int min_green,
int max_green, int min_blue, int max_blue, int min_alpha,
int max_alpha, const sapi::v::Array<uint32_t> &buffer) {
// RGBA images are upside down - adjust for normal ordering
int adjusted_pixel = pixel % 128 + (127 - (pixel / 128)) * 128;
unsigned rgba = buffer[adjusted_pixel];
bool comp = !(TIFFGetR(rgba) >= static_cast<uint32_t>(min_red) &&
TIFFGetR(rgba) <= static_cast<uint32_t>(max_red) &&
TIFFGetG(rgba) >= static_cast<uint32_t>(min_green) &&
TIFFGetG(rgba) <= static_cast<uint32_t>(max_green) &&
TIFFGetB(rgba) >= static_cast<uint32_t>(min_blue) &&
TIFFGetB(rgba) <= static_cast<uint32_t>(max_blue) &&
TIFFGetA(rgba) >= static_cast<uint32_t>(min_alpha) &&
TIFFGetA(rgba) <= static_cast<uint32_t>(max_alpha));
EXPECT_THAT(comp, IsFalse())
<< "Pixel " << pixel << " did not match expected results.\n"
<< "Got R=" << TIFFGetR(rgba) << " (expected " << min_red << ".."
<< max_red << "), G=" << TIFFGetG(rgba) << " (expected " << min_green
<< ".." << max_green << "), B=" << TIFFGetB(rgba) << " (expected "
<< min_blue << ".." << max_blue << "), A=" << TIFFGetA(rgba)
<< " (expected " << min_alpha << ".." << max_alpha << ")";
return comp;
}
TEST(SandboxTest, RawDecode) {
std::string srcfile = GetFilePath("quad-tile.jpg.tiff");
TiffSapiSandbox sandbox("", srcfile);
ASSERT_THAT(sandbox.Init(), IsOk()) << "Couldn't initialize Sandboxed API";
tsize_t sz;
unsigned int pixel_status = 0;
sapi::v::UShort h, v;
sapi::StatusOr<TIFF> status_or_tif;
sapi::StatusOr<int> status_or_int;
sapi::StatusOr<tmsize_t> status_or_long;
TiffApi api(&sandbox);
sapi::v::ConstCStr srcfile_var(srcfile.c_str());
sapi::v::ConstCStr r_var("r");
status_or_tif = api.TIFFOpen(srcfile_var.PtrBefore(), r_var.PtrBefore());
ASSERT_THAT(status_or_tif, IsOk()) << "Could not open " << srcfile;
sapi::v::RemotePtr tif(status_or_tif.value());
ASSERT_THAT(tif.GetValue(), NotNull())
<< "Could not open " << srcfile << ", TIFFOpen return NULL";
status_or_int = api.TIFFGetField2(&tif, TIFFTAG_YCBCRSUBSAMPLING, h.PtrBoth(),
v.PtrBoth());
ASSERT_THAT(status_or_int, IsOk()) << "TIFFGetField2 fatal error";
EXPECT_THAT(
status_or_int.value() == 0 || h.GetValue() != 2 || v.GetValue() != 2,
IsFalse())
<< "Could not retrieve subsampling tag";
status_or_long = api.TIFFTileSize(&tif);
ASSERT_THAT(status_or_int, IsOk()) << "TIFFTileSize fatal error";
EXPECT_THAT(status_or_long.value(), Eq(24576))
<< "tiles are " << status_or_long.value() << " bytes";
sz = status_or_long.value();
sapi::v::Array<uint8_t> buffer_(sz);
status_or_long = api.TIFFReadEncodedTile(&tif, 9, buffer_.PtrBoth(), sz);
ASSERT_THAT(status_or_long, IsOk()) << "TIFFReadEncodedTile fatal error";
EXPECT_THAT(status_or_long.value(), Eq(sz))
<< "Did not get expected result code from TIFFReadEncodedTile()("
<< static_cast<int>(status_or_long.value()) << " instead of " << (int)sz
<< ")";
ASSERT_FALSE(CheckCluster(0, buffer_, kCluster0) ||
CheckCluster(64, buffer_, kCluster64) ||
CheckCluster(128, buffer_, kCluster128))
<< "Clusters did not match expected results";
status_or_int =
api.TIFFSetFieldU1(&tif, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
ASSERT_THAT(status_or_int, IsOk()) << "TIFFSetFieldU1 fatal error";
EXPECT_THAT(status_or_int.value(), IsTrue())
<< "TIFFSetFieldU1 not available";
status_or_long = api.TIFFTileSize(&tif);
ASSERT_THAT(status_or_long, IsOk()) << "TIFFTileSize fatal error";
EXPECT_THAT(status_or_long.value(), Eq(128 * 128 * 3))
<< "tiles are " << status_or_long.value() << " bytes";
sz = status_or_long.value();
sapi::v::Array<uint8_t> buffer2_(sz);
status_or_long = api.TIFFReadEncodedTile(&tif, 9, buffer2_.PtrBoth(), sz);
ASSERT_THAT(status_or_long, IsOk()) << "TIFFReadEncodedTile fatal error";
EXPECT_THAT(status_or_long.value(), Eq(sz))
<< "Did not get expected result code from TIFFReadEncodedTile()("
<< status_or_long.value() << " instead of " << sz;
pixel_status |= CheckRgbPixel(0, 15, 18, 0, 0, 18, 41, buffer2_);
pixel_status |= CheckRgbPixel(64, 0, 0, 0, 0, 0, 2, buffer2_);
pixel_status |= CheckRgbPixel(512, 5, 6, 34, 36, 182, 196, buffer2_);
ASSERT_THAT(api.TIFFClose(&tif), IsOk()) << "TIFFClose fatal error";
status_or_tif = api.TIFFOpen(srcfile_var.PtrBefore(), r_var.PtrBefore());
ASSERT_THAT(status_or_tif, IsOk()) << "TIFFOpen fatal error";
sapi::v::RemotePtr tif2(status_or_tif.value());
ASSERT_THAT(tif2.GetValue(), NotNull())
<< "Could not open " << srcfile << ", TIFFOpen return NULL";
sapi::v::Array<uint32_t> rgba_buffer_(128 * 128);
status_or_int =
api.TIFFReadRGBATile(&tif2, 1 * 128, 2 * 128, rgba_buffer_.PtrBoth());
ASSERT_THAT(status_or_int, IsOk()) << "TIFFReadRGBATile fatal error";
EXPECT_THAT(status_or_int.value(), IsTrue())
<< "TIFFReadRGBATile() returned failure code";
pixel_status |=
CheckRgbaPixel(0, 15, 18, 0, 0, 18, 41, 255, 255, rgba_buffer_);
pixel_status |= CheckRgbaPixel(64, 0, 0, 0, 0, 0, 2, 255, 255, rgba_buffer_);
pixel_status |=
CheckRgbaPixel(512, 5, 6, 34, 36, 182, 196, 255, 255, rgba_buffer_);
EXPECT_THAT(api.TIFFClose(&tif2), IsOk()) << "TIFFClose fatal error";
EXPECT_THAT(pixel_status, IsFalse()) << "wrong encoding";
}
} // namespace

View File

@ -0,0 +1,181 @@
// Copyright 2020 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
//
// http://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 <array>
#include <cstdint>
#include <vector>
#include "check_tag.h" // NOLINT(build/include)
#include "tiffio.h" // NOLINT(build/include)
using ::sapi::IsOk;
using ::testing::Eq;
using ::testing::IsFalse;
using ::testing::IsTrue;
using ::testing::NotNull;
// sapi functions:
// TIFFWriteScanline
// TIFFOpen
// TIFFClose
// TIFFGetField (from check_tag.c)
// TIFFSetField
namespace {
constexpr int kSamplePerPixel = 3;
constexpr int kWidth = 1;
constexpr int kLength = 1;
constexpr int kBps = 8;
constexpr int kPhotometric = PHOTOMETRIC_RGB;
constexpr int kRowsPerStrip = 1;
constexpr int kPlanarConfig = PLANARCONFIG_CONTIG;
struct SingleTag {
const ttag_t tag;
const uint16_t value;
};
struct PairedTag {
const ttag_t tag;
const std::array<uint16_t, 2> values;
};
constexpr std::array<SingleTag, 9> kShortSingleTags = {
{TIFFTAG_COMPRESSION, COMPRESSION_NONE},
{TIFFTAG_FILLORDER, FILLORDER_MSB2LSB},
{TIFFTAG_ORIENTATION, ORIENTATION_BOTRIGHT},
{TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH},
{TIFFTAG_MINSAMPLEVALUE, 23},
{TIFFTAG_MAXSAMPLEVALUE, 241},
{TIFFTAG_INKSET, INKSET_MULTIINK},
{TIFFTAG_NUMBEROFINKS, kSamplePerPixel},
{TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT}};
constexpr std::array<PairedTag, 4> kShortPairedTags = {
{TIFFTAG_PAGENUMBER, {1, 1}},
{TIFFTAG_HALFTONEHINTS, {0, 255}},
{TIFFTAG_DOTRANGE, {8, 16}},
{TIFFTAG_YCBCRSUBSAMPLING, {2, 1}}};
TEST(SandboxTest, ShortTag) {
sapi::StatusOr<std::string> status_or_path =
sandbox2::CreateNamedTempFileAndClose("short_test.tif");
ASSERT_THAT(status_or_path, IsOk()) << "Could not create temp file";
std::string srcfile = sandbox2::file::JoinPath(
sandbox2::file_util::fileops::GetCWD(), status_or_path.value());
TiffSapiSandbox sandbox("", srcfile);
ASSERT_THAT(sandbox.Init(), IsOk()) << "Couldn't initialize Sandboxed API";
std::array<uint8_t, kSamplePerPixel> buffer = {0, 127, 255};
sapi::v::Array<uint8_t> buffer_(buffer.data(), kSamplePerPixel);
sapi::StatusOr<int> status_or_int;
sapi::StatusOr<TIFF*> status_or_tif;
TiffApi api(&sandbox);
sapi::v::ConstCStr srcfile_var(srcfile.c_str());
sapi::v::ConstCStr w_var("w");
status_or_tif = api.TIFFOpen(srcfile_var.PtrBefore(), w_var.PtrBefore());
ASSERT_THAT(status_or_tif, IsOk()) << "Could not open " << srcfile;
sapi::v::RemotePtr tif(status_or_tif.value());
ASSERT_THAT(tif.GetValue(), NotNull())
<< "Can't create test TIFF file " << srcfile;
status_or_int = api.TIFFSetFieldUShort1(&tif, TIFFTAG_IMAGEWIDTH, kWidth);
ASSERT_THAT(status_or_int, IsOk()) << "TIFFSetFieldUShort1 fatal error";
EXPECT_THAT(status_or_int.value(), IsTrue()) << "Can't set ImagekWidth tag";
status_or_int = api.TIFFSetFieldUShort1(&tif, TIFFTAG_IMAGELENGTH, kLength);
ASSERT_THAT(status_or_int, IsOk()) << "TIFFSetFieldUShort1 fatal error";
EXPECT_THAT(status_or_int.value(), IsTrue()) << "Can't set ImageLength tag";
status_or_int = api.TIFFSetFieldUShort1(&tif, TIFFTAG_BITSPERSAMPLE, kBps);
ASSERT_THAT(status_or_int, IsOk()) << "TIFFSetFieldUShort1 fatal error";
EXPECT_THAT(status_or_int.value(), IsTrue()) << "Can't set BitsPerSample tag";
status_or_int =
api.TIFFSetFieldUShort1(&tif, TIFFTAG_SAMPLESPERPIXEL, kSamplePerPixel);
ASSERT_THAT(status_or_int, IsOk()) << "TIFFSetFieldUShort1 fatal error";
EXPECT_THAT(status_or_int.value(), IsTrue())
<< "Can't set SamplesPerPixel tag";
status_or_int =
api.TIFFSetFieldUShort1(&tif, TIFFTAG_ROWSPERSTRIP, kRowsPerStrip);
ASSERT_THAT(status_or_int, IsOk()) << "TIFFSetFieldUShort1 fatal error";
EXPECT_THAT(status_or_int.value(), IsTrue()) << "Can't set RowsPerStrip tag";
status_or_int =
api.TIFFSetFieldUShort1(&tif, TIFFTAG_PLANARCONFIG, kPlanarConfig);
ASSERT_THAT(status_or_int, IsOk()) << "TIFFSetFieldUShort1 fatal error";
EXPECT_THAT(status_or_int.value(), IsTrue())
<< "Can't set PlanarConfiguration tag";
status_or_int =
api.TIFFSetFieldUShort1(&tif, TIFFTAG_PHOTOMETRIC, kPhotometric);
ASSERT_THAT(status_or_int, IsOk()) << "TIFFSetFieldUShort1 fatal error";
EXPECT_THAT(status_or_int.value(), IsTrue())
<< "Can't set PhotometricInterpretation tag";
for (auto& tag : kShortSingleTags) {
status_or_int = api.TIFFSetFieldUShort1(&tif, tag.tag, tag.value);
ASSERT_THAT(status_or_int, IsOk()) << "TIFFSetFieldUShort1 fatal error";
EXPECT_THAT(status_or_int.value(), IsTrue()) << "Can't set tag " << tag.tag;
}
for (auto& tag : kShortPairedTags) {
status_or_int =
api.TIFFSetFieldUShort2(&tif, tag.tag, tag.values[0], tag.values[1]);
ASSERT_THAT(status_or_int, IsOk()) << "TIFFSetFieldUShort2 fatal error";
EXPECT_THAT(status_or_int.value(), IsTrue()) << "Can't set tag " << tag.tag;
}
status_or_int = api.TIFFWriteScanline(&tif, buffer_.PtrBoth(), 0, 0);
ASSERT_THAT(status_or_int, IsOk()) << "TIFFWriteScanline fatal error";
ASSERT_THAT(status_or_int.value(), Ne(-1)) << "Can't write image data";
ASSERT_THAT(api.TIFFClose(&tif), IsOk()) << "TIFFClose fatal error";
sapi::v::ConstCStr r_var("r");
status_or_tif = api.TIFFOpen(srcfile_var.PtrBefore(), r_var.PtrBefore());
ASSERT_THAT(status_or_tif, IsOk()) << "Could not open " << srcfile;
sapi::v::RemotePtr tif2(status_or_tif.value());
ASSERT_THAT(tif2.GetValue(), NotNull())
<< "Can't create test TIFF file " << srcfile;
CheckLongField(api, tif2, TIFFTAG_IMAGEWIDTH, kWidth);
CheckLongField(api, tif2, TIFFTAG_IMAGELENGTH, kLength);
CheckShortField(api, tif2, TIFFTAG_BITSPERSAMPLE, kBps);
CheckShortField(api, tif2, TIFFTAG_PHOTOMETRIC, kPhotometric);
CheckShortField(api, tif2, TIFFTAG_SAMPLESPERPIXEL, kSamplePerPixel);
CheckLongField(api, tif2, TIFFTAG_ROWSPERSTRIP, kRowsPerStrip);
CheckShortField(api, tif2, TIFFTAG_PLANARCONFIG, kPlanarConfig);
for (auto& tag : kShortSingleTags) {
CheckShortField(api, tif2, tag.tag, tag.value);
}
for (auto& tag : kShortPairedTags) {
CheckShortPairedField(api, tif2, tag.tag, tag.values);
}
ASSERT_THAT(api.TIFFClose(&tif2), IsOk()) << "TIFFClose fatal error";
}
} // namespace

View File

@ -0,0 +1,29 @@
# Copyright 2020 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
#
# http://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.
add_library(wrapped_tiff OBJECT
func.h
func.cc
)
set_target_properties(wrapped_tiff
PROPERTIES LINKER_LANGUAGE C
)
add_subdirectory(libtiff)
target_link_libraries(wrapped_tiff
sandbox2::temp_file
sapi::sapi
tiff
)

View File

@ -0,0 +1,163 @@
// Copyright 2020 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
//
// http://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 "func.h" // NOLINT(build/include)
int TIFFGetField1(TIFF* tif, uint32_t tag, void* param) {
return TIFFGetField(tif, tag, param);
}
int TIFFGetField2(TIFF* tif, uint32_t tag, void* param1, void* param2) {
return TIFFGetField(tif, tag, param1, param2);
}
int TIFFGetField3(TIFF* tif, uint32_t tag, void* param1, void* param2,
void* param3) {
return TIFFGetField(tif, tag, param1, param2, param3);
}
int TIFFSetFieldUChar1(TIFF* tif, uint32_t tag, uint8_t param) {
return TIFFSetField(tif, tag, param);
}
int TIFFSetFieldUChar2(TIFF* tif, uint32_t tag, uint8_t param1,
uint8_t param2) {
return TIFFSetField(tif, tag, param1, param2);
}
int TIFFSetFieldUChar3(TIFF* tif, uint32_t tag, uint8_t param1, uint8_t param2,
uint8_t param3) {
return TIFFSetField(tif, tag, param1, param2, param3);
}
int TIFFSetFieldSChar1(TIFF* tif, uint32_t tag, int8_t param) {
return TIFFSetField(tif, tag, param);
}
int TIFFSetFieldSChar2(TIFF* tif, uint32_t tag, int8_t param1, int8_t param2) {
return TIFFSetField(tif, tag, param1, param2);
}
int TIFFSetFieldSChar3(TIFF* tif, uint32_t tag, int8_t param1, int8_t param2,
int8_t param3) {
return TIFFSetField(tif, tag, param1, param2, param3);
}
int TIFFSetFieldU1(TIFF* tif, uint32_t tag, uint32_t param) {
return TIFFSetField(tif, tag, param);
}
int TIFFSetFieldU2(TIFF* tif, uint32_t tag, uint32_t param1, uint32_t param2) {
return TIFFSetField(tif, tag, param1, param2);
}
int TIFFSetFieldU3(TIFF* tif, uint32_t tag, uint32_t param1, uint32_t param2,
uint32_t param3) {
return TIFFSetField(tif, tag, param1, param2, param3);
}
int TIFFSetFieldS1(TIFF* tif, uint32_t tag, int param) {
return TIFFSetField(tif, tag, param);
}
int TIFFSetFieldS2(TIFF* tif, uint32_t tag, int param1, int param2) {
return TIFFSetField(tif, tag, param1, param2);
}
int TIFFSetFieldS3(TIFF* tif, uint32_t tag, int param1, int param2,
int param3) {
return TIFFSetField(tif, tag, param1, param2, param3);
}
int TIFFSetFieldUShort1(TIFF* tif, uint32_t tag, uint16_t param) {
return TIFFSetField(tif, tag, param);
}
int TIFFSetFieldUShort2(TIFF* tif, uint32_t tag, uint16_t param1,
uint16_t param2) {
return TIFFSetField(tif, tag, param1, param2);
}
int TIFFSetFieldUShort3(TIFF* tif, uint32_t tag, uint16_t param1,
uint16_t param2, uint16_t param3) {
return TIFFSetField(tif, tag, param1, param2, param3);
}
int TIFFSetFieldSShort1(TIFF* tif, uint32_t tag, int16_t param) {
return TIFFSetField(tif, tag, param);
}
int TIFFSetFieldSShort2(TIFF* tif, uint32_t tag, int16_t param1,
int16_t param2) {
return TIFFSetField(tif, tag, param1, param2);
}
int TIFFSetFieldSShort3(TIFF* tif, uint32_t tag, int16_t param1, int16_t param2,
int16_t param3) {
return TIFFSetField(tif, tag, param1, param2, param3);
}
int TIFFSetFieldULLong1(TIFF* tif, uint32_t tag, uint64_t param) {
return TIFFSetField(tif, tag, param);
}
int TIFFSetFieldULLong2(TIFF* tif, uint32_t tag, uint64_t param1,
uint64_t param2) {
return TIFFSetField(tif, tag, param1, param2);
}
int TIFFSetFieldULLong3(TIFF* tif, uint32_t tag, uint64_t param1,
uint64_t param2, uint64_t param3) {
return TIFFSetField(tif, tag, param1, param2, param3);
}
int TIFFSetFieldSLLong1(TIFF* tif, uint32_t tag, int64_t param) {
return TIFFSetField(tif, tag, param);
}
int TIFFSetFieldSLLong2(TIFF* tif, uint32_t tag, int64_t param1,
int64_t param2) {
return TIFFSetField(tif, tag, param1, param2);
}
int TIFFSetFieldSLLong3(TIFF* tif, uint32_t tag, int64_t param1, int64_t param2,
int64_t param3) {
return TIFFSetField(tif, tag, param1, param2, param3);
}
int TIFFSetFieldFloat1(TIFF* tif, uint32_t tag, float param) {
return TIFFSetField(tif, tag, param);
}
int TIFFSetFieldFloat2(TIFF* tif, uint32_t tag, float param1, float param2) {
return TIFFSetField(tif, tag, param1, param2);
}
int TIFFSetFieldFloat3(TIFF* tif, uint32_t tag, float param1, float param2,
float param3) {
return TIFFSetField(tif, tag, param1, param2, param3);
}
int TIFFSetFieldDouble1(TIFF* tif, uint32_t tag, double param) {
return TIFFSetField(tif, tag, param);
}
int TIFFSetFieldDouble2(TIFF* tif, uint32_t tag, double param1, double param2) {
return TIFFSetField(tif, tag, param1, param2);
}
int TIFFSetFieldDouble3(TIFF* tif, uint32_t tag, double param1, double param2,
double param3) {
return TIFFSetField(tif, tag, param1, param2, param3);
}

View File

@ -0,0 +1,88 @@
// Copyright 2020 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
//
// http://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 LIBTIFF_WRAPPER_FUNC_H_
#define LIBTIFF_WRAPPER_FUNC_H_
#include <cstdint>
#include "tiffio.h" // NOLINT(build/include)
// s - signed
// u - uint32_t
// wrapper for variadic functions TIFFGetField and TIFFSetField
extern "C" {
int TIFFGetField1(TIFF* tif, uint32_t tag, void* param);
int TIFFGetField2(TIFF* tif, uint32_t tag, void* param1, void* param2);
int TIFFGetField3(TIFF* tif, uint32_t tag, void* param1, void* param2,
void* param3);
int TIFFSetFieldUChar1(TIFF* tif, uint32_t tag, uint8_t param);
int TIFFSetFieldUChar2(TIFF* tif, uint32_t tag, uint8_t param1, uint8_t param2);
int TIFFSetFieldUChar3(TIFF* tif, uint32_t tag, uint8_t param1, uint8_t param2,
uint8_t param3);
int TIFFSetFieldSChar1(TIFF* tif, uint32_t tag, int8_t param);
int TIFFSetFieldSChar2(TIFF* tif, uint32_t tag, int8_t param1, int8_t param2);
int TIFFSetFieldSChar3(TIFF* tif, uint32_t tag, int8_t param1, int8_t param2,
int8_t param3);
int TIFFSetFieldU1(TIFF* tif, uint32_t tag, uint32_t param);
int TIFFSetFieldU2(TIFF* tif, uint32_t tag, uint32_t param1, uint32_t param2);
int TIFFSetFieldU3(TIFF* tif, uint32_t tag, uint32_t param1, uint32_t param2,
uint32_t param3);
int TIFFSetFieldS1(TIFF* tif, uint32_t tag, int param);
int TIFFSetFieldS2(TIFF* tif, uint32_t tag, int param1, int param2);
int TIFFSetFieldS3(TIFF* tif, uint32_t tag, int param1, int param2, int param3);
int TIFFSetFieldUShort1(TIFF* tif, uint32_t tag, uint16_t param);
int TIFFSetFieldUShort2(TIFF* tif, uint32_t tag, uint16_t param1,
uint16_t param2);
int TIFFSetFieldUShort3(TIFF* tif, uint32_t tag, uint16_t param1,
uint16_t param2, uint16_t param3);
int TIFFSetFieldSShort1(TIFF* tif, uint32_t tag, int16_t param);
int TIFFSetFieldSShort2(TIFF* tif, uint32_t tag, int16_t param1,
int16_t param2);
int TIFFSetFieldSShort3(TIFF* tif, uint32_t tag, int16_t param1, int16_t param2,
int16_t param3);
int TIFFSetFieldULLong1(TIFF* tif, uint32_t tag, uint64_t param);
int TIFFSetFieldULLong2(TIFF* tif, uint32_t tag, uint64_t param1,
uint64_t param2);
int TIFFSetFieldULLong3(TIFF* tif, uint32_t tag, uint64_t param1,
uint64_t param2, uint64_t param3);
int TIFFSetFieldSLLong1(TIFF* tif, uint32_t tag, int64_t param);
int TIFFSetFieldSLLong2(TIFF* tif, uint32_t tag, int64_t param1,
int64_t param2);
int TIFFSetFieldSLLong3(TIFF* tif, uint32_t tag, int64_t param1, int64_t param2,
int64_t param3);
int TIFFSetFieldFloat1(TIFF* tif, uint32_t tag, float param);
int TIFFSetFieldFloat2(TIFF* tif, uint32_t tag, float param1, float param2);
int TIFFSetFieldFloat3(TIFF* tif, uint32_t tag, float param1, float param2,
float param3);
int TIFFSetFieldDouble1(TIFF* tif, uint32_t tag, double param);
int TIFFSetFieldDouble2(TIFF* tif, uint32_t tag, double param1, double param2);
int TIFFSetFieldDouble3(TIFF* tif, uint32_t tag, double param1, double param2,
double param3);
} // extern "C"
#endif // LIBTIFF_WRAPPER_FUNC_H_

@ -0,0 +1 @@
Subproject commit c8f0a16f4ad10cd5d595bd5614104e2ecf52ee92