// Copyright (c) the JPEG XL Project Authors. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file.
Status ConvertFromExternalNoSizeCheck(const uint8_t* data, size_t xsize,
size_t ysize, size_t stride, const ColorEncoding& c_current,
size_t color_channels,
size_t bits_per_sample,
JxlPixelFormat format, ThreadPool* pool,
ImageBundle* ib) {
JxlMemoryManager* memory_manager = ib->memory_manager(); bool has_alpha = format.num_channels == 2 || format.num_channels == 4; if (format.num_channels < color_channels) { return JXL_FAILURE("Expected %" PRIuS " color channels, received only %u channels",
color_channels, format.num_channels);
}
JXL_ASSIGN_OR_RETURN(Image3F color,
Image3F::Create(memory_manager, xsize, ysize)); for (size_t c = 0; c < color_channels; ++c) {
JXL_RETURN_IF_ERROR(ConvertFromExternalNoSizeCheck(
data, xsize, ysize, stride, bits_per_sample, format, c, pool,
&color.Plane(c)));
} if (color_channels == 1) {
JXL_RETURN_IF_ERROR(CopyImageTo(color.Plane(0), &color.Plane(1)));
JXL_RETURN_IF_ERROR(CopyImageTo(color.Plane(0), &color.Plane(2)));
}
JXL_RETURN_IF_ERROR(ib->SetFromImage(std::move(color), c_current));
// Passing an interleaved image with an alpha channel to an image that doesn't // have alpha channel just discards the passed alpha channel. if (has_alpha && ib->HasAlpha()) {
JXL_ASSIGN_OR_RETURN(ImageF alpha,
ImageF::Create(memory_manager, xsize, ysize));
JXL_RETURN_IF_ERROR(ConvertFromExternalNoSizeCheck(
data, xsize, ysize, stride, bits_per_sample, format,
format.num_channels - 1, pool, &alpha));
JXL_RETURN_IF_ERROR(ib->SetAlpha(std::move(alpha)));
} elseif (!has_alpha && ib->HasAlpha()) { // if alpha is not passed, but it is expected, then assume // it is all-opaque
JXL_ASSIGN_OR_RETURN(ImageF alpha,
ImageF::Create(memory_manager, xsize, ysize));
FillImage(1.0f, &alpha);
JXL_RETURN_IF_ERROR(ib->SetAlpha(std::move(alpha)));
}
returntrue;
}
Status ConvertFromExternal(const uint8_t* data, size_t size, size_t xsize,
size_t ysize, size_t bits_per_sample,
JxlPixelFormat format, size_t c, ThreadPool* pool,
ImageF* channel) {
size_t bytes_per_channel = JxlDataTypeBytes(format.data_type);
size_t bytes_per_pixel = format.num_channels * bytes_per_channel; const size_t last_row_size = xsize * bytes_per_pixel; const size_t align = format.align; const size_t row_size =
(align > 1 ? jxl::DivCeil(last_row_size, align) * align : last_row_size); const size_t bytes_to_read = row_size * (ysize - 1) + last_row_size; if (xsize == 0 || ysize == 0) return JXL_FAILURE("Empty image"); if (size > 0 && size < bytes_to_read) { return JXL_FAILURE("Buffer size is too small, expected: %" PRIuS " got: %" PRIuS " (Image: %" PRIuS "x%" PRIuS "x%u, bytes_per_channel: %" PRIuS ")",
bytes_to_read, size, xsize, ysize, format.num_channels,
bytes_per_channel);
} // Too large buffer is likely an application bug, so also fail for that. // Do allow padding to stride in last row though. if (size > row_size * ysize) { return JXL_FAILURE("Buffer size is too large");
} return ConvertFromExternalNoSizeCheck(
data, xsize, ysize, row_size, bits_per_sample, format, c, pool, channel);
}
Status ConvertFromExternal(Span<const uint8_t> bytes, size_t xsize,
size_t ysize, const ColorEncoding& c_current,
size_t color_channels, size_t bits_per_sample,
JxlPixelFormat format, ThreadPool* pool,
ImageBundle* ib) {
JxlMemoryManager* memory_manager = ib->memory_manager(); bool has_alpha = format.num_channels == 2 || format.num_channels == 4; if (format.num_channels < color_channels) { return JXL_FAILURE("Expected %" PRIuS " color channels, received only %u channels",
color_channels, format.num_channels);
}
JXL_ASSIGN_OR_RETURN(Image3F color,
Image3F::Create(memory_manager, xsize, ysize)); for (size_t c = 0; c < color_channels; ++c) {
JXL_RETURN_IF_ERROR(ConvertFromExternal(bytes.data(), bytes.size(), xsize,
ysize, bits_per_sample, format, c,
pool, &color.Plane(c)));
} if (color_channels == 1) {
JXL_RETURN_IF_ERROR(CopyImageTo(color.Plane(0), &color.Plane(1)));
JXL_RETURN_IF_ERROR(CopyImageTo(color.Plane(0), &color.Plane(2)));
}
JXL_RETURN_IF_ERROR(ib->SetFromImage(std::move(color), c_current));
// Passing an interleaved image with an alpha channel to an image that doesn't // have alpha channel just discards the passed alpha channel. if (has_alpha && ib->HasAlpha()) {
JXL_ASSIGN_OR_RETURN(ImageF alpha,
ImageF::Create(memory_manager, xsize, ysize));
JXL_RETURN_IF_ERROR(ConvertFromExternal(
bytes.data(), bytes.size(), xsize, ysize, bits_per_sample, format,
format.num_channels - 1, pool, &alpha));
JXL_RETURN_IF_ERROR(ib->SetAlpha(std::move(alpha)));
} elseif (!has_alpha && ib->HasAlpha()) { // if alpha is not passed, but it is expected, then assume // it is all-opaque
JXL_ASSIGN_OR_RETURN(ImageF alpha,
ImageF::Create(memory_manager, xsize, ysize));
FillImage(1.0f, &alpha);
JXL_RETURN_IF_ERROR(ib->SetAlpha(std::move(alpha)));
}
returntrue;
}
Status ConvertFromExternal(Span<const uint8_t> bytes, size_t xsize,
size_t ysize, const ColorEncoding& c_current,
size_t bits_per_sample, JxlPixelFormat format,
ThreadPool* pool, ImageBundle* ib) { return ConvertFromExternal(bytes, xsize, ysize, c_current,
c_current.Channels(), bits_per_sample, format,
pool, ib);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.