from local repo to fork

This commit is contained in:
Alexandra Latysheva 2020-09-23 20:21:33 +00:00
parent 9331eabd7e
commit 673154e65c
21 changed files with 1841 additions and 0 deletions

3
.gitmodules vendored
View File

@ -7,3 +7,6 @@
[submodule "oss-internship-2020/curl/curl_wrapper/curl"] [submodule "oss-internship-2020/curl/curl_wrapper/curl"]
path = oss-internship-2020/curl/curl_wrapper/curl path = oss-internship-2020/curl/curl_wrapper/curl
url = https://github.com/curl/curl url = https://github.com/curl/curl
[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,129 @@
# 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
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
# List of functions that we want to include in the
# generated sandboxed API class
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,279 @@
// 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 <cstring>
#include <iostream>
#include <vector>
#include "../sandboxed.h"
#include "sandboxed_api/sandbox2/util/fileops.h"
#include "sandboxed_api/sandbox2/util/path.h"
#include "tiffio.h"
/* sapi functions:
* TIFFTileSize
* TIFFOpen
* TIFFReadEncodedTile
* TIFFSetField
* TIFFClose
* TIFFReadRGBATile
* TIFFGetField
*/
static const std::vector<unsigned char> cluster_0 = {0, 0, 2, 0, 138, 139};
static const std::vector<unsigned char> cluster_64 = {0, 0, 9, 6, 134, 119};
static const std::vector<unsigned char> cluster_128 = {44, 40, 63, 59, 230, 95};
static int check_cluster(int cluster,
const sapi::v::Array<unsigned char> &buffer,
const std::vector<unsigned char> &expected_cluster) {
unsigned char *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;
}
static int check_rgb_pixel(int pixel, int min_red, int max_red, int min_green,
int max_green, int min_blue, int max_blue,
const sapi::v::Array<unsigned char> &buffer) {
unsigned char *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;
}
static int check_rgba_pixel(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<unsigned> &buffer) {
// RGBA images are upside down - adjust for normal ordering
int adjusted_pixel = pixel % 128 + (127 - (pixel / 128)) * 128;
uint32 rgba = buffer[adjusted_pixel];
if (TIFFGetR(rgba) >= (uint32)min_red && TIFFGetR(rgba) <= (uint32)max_red &&
TIFFGetG(rgba) >= (uint32)min_green &&
TIFFGetG(rgba) <= (uint32)max_green &&
TIFFGetB(rgba) >= (uint32)min_blue &&
TIFFGetB(rgba) <= (uint32)max_blue &&
TIFFGetA(rgba) >= (uint32)min_alpha &&
TIFFGetA(rgba) <= (uint32)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);
}
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<unsigned char> 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 (check_cluster(0, buffer_, cluster_0) ||
check_cluster(64, buffer_, cluster_64) ||
check_cluster(128, buffer_, cluster_128)) {
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<unsigned char> 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;
}
unsigned pixel_status = 0;
pixel_status |= check_rgb_pixel(0, 15, 18, 0, 0, 18, 41, buffer2_);
pixel_status |= check_rgb_pixel(64, 0, 0, 0, 0, 0, 2, buffer2_);
pixel_status |= check_rgb_pixel(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 |=
check_rgba_pixel(0, 15, 18, 0, 0, 18, 41, 255, 255, rgba_buffer_);
pixel_status |=
check_rgba_pixel(64, 0, 0, 0, 0, 0, 2, 255, 255, rgba_buffer_);
pixel_status |=
check_rgba_pixel(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,68 @@
// 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 <linux/futex.h>
#include <syscall.h>
#include <utility>
#include "sandboxed_api/util/flag.h"
#include "tiff_sapi.sapi.h"
ABSL_DECLARE_FLAG(string, sandbox2_danger_danger_permit_all);
ABSL_DECLARE_FLAG(string, sandbox2_danger_danger_permit_all_and_log);
namespace {
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 = std::make_unique<sandbox2::PolicyBuilder>();
(*builder)
.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.get()->BuildOrDie();
}
std::string dir_, file_;
};
} // namespace

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,63 @@
// 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"
/* sapi functions:
* TIFFGetField
*/
void CheckShortField(TiffApi& api, sapi::v::RemotePtr& tif, const ttag_t field,
const unsigned short 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<unsigned short, 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 unsigned 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;
}

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.
#include "helper.h"
#include "tiffio.h"
void CheckShortField(TiffApi&, sapi::v::RemotePtr& tif, const ttag_t field,
const unsigned short value);
void CheckShortPairedField(TiffApi& api, sapi::v::RemotePtr& tif,
const ttag_t field,
const std::array<unsigned short, 2>& values);
void CheckLongField(TiffApi&, sapi::v::RemotePtr& tif, const ttag_t field,
const unsigned value);

View File

@ -0,0 +1,322 @@
// 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"
#include "tiffio.h"
/* sapi functions:
* TIFFOpen
* TIFFClose
* TIFFGetField
* TIFFSetField
* TIFFWriteCheck
* TIFFSetDirectory
* TIFFFreeDirectory
* TIFFWriteScanline
* TIFFWriteDirectory
* TIFFCreateDirectory
* TIFFReadEncodedTile
* TIFFReadEncodedStrip
* TIFFWriteEncodedTile
* TIFFWriteEncodedStrip
* TIFFDeferStrileArrayWriting
* TIFFForceStrileArrayWriting
*/
#define TBS 256 // kTileBufferSize
static const unsigned short kWidth = 1;
static const unsigned short kBps = 8;
static const unsigned short kRowsPerStrip = 1;
static const unsigned short kSamplePerPixel = 1;
void test_writing(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<signed long> 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<unsigned char, TBS> tilebuffer;
tilebuffer.fill(i);
sapi::v::Array<unsigned char> tilebuffer_(tilebuffer.data(), TBS);
status_or_int =
api.TIFFWriteEncodedTile(&tif, i, tilebuffer_.PtrBoth(), TBS);
ASSERT_THAT(status_or_int, IsOk()) << "TIFFWriteEncodedTile fatal error";
EXPECT_THAT(status_or_int.value(), Eq(TBS))
<< "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<unsigned char, TBS> tilebuffer;
unsigned char expected_c = (unsigned char)i;
tilebuffer.fill(0);
sapi::v::Array<unsigned char> tilebuffer_(tilebuffer.data(), TBS);
status_or_long =
api.TIFFReadEncodedTile(&tif2, i, tilebuffer_.PtrBoth(), TBS);
ASSERT_THAT(status_or_long, IsOk())
<< "TIFFReadEncodedTile fatal error";
EXPECT_THAT(status_or_long.value(), Eq(TBS))
<< "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);
unsigned char expected_c = (unsigned char)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) {
test_writing("w", tiled, 1);
test_writing("w", tiled, 10);
test_writing("w8", tiled, 1);
test_writing("wD", tiled, 1);
}
}

View File

@ -0,0 +1,51 @@
// 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"
#include <iostream>
std::string inDir;
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 (inDir.empty()) {
inDir = GetImagesDir();
}
return sandbox2::file::JoinPath(inDir, filename);
}
std::string GetOutPath() { return GetImagesDir() + '/' + kOutDir; }
std::string GetNewFilePath(const std::string& filename) {
return GetOutPath() + '/' + filename;
}

View File

@ -0,0 +1,35 @@
// 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 <string>
#include "../sandboxed.h"
#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"
const std::string kOutDir = "output";
using ::sapi::IsOk;
using ::testing::Eq;
using ::testing::IsFalse;
using ::testing::IsTrue;
using ::testing::Ne;
using ::testing::NotNull;
std::string GetOutPath();
std::string GetFilePath(const std::string& filename);
std::string GetNewFilePath(const std::string& filename);

View File

@ -0,0 +1,135 @@
// 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"
#include "tiffio.h"
/* sapi functions:
* TIFFWriteScanline
* TIFFOpen
* TIFFClose
* TIFFGetField (from check_tag.c)
* TIFFSetField
*/
struct long_tag {
ttag_t tag;
short count;
unsigned value;
};
const std::vector<long_tag> long_tags = {
{TIFFTAG_SUBFILETYPE, 1,
FILETYPE_REDUCEDIMAGE | FILETYPE_PAGE | FILETYPE_MASK}};
#define SPP 3 // kSamplePerPixel
static const unsigned kWidth = 1;
static const unsigned kLength = 1;
static const unsigned kBps = 8;
static const unsigned 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<unsigned char, SPP> buffer = {0, 127, 255};
sapi::v::Array<unsigned char> 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 : long_tags) {
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 : long_tags) {
CheckLongField(api, tif2, tag.tag, tag.value);
}
ASSERT_THAT(api.TIFFClose(&tif2), IsOk()) << "TIFFClose fatal error";
unlink(srcfile.c_str());
}

View File

@ -0,0 +1,198 @@
// 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 <cstring>
#include "gtest/gtest.h"
#include "helper.h"
#include "tiffio.h"
/* sapi functions:
* TIFFOpen
* TIFFClose
* TIFFGetField
* TIFFSetField
* TIFFTileSize
* TIFFReadRGBATile
* TIFFReadEncodedTile
*/
static const std::vector<unsigned char> cluster_0 = {0, 0, 2, 0, 138, 139};
static const std::vector<unsigned char> cluster_64 = {0, 0, 9, 6, 134, 119};
static const std::vector<unsigned char> cluster_128 = {44, 40, 63, 59, 230, 95};
static int check_cluster(int cluster,
const sapi::v::Array<unsigned char> &buffer,
const std::vector<unsigned char> &expected_cluster) {
unsigned char *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;
}
static int check_rgb_pixel(int pixel, int min_red, int max_red, int min_green,
int max_green, int min_blue, int max_blue,
const sapi::v::Array<unsigned char> &buffer) {
unsigned char *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;
}
static int check_rgba_pixel(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<unsigned> &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) >= (unsigned)min_red &&
TIFFGetR(rgba) <= (unsigned)max_red &&
TIFFGetG(rgba) >= (unsigned)min_green &&
TIFFGetG(rgba) <= (unsigned)max_green &&
TIFFGetB(rgba) >= (unsigned)min_blue &&
TIFFGetB(rgba) <= (unsigned)max_blue &&
TIFFGetA(rgba) >= (unsigned)min_alpha &&
TIFFGetA(rgba) <= (unsigned)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<unsigned char> 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()("
<< (int)status_or_long.value() << " instead of " << (int)sz << ")";
ASSERT_FALSE(check_cluster(0, buffer_, cluster_0) ||
check_cluster(64, buffer_, cluster_64) ||
check_cluster(128, buffer_, cluster_128))
<< "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<unsigned char> 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 |= check_rgb_pixel(0, 15, 18, 0, 0, 18, 41, buffer2_);
pixel_status |= check_rgb_pixel(64, 0, 0, 0, 0, 0, 2, buffer2_);
pixel_status |= check_rgb_pixel(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<unsigned> 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 |=
check_rgba_pixel(0, 15, 18, 0, 0, 18, 41, 255, 255, rgba_buffer_);
pixel_status |=
check_rgba_pixel(64, 0, 0, 0, 0, 0, 2, 255, 255, rgba_buffer_);
pixel_status |=
check_rgba_pixel(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";
}

View File

@ -0,0 +1,170 @@
// 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"
#include "tiffio.h"
/* sapi functions:
* TIFFWriteScanline
* TIFFOpen
* TIFFClose
* TIFFGetField (from check_tag.c)
* TIFFSetField
*/
#define SPP 3 // kSamplePerPixel
static const unsigned short kWidth = 1;
static const unsigned short kLength = 1;
static const unsigned short kBps = 8;
static const unsigned short kPhotometric = PHOTOMETRIC_RGB;
static const unsigned short kRowsPerStrip = 1;
static const unsigned short kPlanarConfig = PLANARCONFIG_CONTIG;
struct single_tag {
const ttag_t tag;
const unsigned short value;
};
struct paired_tag {
const ttag_t tag;
const std::array<unsigned short, 2> values;
};
static const std::vector<single_tag> short_single_tags = {
{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, SPP},
{TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT}};
static const std::vector<paired_tag> short_paired_tags = {
{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<unsigned char, SPP> buffer = {0, 127, 255};
sapi::v::Array<unsigned char> 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.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, SPP);
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 : short_single_tags) {
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 : short_paired_tags) {
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, SPP);
CheckLongField(api, tif2, TIFFTAG_ROWSPERSTRIP, kRowsPerStrip);
CheckShortField(api, tif2, TIFFTAG_PLANARCONFIG, kPlanarConfig);
for (auto& tag : short_single_tags) {
CheckShortField(api, tif2, tag.tag, tag.value);
}
for (auto& tag : short_paired_tags) {
CheckShortPairedField(api, tif2, tag.tag, tag.values);
}
ASSERT_THAT(api.TIFFClose(&tif2), IsOk()) << "TIFFClose fatal error";
}

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"
int TIFFGetField1(TIFF* tif, unsigned tag, void* param) {
return TIFFGetField(tif, tag, param);
}
int TIFFGetField2(TIFF* tif, unsigned tag, void* param1, void* param2) {
return TIFFGetField(tif, tag, param1, param2);
}
int TIFFGetField3(TIFF* tif, unsigned tag, void* param1, void* param2,
void* param3) {
return TIFFGetField(tif, tag, param1, param2, param3);
}
int TIFFSetFieldUChar1(TIFF* tif, unsigned tag, unsigned char param) {
return TIFFSetField(tif, tag, param);
}
int TIFFSetFieldUChar2(TIFF* tif, unsigned tag, unsigned char param1,
unsigned char param2) {
return TIFFSetField(tif, tag, param1, param2);
}
int TIFFSetFieldUChar3(TIFF* tif, unsigned tag, unsigned char param1,
unsigned char param2, unsigned char param3) {
return TIFFSetField(tif, tag, param1, param2, param3);
}
int TIFFSetFieldSChar1(TIFF* tif, unsigned tag, signed char param) {
return TIFFSetField(tif, tag, param);
}
int TIFFSetFieldSChar2(TIFF* tif, unsigned tag, signed char param1,
signed char param2) {
return TIFFSetField(tif, tag, param1, param2);
}
int TIFFSetFieldSChar3(TIFF* tif, unsigned tag, signed char param1,
signed char param2, signed char param3) {
return TIFFSetField(tif, tag, param1, param2, param3);
}
int TIFFSetFieldU1(TIFF* tif, unsigned tag, unsigned param) {
return TIFFSetField(tif, tag, param);
}
int TIFFSetFieldU2(TIFF* tif, unsigned tag, unsigned param1, unsigned param2) {
return TIFFSetField(tif, tag, param1, param2);
}
int TIFFSetFieldU3(TIFF* tif, unsigned tag, unsigned param1, unsigned param2,
unsigned param3) {
return TIFFSetField(tif, tag, param1, param2, param3);
}
int TIFFSetFieldS1(TIFF* tif, unsigned tag, int param) {
return TIFFSetField(tif, tag, param);
}
int TIFFSetFieldS2(TIFF* tif, unsigned tag, int param1, int param2) {
return TIFFSetField(tif, tag, param1, param2);
}
int TIFFSetFieldS3(TIFF* tif, unsigned tag, int param1, int param2,
int param3) {
return TIFFSetField(tif, tag, param1, param2, param3);
}
int TIFFSetFieldUShort1(TIFF* tif, unsigned tag, unsigned short param) {
return TIFFSetField(tif, tag, param);
}
int TIFFSetFieldUShort2(TIFF* tif, unsigned tag, unsigned short param1,
unsigned short param2) {
return TIFFSetField(tif, tag, param1, param2);
}
int TIFFSetFieldUShort3(TIFF* tif, unsigned tag, unsigned short param1,
unsigned short param2, unsigned short param3) {
return TIFFSetField(tif, tag, param1, param2, param3);
}
int TIFFSetFieldSShort1(TIFF* tif, unsigned tag, short param) {
return TIFFSetField(tif, tag, param);
}
int TIFFSetFieldSShort2(TIFF* tif, unsigned tag, short param1, short param2) {
return TIFFSetField(tif, tag, param1, param2);
}
int TIFFSetFieldSShort3(TIFF* tif, unsigned tag, short param1, short param2,
short param3) {
return TIFFSetField(tif, tag, param1, param2, param3);
}
int TIFFSetFieldULLong1(TIFF* tif, unsigned tag, unsigned long long param) {
return TIFFSetField(tif, tag, param);
}
int TIFFSetFieldULLong2(TIFF* tif, unsigned tag, unsigned long long param1,
unsigned long long param2) {
return TIFFSetField(tif, tag, param1, param2);
}
int TIFFSetFieldULLong3(TIFF* tif, unsigned tag, unsigned long long param1,
unsigned long long param2, unsigned long long param3) {
return TIFFSetField(tif, tag, param1, param2, param3);
}
int TIFFSetFieldSLLong1(TIFF* tif, unsigned tag, long long param) {
return TIFFSetField(tif, tag, param);
}
int TIFFSetFieldSLLong2(TIFF* tif, unsigned tag, long long param1,
long long param2) {
return TIFFSetField(tif, tag, param1, param2);
}
int TIFFSetFieldSLLong3(TIFF* tif, unsigned tag, long long param1,
long long param2, long long param3) {
return TIFFSetField(tif, tag, param1, param2, param3);
}
int TIFFSetFieldFloat1(TIFF* tif, unsigned tag, float param) {
return TIFFSetField(tif, tag, param);
}
int TIFFSetFieldFloat2(TIFF* tif, unsigned tag, float param1, float param2) {
return TIFFSetField(tif, tag, param1, param2);
}
int TIFFSetFieldFloat3(TIFF* tif, unsigned tag, float param1, float param2,
float param3) {
return TIFFSetField(tif, tag, param1, param2, param3);
}
int TIFFSetFieldDouble1(TIFF* tif, unsigned tag, double param) {
return TIFFSetField(tif, tag, param);
}
int TIFFSetFieldDouble2(TIFF* tif, unsigned tag, double param1, double param2) {
return TIFFSetField(tif, tag, param1, param2);
}
int TIFFSetFieldDouble3(TIFF* tif, unsigned tag, double param1, double param2,
double param3) {
return TIFFSetField(tif, tag, param1, param2, param3);
}

View File

@ -0,0 +1,86 @@
// 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 "tiffio.h"
/* s - signed
* u - unsigned
* wrapper for variadic functions TIFFGetField and TIFFSetField
*/
extern "C" {
int TIFFGetField1(TIFF* tif, unsigned tag, void* param);
int TIFFGetField2(TIFF* tif, unsigned tag, void* param1, void* param2);
int TIFFGetField3(TIFF* tif, unsigned tag, void* param1, void* param2,
void* param3);
int TIFFSetFieldUChar1(TIFF* tif, unsigned tag, unsigned char param);
int TIFFSetFieldUChar2(TIFF* tif, unsigned tag, unsigned char param1,
unsigned char param2);
int TIFFSetFieldUChar3(TIFF* tif, unsigned tag, unsigned char param1,
unsigned char param2, unsigned char param3);
int TIFFSetFieldSChar1(TIFF* tif, unsigned tag, signed char param);
int TIFFSetFieldSChar2(TIFF* tif, unsigned tag, signed char param1,
signed char param2);
int TIFFSetFieldSChar3(TIFF* tif, unsigned tag, signed char param1,
signed char param2, signed char param3);
int TIFFSetFieldU1(TIFF* tif, unsigned tag, unsigned param);
int TIFFSetFieldU2(TIFF* tif, unsigned tag, unsigned param1, unsigned param2);
int TIFFSetFieldU3(TIFF* tif, unsigned tag, unsigned param1, unsigned param2,
unsigned param3);
int TIFFSetFieldS1(TIFF* tif, unsigned tag, int param);
int TIFFSetFieldS2(TIFF* tif, unsigned tag, int param1, int param2);
int TIFFSetFieldS3(TIFF* tif, unsigned tag, int param1, int param2, int param3);
int TIFFSetFieldUShort1(TIFF* tif, unsigned tag, unsigned short param);
int TIFFSetFieldUShort2(TIFF* tif, unsigned tag, unsigned short param1,
unsigned short param2);
int TIFFSetFieldUShort3(TIFF* tif, unsigned tag, unsigned short param1,
unsigned short param2, unsigned short param3);
int TIFFSetFieldSShort1(TIFF* tif, unsigned tag, short param);
int TIFFSetFieldSShort2(TIFF* tif, unsigned tag, short param1, short param2);
int TIFFSetFieldSShort3(TIFF* tif, unsigned tag, short param1, short param2,
short param3);
int TIFFSetFieldULLong1(TIFF* tif, unsigned tag, unsigned long long param);
int TIFFSetFieldULLong2(TIFF* tif, unsigned tag, unsigned long long param1,
unsigned long long param2);
int TIFFSetFieldULLong3(TIFF* tif, unsigned tag, unsigned long long param1,
unsigned long long param2, unsigned long long param3);
int TIFFSetFieldSLLong1(TIFF* tif, unsigned tag, long long param);
int TIFFSetFieldSLLong2(TIFF* tif, unsigned tag, long long param1,
long long param2);
int TIFFSetFieldSLLong3(TIFF* tif, unsigned tag, long long param1,
long long param2, long long param3);
int TIFFSetFieldFloat1(TIFF* tif, unsigned tag, float param);
int TIFFSetFieldFloat2(TIFF* tif, unsigned tag, float param1, float param2);
int TIFFSetFieldFloat3(TIFF* tif, unsigned tag, float param1, float param2,
float param3);
int TIFFSetFieldDouble1(TIFF* tif, unsigned tag, double param);
int TIFFSetFieldDouble2(TIFF* tif, unsigned tag, double param1, double param2);
int TIFFSetFieldDouble3(TIFF* tif, unsigned tag, double param1, double param2,
double param3);
}
#endif

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