mirror of
https://github.com/SerenityOS/serenity.git
synced 2026-11-07 12:38:38 -10:00
It seems that `bool has_next() / Y next()` interface is somewhat more natural compared to `bool is_done() / Optional<Y> next()`.
335 lines
16 KiB
C++
335 lines
16 KiB
C++
/*
|
||
* Copyright (c) 2025, Nico Weber <[email protected]>
|
||
*
|
||
* SPDX-License-Identifier: BSD-2-Clause
|
||
*/
|
||
|
||
#include <LibGfx/ImageFormats/JPEG2000ProgressionIterators.h>
|
||
|
||
namespace Gfx::JPEG2000 {
|
||
|
||
LayerResolutionLevelComponentPositionProgressionIterator::LayerResolutionLevelComponentPositionProgressionIterator(int layer_count, int max_number_of_decomposition_levels, int component_count, Function<int(int resolution_level, int component)> precinct_count)
|
||
: m_layer_count(layer_count)
|
||
, m_max_number_of_decomposition_levels(max_number_of_decomposition_levels)
|
||
, m_component_count(component_count)
|
||
, m_precinct_count(move(precinct_count))
|
||
, m_generator(generator())
|
||
|
||
{
|
||
}
|
||
|
||
bool LayerResolutionLevelComponentPositionProgressionIterator::has_next() const
|
||
{
|
||
return m_generator.has_next();
|
||
}
|
||
|
||
ProgressionData LayerResolutionLevelComponentPositionProgressionIterator::next()
|
||
{
|
||
return m_generator.next();
|
||
}
|
||
|
||
SyncGenerator<ProgressionData> LayerResolutionLevelComponentPositionProgressionIterator::generator()
|
||
{
|
||
// B.12.1.1 Layer-resolution level-component-position progression
|
||
// "for each l = 0,..., L – 1
|
||
// for each r = 0,..., Nmax
|
||
// for each i = 0,..., Csiz – 1
|
||
// for each k = 0,..., numprecincts – 1
|
||
// packet for component i, resolution level r, layer l, and precinct k.
|
||
// Here, L is the number of layers and Nmax is the maximum number of decomposition levels, N_L, used in any component of the tile."
|
||
// FIXME: This always iterates up to Nmax, instead of just N_l of each component. That means several of the iteration results will be invalid and skipped.
|
||
// (This is a performance issue, not a correctness issue.)
|
||
|
||
for (int l = 0; l < m_layer_count; ++l)
|
||
for (int r = 0; r <= m_max_number_of_decomposition_levels; ++r)
|
||
for (int i = 0; i < m_component_count; ++i)
|
||
for (int k = 0; k < m_precinct_count(r, i); ++k)
|
||
co_yield ProgressionData { l, r, i, k };
|
||
}
|
||
|
||
ResolutionLevelLayerComponentPositionProgressionIterator::ResolutionLevelLayerComponentPositionProgressionIterator(int layer_count, int max_number_of_decomposition_levels, int component_count, Function<int(int resolution_level, int component)> precinct_count)
|
||
: m_layer_count(layer_count)
|
||
, m_max_number_of_decomposition_levels(max_number_of_decomposition_levels)
|
||
, m_component_count(component_count)
|
||
, m_precinct_count(move(precinct_count))
|
||
, m_generator(generator())
|
||
{
|
||
}
|
||
|
||
bool ResolutionLevelLayerComponentPositionProgressionIterator::has_next() const
|
||
{
|
||
return m_generator.has_next();
|
||
}
|
||
|
||
ProgressionData ResolutionLevelLayerComponentPositionProgressionIterator::next()
|
||
{
|
||
return m_generator.next();
|
||
}
|
||
|
||
SyncGenerator<ProgressionData> ResolutionLevelLayerComponentPositionProgressionIterator::generator()
|
||
{
|
||
// B.12.1.2 Resolution level-layer-component-position progression
|
||
// "for each r = 0,..., Nmax
|
||
// for each l = 0,..., L – 1
|
||
// for each i = 0,..., Csiz – 1
|
||
// for each k = 0,..., numprecincts – 1
|
||
// packet for component i, resolution level r, layer l, and precinct k."
|
||
// FIXME: This always iterates up to Nmax, instead of just N_l of each component. That means several of the iteration results will be invalid and skipped.
|
||
// (This is a performance issue, not a correctness issue.)
|
||
|
||
for (int r = 0; r <= m_max_number_of_decomposition_levels; ++r)
|
||
for (int l = 0; l < m_layer_count; ++l)
|
||
for (int i = 0; i < m_component_count; ++i)
|
||
for (int k = 0; k < m_precinct_count(r, i); ++k)
|
||
co_yield ProgressionData { l, r, i, k };
|
||
}
|
||
|
||
ResolutionLevelPositionComponentLayerProgressionIterator::ResolutionLevelPositionComponentLayerProgressionIterator(
|
||
int layer_count, int max_number_of_decomposition_levels, int component_count, Function<int(int resolution_level, int component)> precinct_count,
|
||
Function<int(int component)> XRsiz, Function<int(int component)> YRsiz,
|
||
Function<int(int resolution_level, int component)> PPx, Function<int(int resolution_level, int component)> PPy,
|
||
Function<int(int component)> N_L,
|
||
Function<int(int resolution_level, int component)> num_precincts_wide,
|
||
Gfx::IntRect tile_rect,
|
||
Function<IntRect(int resolution_level, int component)> ll_rect)
|
||
: m_layer_count(layer_count)
|
||
, m_max_number_of_decomposition_levels(max_number_of_decomposition_levels)
|
||
, m_component_count(component_count)
|
||
, m_precinct_count(move(precinct_count))
|
||
, m_XRsiz(move(XRsiz))
|
||
, m_YRsiz(move(YRsiz))
|
||
, m_PPx(move(PPx))
|
||
, m_PPy(move(PPy))
|
||
, m_N_L(move(N_L))
|
||
, m_num_precincts_wide(move(num_precincts_wide))
|
||
, m_tile_rect(tile_rect)
|
||
, m_ll_rect(move(ll_rect))
|
||
, m_generator(generator())
|
||
{
|
||
}
|
||
|
||
bool ResolutionLevelPositionComponentLayerProgressionIterator::has_next() const
|
||
{
|
||
return m_generator.has_next();
|
||
}
|
||
|
||
ProgressionData ResolutionLevelPositionComponentLayerProgressionIterator::next()
|
||
{
|
||
return m_generator.next();
|
||
}
|
||
|
||
SyncGenerator<ProgressionData> ResolutionLevelPositionComponentLayerProgressionIterator::generator()
|
||
{
|
||
auto compute_precinct = [&](int x, int y, int r, int i) {
|
||
// (B-20)
|
||
auto const trx0 = m_ll_rect(r, i).left();
|
||
auto const try0 = m_ll_rect(r, i).top();
|
||
auto const x_offset = floor_div(ceil_div(x, m_XRsiz(i) * (1 << (m_N_L(i) - r))), 1 << m_PPx(r, i)) - floor_div(trx0, 1 << m_PPx(r, i));
|
||
auto const y_offset = floor_div(ceil_div(y, m_YRsiz(i) * (1 << (m_N_L(i) - r))), 1 << m_PPy(r, i)) - floor_div(try0, 1 << m_PPy(r, i));
|
||
return x_offset + m_num_precincts_wide(r, i) * y_offset;
|
||
};
|
||
// B.12.1.3 Resolution level-position-component-layer progression
|
||
// "for each r = 0,..., Nmax
|
||
// for each y = ty0,..., ty1 – 1,
|
||
// for each x = tx0,..., tx1 – 1,
|
||
// for each i = 0,..., Csiz – 1
|
||
// if ((y divisible by YRsiz(i) * 2 ** (PPy(r, i) + N_L(i) - r) OR
|
||
// ((y == ty0) AND (try0 * 2 ** (N_L(i) - r) NOT divisible by 2 ** (PPy(r, i) + N_L(i) - r))))
|
||
// if ((x divisible by XRsiz(i) * 2 ** (PPx(r, i) + N_L(i) - r) OR
|
||
// ((x == tx0) AND (trx0 * 2 ** (N_L(i) - r) NOT divisible by 2 ** (PPx(r, i) + N_L(i) - r))))
|
||
// for the next precinct, k, if one exists,
|
||
// for each l = 0,..., L – 1
|
||
// packet for component i, resolution level r, layer l, and precinct k."
|
||
// The motivation for this loop is to walk corresponding precincts in different components at the same time,
|
||
// even if the components have different precinct counts.
|
||
for (int r = 0; r <= m_max_number_of_decomposition_levels; ++r) {
|
||
auto const tx0 = m_tile_rect.left();
|
||
auto const ty0 = m_tile_rect.top();
|
||
for (int y = ty0; y < m_tile_rect.bottom(); ++y) {
|
||
for (int x = tx0; x < m_tile_rect.right(); ++x) {
|
||
for (int i = 0; i < m_component_count; ++i) {
|
||
auto const trx0 = m_ll_rect(r, i).left();
|
||
auto const try0 = m_ll_rect(r, i).top();
|
||
if ((y % (m_YRsiz(i) * (1 << (m_PPy(r, i) + m_N_L(i) - r))) == 0)
|
||
|| ((y == ty0) && (try0 * (1 << (m_N_L(i) - r)) % (1 << (m_PPy(r, i) + m_N_L(i) - r)) != 0))) {
|
||
if ((x % (m_XRsiz(i) * (1 << (m_PPx(r, i) + m_N_L(i) - r))) == 0)
|
||
|| ((x == tx0) && (trx0 * (1 << (m_N_L(i) - r)) % (1 << (m_PPx(r, i) + m_N_L(i) - r)) != 0))) {
|
||
if (int k = compute_precinct(x, y, r, i); k < m_precinct_count(r, i)) {
|
||
for (int l = 0; l < m_layer_count; ++l) {
|
||
co_yield ProgressionData { l, r, i, k };
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
PositionComponentResolutionLevelLayerProgressionIterator::PositionComponentResolutionLevelLayerProgressionIterator(
|
||
int layer_count, int component_count, Function<int(int resolution_level, int component)> precinct_count,
|
||
Function<int(int component)> XRsiz, Function<int(int component)> YRsiz,
|
||
Function<int(int resolution_level, int component)> PPx, Function<int(int resolution_level, int component)> PPy,
|
||
Function<int(int component)> N_L,
|
||
Function<int(int resolution_level, int component)> num_precincts_wide,
|
||
Gfx::IntRect tile_rect,
|
||
Function<IntRect(int resolution_level, int component)> ll_rect)
|
||
: m_layer_count(layer_count)
|
||
, m_component_count(component_count)
|
||
, m_precinct_count(move(precinct_count))
|
||
, m_XRsiz(move(XRsiz))
|
||
, m_YRsiz(move(YRsiz))
|
||
, m_PPx(move(PPx))
|
||
, m_PPy(move(PPy))
|
||
, m_N_L(move(N_L))
|
||
, m_num_precincts_wide(move(num_precincts_wide))
|
||
, m_tile_rect(tile_rect)
|
||
, m_ll_rect(move(ll_rect))
|
||
, m_generator(generator())
|
||
{
|
||
}
|
||
|
||
bool PositionComponentResolutionLevelLayerProgressionIterator::has_next() const
|
||
{
|
||
return m_generator.has_next();
|
||
}
|
||
|
||
ProgressionData PositionComponentResolutionLevelLayerProgressionIterator::next()
|
||
{
|
||
return m_generator.next();
|
||
}
|
||
|
||
SyncGenerator<ProgressionData> PositionComponentResolutionLevelLayerProgressionIterator::generator()
|
||
{
|
||
auto compute_precinct = [&](int x, int y, int r, int i) {
|
||
// (B-20)
|
||
auto const trx0 = m_ll_rect(r, i).left();
|
||
auto const try0 = m_ll_rect(r, i).top();
|
||
auto const x_offset = floor_div(ceil_div(x, m_XRsiz(i) * (1 << (m_N_L(i) - r))), 1 << m_PPx(r, i)) - floor_div(trx0, 1 << m_PPx(r, i));
|
||
auto const y_offset = floor_div(ceil_div(y, m_YRsiz(i) * (1 << (m_N_L(i) - r))), 1 << m_PPy(r, i)) - floor_div(try0, 1 << m_PPy(r, i));
|
||
return x_offset + m_num_precincts_wide(r, i) * y_offset;
|
||
};
|
||
// B.12.1.4 Position-component-resolution level-layer progression
|
||
// "for each y = ty0,..., ty1 – 1,
|
||
// for each x = tx0,..., tx1 – 1,
|
||
// for each i = 0,..., Csiz – 1
|
||
// for each r = 0,..., NL where NL is the number of decomposition levels for component i,
|
||
// if ((y divisible by YRsiz(i) * 2 ** (PPy(r, i) + N_L(i) - r) OR
|
||
// ((y == ty0) AND (try0 * 2 ** (N_L(i) - r) NOT divisible by 2 ** (PPy(r, i) + N_L(i) - r))))
|
||
// if ((x divisible by XRsiz(i) * 2 ** (PPx(r, i) + N_L(i) - r) OR
|
||
// ((x == tx0) AND (trx0 * 2 ** (N_L(i) - r) NOT divisible by 2 ** (PPx(r, i) + N_L(i) - r))))
|
||
// for the next precinct, k, if one exists, in the sequence shown in Figure B.8
|
||
// for each l = 0,..., L – 1
|
||
// packet for component i, resolution level r, layer l, and precinct k."
|
||
// The motivation for this loop is to walk corresponding precincts in different components and resolution levels at the same time,
|
||
// even if the components or resolution levels have different precinct counts.
|
||
auto const tx0 = m_tile_rect.left();
|
||
auto const ty0 = m_tile_rect.top();
|
||
for (int y = ty0; y < m_tile_rect.bottom(); ++y) {
|
||
for (int x = tx0; x < m_tile_rect.right(); ++x) {
|
||
for (int i = 0; i < m_component_count; ++i) {
|
||
for (int r = 0; r <= m_N_L(i); ++r) {
|
||
auto const trx0 = m_ll_rect(r, i).left();
|
||
auto const try0 = m_ll_rect(r, i).top();
|
||
if ((y % (m_YRsiz(i) * (1 << (m_PPy(r, i) + m_N_L(i) - r))) == 0)
|
||
|| ((y == ty0) && (try0 * (1 << (m_N_L(i) - r)) % (1 << (m_PPy(r, i) + m_N_L(i) - r)) != 0))) {
|
||
if ((x % (m_XRsiz(i) * (1 << (m_PPx(r, i) + m_N_L(i) - r))) == 0)
|
||
|| ((x == tx0) && (trx0 * (1 << (m_N_L(i) - r)) % (1 << (m_PPx(r, i) + m_N_L(i) - r)) != 0))) {
|
||
if (int k = compute_precinct(x, y, r, i); k < m_precinct_count(r, i)) {
|
||
for (int l = 0; l < m_layer_count; ++l) {
|
||
co_yield ProgressionData { l, r, i, k };
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
ComponentPositionResolutionLevelLayerProgressionIterator::ComponentPositionResolutionLevelLayerProgressionIterator(
|
||
int layer_count, int component_count, Function<int(int resolution_level, int component)> precinct_count,
|
||
Function<int(int component)> XRsiz, Function<int(int component)> YRsiz,
|
||
Function<int(int resolution_level, int component)> PPx, Function<int(int resolution_level, int component)> PPy,
|
||
Function<int(int component)> N_L,
|
||
Function<int(int resolution_level, int component)> num_precincts_wide,
|
||
Gfx::IntRect tile_rect,
|
||
Function<IntRect(int resolution_level, int component)> ll_rect)
|
||
: m_layer_count(layer_count)
|
||
, m_component_count(component_count)
|
||
, m_precinct_count(move(precinct_count))
|
||
, m_XRsiz(move(XRsiz))
|
||
, m_YRsiz(move(YRsiz))
|
||
, m_PPx(move(PPx))
|
||
, m_PPy(move(PPy))
|
||
, m_N_L(move(N_L))
|
||
, m_num_precincts_wide(move(num_precincts_wide))
|
||
, m_tile_rect(tile_rect)
|
||
, m_ll_rect(move(ll_rect))
|
||
, m_generator(generator())
|
||
{
|
||
}
|
||
|
||
bool ComponentPositionResolutionLevelLayerProgressionIterator::has_next() const
|
||
{
|
||
return m_generator.has_next();
|
||
}
|
||
|
||
ProgressionData ComponentPositionResolutionLevelLayerProgressionIterator::next()
|
||
{
|
||
return m_generator.next();
|
||
}
|
||
|
||
SyncGenerator<ProgressionData> ComponentPositionResolutionLevelLayerProgressionIterator::generator()
|
||
{
|
||
auto compute_precinct = [&](int x, int y, int r, int i) {
|
||
// (B-20)
|
||
auto const trx0 = m_ll_rect(r, i).left();
|
||
auto const try0 = m_ll_rect(r, i).top();
|
||
auto const x_offset = floor_div(ceil_div(x, m_XRsiz(i) * (1 << (m_N_L(i) - r))), 1 << m_PPx(r, i)) - floor_div(trx0, 1 << m_PPx(r, i));
|
||
auto const y_offset = floor_div(ceil_div(y, m_YRsiz(i) * (1 << (m_N_L(i) - r))), 1 << m_PPy(r, i)) - floor_div(try0, 1 << m_PPy(r, i));
|
||
return x_offset + m_num_precincts_wide(r, i) * y_offset;
|
||
};
|
||
// B.12.1.5 Component-position-resolution level-layer progression
|
||
// "for each i = 0,..., Csiz – 1
|
||
// for each y = ty0,..., ty1 – 1,
|
||
// for each x = tx0,..., tx1 – 1,
|
||
// for each r = 0,..., NL where NL is the number of decomposition levels for component i,
|
||
// if ((y divisible by YRsiz(i) * 2 ** (PPy(r, i) + N_L(i) - r) OR
|
||
// ((y == ty0) AND (try0 * 2 ** (N_L(i) - r) NOT divisible by 2 ** (PPy(r, i) + N_L(i) - r))))
|
||
// if ((x divisible by XRsiz(i) * 2 ** (PPx(r, i) + N_L(i) - r) OR
|
||
// ((x == tx0) AND (trx0 * 2 ** (N_L(i) - r) NOT divisible by 2 ** (PPx(r, i) + N_L(i) - r))))
|
||
// for the next precinct, k, if one exists, in the sequence shown in Figure B.8
|
||
// for each l = 0,..., L – 1
|
||
// packet for component i, resolution level r, layer l, and precinct k."
|
||
// The motivation for this loop is to walk corresponding precincts in different resolution levels at the same time,
|
||
// even if the resolution levels have different precinct counts.
|
||
auto const tx0 = m_tile_rect.left();
|
||
auto const ty0 = m_tile_rect.top();
|
||
for (int i = 0; i < m_component_count; ++i) {
|
||
for (int y = ty0; y < m_tile_rect.bottom(); ++y) {
|
||
for (int x = tx0; x < m_tile_rect.right(); ++x) {
|
||
for (int r = 0; r <= m_N_L(i); ++r) {
|
||
auto const trx0 = m_ll_rect(r, i).left();
|
||
auto const try0 = m_ll_rect(r, i).top();
|
||
if ((y % (m_YRsiz(i) * (1 << (m_PPy(r, i) + m_N_L(i) - r))) == 0)
|
||
|| ((y == ty0) && (try0 * (1 << (m_N_L(i) - r)) % (1 << (m_PPy(r, i) + m_N_L(i) - r)) != 0))) {
|
||
if ((x % (m_XRsiz(i) * (1 << (m_PPx(r, i) + m_N_L(i) - r))) == 0)
|
||
|| ((x == tx0) && (trx0 * (1 << (m_N_L(i) - r)) % (1 << (m_PPx(r, i) + m_N_L(i) - r)) != 0))) {
|
||
if (int k = compute_precinct(x, y, r, i); k < m_precinct_count(r, i)) {
|
||
for (int l = 0; l < m_layer_count; ++l) {
|
||
co_yield ProgressionData { l, r, i, k };
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
}
|