Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion tests/cts
Submodule cts updated 44 files
+1 −1 clitests/.gitignore
+3 −0 clitests/CMakeLists.txt
+1 −0 clitests/golden/create/cli_errors/assign_tcorigin_invalid_lower.err.txt
+1 −0 clitests/golden/create/cli_errors/assign_tcorigin_invalid_z_first.err.txt
+1 −0 clitests/golden/create/cli_errors/cvt_tcorigin_3d_no_z.err.txt
+1 −0 clitests/golden/create/cli_errors/cvt_tcorigin_cubemap_not_top_left.err.txt
+1 −0 clitests/golden/create/cli_errors/cvt_tcorigin_invalid_left_only.err.txt
+1 −0 clitests/golden/create/cli_errors/cvt_tcorigin_invalid_lower.err.txt
+1 −0 clitests/golden/create/cli_errors/cvt_tcorigin_invalid_no_underscore.err.txt
+1 −0 clitests/golden/create/cli_errors/cvt_tcorigin_raw.err.txt
+26 −0 clitests/golden/create/help/help.out.txt
+ clitests/golden/create/line_order_exr/decreasing.ktx2
+ clitests/golden/create/line_order_exr/increasing.ktx2
+ clitests/golden/create/texcoord_origin/output_R16G16B16A16_SFLOAT_assign_bottom_left.ktx2
+ clitests/golden/create/texcoord_origin/output_R16G16B16A16_SFLOAT_assign_top_left.ktx2
+ clitests/golden/create/texcoord_origin/output_R16G16B16A16_SFLOAT_convert_bottom_left.ktx2
+ clitests/golden/create/texcoord_origin/output_R16G16B16A16_SFLOAT_convert_top_left.ktx2
+ clitests/golden/create/texcoord_origin/output_R8G8B8A8_SRGB_assign_bottom_left.ktx2
+ clitests/golden/create/texcoord_origin/output_R8G8B8A8_SRGB_assign_top_left.ktx2
+ clitests/golden/create/texcoord_origin/output_R8G8B8A8_SRGB_convert_bottom_left.ktx2
+ clitests/golden/create/texcoord_origin/output_R8G8B8A8_SRGB_convert_top_left.ktx2
+ clitests/golden/create/texcoord_origin/output_R8G8B8_SRGB_assign_bottom_left.ktx2
+ clitests/golden/create/texcoord_origin/output_R8G8B8_SRGB_assign_top_left.ktx2
+ clitests/golden/create/texcoord_origin/output_R8G8B8_SRGB_convert_bottom_left.ktx2
+ clitests/golden/create/texcoord_origin/output_R8G8B8_SRGB_convert_top_left.ktx2
+ clitests/golden/create/texcoord_origin/output_R8G8_UNORM_assign_bottom_left.ktx2
+ clitests/golden/create/texcoord_origin/output_R8G8_UNORM_assign_top_left.ktx2
+ clitests/golden/create/texcoord_origin/output_R8G8_UNORM_convert_bottom_left.ktx2
+ clitests/golden/create/texcoord_origin/output_R8G8_UNORM_convert_top_left.ktx2
+ clitests/golden/create/texcoord_origin/output_R8_UNORM_assign_bottom_left.ktx2
+ clitests/golden/create/texcoord_origin/output_R8_UNORM_assign_top_left.ktx2
+ clitests/golden/create/texcoord_origin/output_R8_UNORM_convert_bottom_left.ktx2
+ clitests/golden/create/texcoord_origin/output_R8_UNORM_convert_top_left.ktx2
+1 −0 clitests/golden/create/warn-fail-texcoord-origin/conversion.err.txt
+1 −0 clitests/golden/create/warn-fail-texcoord-origin/conversion.warn.txt
+0 −0 clitests/golden/create/warn-fail-texcoord-origin/empty.err.txt
+ clitests/input/exr/line_order_decreasing.exr
+ clitests/input/exr/line_order_increasing.exr
+ clitests/input/exr_sample/test_this_way_up_RGB_HALF_128x128.exr
+ clitests/input/png_sample/test_this_way_up_sRGB_128x128.png
+9 −1 clitests/tests/create/cli_errors.json
+15 −0 clitests/tests/create/line_order_exr.json
+23 −0 clitests/tests/create/texcoord_origin.json
+19 −0 clitests/tests/create/warn_fail_texcoord_origin.json
12 changes: 12 additions & 0 deletions tools/imageio/exr.imageio/exrinput.cc
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,8 @@ void ExrInput::open(ImageSpec& newspec) {
width,
height,
1,
// We make TinyEXR decode to top-left.
ImageSpec::Origin(ImageSpec::Origin::eLeft, ImageSpec::Origin::eTop),
header.num_channels,
bitDepth,
static_cast<khr_df_sample_datatype_qualifiers_e>(qualifiers),
Expand Down Expand Up @@ -236,6 +238,13 @@ void ExrInput::readImage(void* outputBuffer, size_t bufferByteCount,
fmt::format("EXR load error: {}.", "Unsupported EXR version (2.0)"));

// Load image data

// TinyEXR decodes images so that the first bytes in the returned buffer
// are the top-left corner of the image with line_order == 0 "increasing Y"
// and the bottom-left corner otherwise, "decreasing Y". Force a top-left
// origin regardless of the line_order in the file. See
// https://github.com/syoyo/tinyexr/issues/213 for more information.
header.line_order = 0;
ec = LoadEXRImageFromMemory(&image, &header, exrBuffer.data(), exrBuffer.size(), &err);
if (ec != TINYEXR_SUCCESS)
throw std::runtime_error(fmt::format("EXR load error: {} - {}.", ec, err));
Expand Down Expand Up @@ -263,6 +272,9 @@ void ExrInput::readImage(void* outputBuffer, size_t bufferByteCount,
channels[3] = i;
else
warning(fmt::format("EXR load warning: Unrecognized channel \"{}\" is ignored.", header.channels[i].name));
// TODO: check for 1 channel "Y" and make greyscale texture.
// TODO: check for "Y", "RY" and "BY" (luminance/chroma) and reject as unsupported.
// TODO: check for "AR", "AG", "AB" and make texture with pre-multipled alpha provided there is also an A channel? Or reject?
}

// Copy the data
Expand Down
89 changes: 83 additions & 6 deletions tools/imageio/imageio.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,18 +50,49 @@ const stride_t AutoStride = std::numeric_limits<stride_t>::min();
typedef bool (*ProgressCallback)(void *opaque_data, float portion_done);

class ImageSpec {
public:
struct Origin {
uint8_t x;
uint8_t y;
uint8_t z;

static const uint8_t eLeft = 0;
static const uint8_t eRight = 1;
static const uint8_t eTop = 0;
static const uint8_t eBottom = 1;
static const uint8_t eFront = 0;
static const uint8_t eBack = 1;
static const uint8_t eUnspecified = 0xff;

// This is the most common origin among image file formats, hence
// the no arg constructor sets it. If unspecified, use the 3 arg ctor.
Origin() : x(eLeft), y(eTop), z(eFront) { };
Origin(uint8_t _x, uint8_t _y) : x(_x), y(_y), z(eFront) { }
Origin(uint8_t _x, uint8_t _y, uint8_t _z) : x(_x), y(_y), z(_z) { }

bool unspecified() {
return x == eUnspecified || y == eUnspecified || z == eUnspecified;
}
};

protected:
FormatDescriptor formatDesc;
uint32_t imageWidth; ///< width of the pixel data
uint32_t imageHeight; ///< height of the pixel data
uint32_t imageDepth; ///< depth of pixel data, >1 indicates a "volume"
Origin imageOrigin; ///< logical corner of image that is the first pixel in the data stream

public:
ImageSpec() : imageWidth(0), imageHeight(0), imageDepth(0) { }
ImageSpec() : imageWidth(0), imageHeight(0),
imageDepth(0), imageOrigin() { }

ImageSpec(uint32_t w, uint32_t h, uint32_t d, FormatDescriptor& formatDesc)
: ImageSpec(w, h, d, Origin(), formatDesc) { }

ImageSpec(uint32_t w, uint32_t h, uint32_t d, FormatDescriptor formatDesc)
ImageSpec(uint32_t w, uint32_t h, uint32_t d, Origin&& o,
FormatDescriptor formatDesc)
: formatDesc(std::move(formatDesc)),
imageWidth(w), imageHeight(h), imageDepth(d) { }
imageWidth(w), imageHeight(h), imageDepth(d), imageOrigin(o) { }

ImageSpec(uint32_t w, uint32_t h, uint32_t d,
uint32_t channelCount, uint32_t channelBitCount,
Expand All @@ -71,8 +102,19 @@ class ImageSpec {
khr_df_primaries_e p = KHR_DF_PRIMARIES_BT709,
khr_df_model_e m = KHR_DF_MODEL_RGBSDA,
khr_df_flags_e f = KHR_DF_FLAG_ALPHA_STRAIGHT)
: ImageSpec(w, h, d, Origin(), channelCount,
channelBitCount, dt, t, p, m, f) { }

ImageSpec(uint32_t w, uint32_t h, uint32_t d, Origin&& o,
uint32_t channelCount, uint32_t channelBitCount,
khr_df_sample_datatype_qualifiers_e dt
= static_cast<khr_df_sample_datatype_qualifiers_e>(0),
khr_df_transfer_e t = KHR_DF_TRANSFER_UNSPECIFIED,
khr_df_primaries_e p = KHR_DF_PRIMARIES_BT709,
khr_df_model_e m = KHR_DF_MODEL_RGBSDA,
khr_df_flags_e f = KHR_DF_FLAG_ALPHA_STRAIGHT)
: formatDesc(channelCount, channelBitCount, dt, t, p, m, f),
imageWidth(w), imageHeight(h), imageDepth(d) { }
imageWidth(w), imageHeight(h), imageDepth(d), imageOrigin(o) { }

ImageSpec(uint32_t w, uint32_t h, uint32_t d,
uint32_t channelCount, uint32_t channelBitCount,
Expand All @@ -83,10 +125,23 @@ class ImageSpec {
khr_df_primaries_e p = KHR_DF_PRIMARIES_BT709,
khr_df_model_e m = KHR_DF_MODEL_RGBSDA,
khr_df_flags_e f = KHR_DF_FLAG_ALPHA_STRAIGHT)
: ImageSpec(w, h, d, Origin(), channelCount,
channelBitCount,channelLower, channelUpper,
dt, t, p, m, f) { }

ImageSpec(uint32_t w, uint32_t h, uint32_t d, Origin&& o,
uint32_t channelCount, uint32_t channelBitCount,
uint32_t channelLower, uint32_t channelUpper,
khr_df_sample_datatype_qualifiers_e dt
= static_cast<khr_df_sample_datatype_qualifiers_e>(0),
khr_df_transfer_e t = KHR_DF_TRANSFER_UNSPECIFIED,
khr_df_primaries_e p = KHR_DF_PRIMARIES_BT709,
khr_df_model_e m = KHR_DF_MODEL_RGBSDA,
khr_df_flags_e f = KHR_DF_FLAG_ALPHA_STRAIGHT)
: formatDesc(channelCount, channelBitCount,
channelLower, channelUpper,
dt, t, p, m, f),
imageWidth(w), imageHeight(h), imageDepth(d) { }
imageWidth(w), imageHeight(h), imageDepth(d), imageOrigin(o) { }

ImageSpec(uint32_t w, uint32_t h, uint32_t d,
uint32_t channelCount, std::vector<uint32_t>& channelBitLengths,
Expand All @@ -97,9 +152,21 @@ class ImageSpec {
khr_df_primaries_e p = KHR_DF_PRIMARIES_BT709,
khr_df_model_e m = KHR_DF_MODEL_RGBSDA,
khr_df_flags_e f = KHR_DF_FLAG_ALPHA_STRAIGHT)
: ImageSpec(w, h, d, Origin(), channelCount,
channelBitLengths, channelTypes, dt, t, p, m, f) { }

ImageSpec(uint32_t w, uint32_t h, uint32_t d, Origin&& o,
uint32_t channelCount, std::vector<uint32_t>& channelBitLengths,
std::vector<khr_df_model_channels_e>& channelTypes,
khr_df_sample_datatype_qualifiers_e dt
= static_cast<khr_df_sample_datatype_qualifiers_e>(0),
khr_df_transfer_e t = KHR_DF_TRANSFER_UNSPECIFIED,
khr_df_primaries_e p = KHR_DF_PRIMARIES_BT709,
khr_df_model_e m = KHR_DF_MODEL_RGBSDA,
khr_df_flags_e f = KHR_DF_FLAG_ALPHA_STRAIGHT)
: formatDesc(channelCount, channelBitLengths,
channelTypes, dt, t, p, m, f),
imageWidth(w), imageHeight(h), imageDepth(d) { }
imageWidth(w), imageHeight(h), imageDepth(d), imageOrigin(o) { }


FormatDescriptor& format() { return formatDesc; }
Expand All @@ -108,10 +175,12 @@ class ImageSpec {
uint32_t width() const noexcept { return imageWidth; }
uint32_t height() const noexcept { return imageHeight; }
uint32_t depth() const noexcept { return imageDepth; }
const Origin& origin() const noexcept { return imageOrigin; }

void setWidth(uint32_t w) { imageWidth = w; }
void setHeight(uint32_t h) { imageHeight = h; }
void setDepth(uint32_t d) { imageDepth = d; }
void setOrigin(const Origin& o) { imageOrigin = o; }

size_t imagePixelCount() const noexcept {
return depth() * width() * height();
Expand All @@ -134,6 +203,14 @@ class ImageSpec {
}
};

constexpr bool operator==(const ImageSpec::Origin& lhs, const ImageSpec::Origin& rhs) {
return lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z;
}

constexpr bool operator!=(const ImageSpec::Origin& lhs, const ImageSpec::Origin& rhs) {
return lhs.x != rhs.x || lhs.y != rhs.y || lhs.z != rhs.z;
}

typedef std::function<void(const std::string&)> WarningCallbackFunction;

enum class ImageInputFormatType {
Expand Down
1 change: 1 addition & 0 deletions tools/imageio/jpg.imageio/jpginput.cc
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ JpegInput::readHeader()
// return what the decode() method will return not what is in the file.

images.emplace_back(ImageSpec(pJd->get_width(), pJd->get_height(), 1,
ImageSpec::Origin(ImageSpec::Origin::eLeft, ImageSpec::Origin::eTop),
pJd->get_num_components(), 8, // component bit length
static_cast<khr_df_sample_datatype_qualifiers_e>(0),
KHR_DF_TRANSFER_SRGB,
Expand Down
13 changes: 7 additions & 6 deletions tools/imageio/npbm.imageio/npbminput.cc
Original file line number Diff line number Diff line change
Expand Up @@ -404,12 +404,13 @@ void NpbmInput::parseGPHeader(filetype ftype)
}

images.emplace_back(ImageSpec(width, height, 1,
ftype == filetype::PPM ? 3 : 1, 8,
0, maxVal,
static_cast<khr_df_sample_datatype_qualifiers_e>(0),
KHR_DF_TRANSFER_ITU,
KHR_DF_PRIMARIES_BT709,
ftype == filetype::PPM
ImageSpec::Origin(ImageSpec::Origin::eLeft, ImageSpec::Origin::eTop),
ftype == filetype::PPM ? 3 : 1, 8,
0, maxVal,
static_cast<khr_df_sample_datatype_qualifiers_e>(0),
KHR_DF_TRANSFER_ITU,
KHR_DF_PRIMARIES_BT709,
ftype == filetype::PPM
? KHR_DF_MODEL_RGBSDA
: KHR_DF_MODEL_YUVSDA),
ImageInputFormatType::npbm);
Expand Down
4 changes: 3 additions & 1 deletion tools/imageio/png.imageio/pnginput.cc
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,9 @@ PngInput::readHeader()
break;
}

images.emplace_back(ImageSpec(w, h, 1, componentCount,
images.emplace_back(ImageSpec(w, h, 1,
ImageSpec::Origin(ImageSpec::Origin::eLeft, ImageSpec::Origin::eTop),
componentCount,
bitDepth,
static_cast<khr_df_sample_datatype_qualifiers_e>(0),
KHR_DF_TRANSFER_UNSPECIFIED,
Expand Down
Loading
Loading