ResWindow.h
Go to the documentation of this file.
#pragma once
#include "grk_includes.h"
#include <stdexcept>
#include <algorithm>
/*
Various coordinate systems are used to describe regions in the tile component buffer.
1) Canvas coordinates: JPEG 2000 global image coordinates.
2) Tile component coordinates: canvas coordinates with sub-sampling applied
3) Band coordinates: coordinates relative to a specified sub-band's origin
4) Buffer coordinates: coordinate system where all resolutions are translated
to common origin (0,0). If each code block is translated relative to the origin of the
resolution that **it belongs to**, the blocks are then all in buffer coordinate system
Note: the name of any method or variable returning non canvas coordinates is appended
with "REL", to signify relative coordinates.
*/
namespace grk
{
enum eSplitOrientation
{
SPLIT_L,
SPLIT_H,
SPLIT_NUM_ORIENTATIONS
};
template<typename T>
struct TileComponentWindow;
template<typename T>
struct TileComponentWindowBase;
template<typename T>
struct ResWindow
{
friend struct TileComponentWindowBase<T>;
friend struct TileComponentWindow<T>;
typedef grk_buf2d<T, AllocatorAligned> Buf2dAligned;
private:
ResWindow(uint8_t numresolutions, uint8_t resno, Buf2dAligned* resWindowHighestResREL,
ResSimple tileCompAtRes, ResSimple tileCompAtLowerRes, grk_rect32 resWindow,
grk_rect32 tileCompWindowUnreduced, grk_rect32 tileCompUnreduced,
uint32_t FILTER_WIDTH)
: allocated_(false), filterWidth_(FILTER_WIDTH), tileCompAtRes_(tileCompAtRes),
tileCompAtLowerRes_(tileCompAtLowerRes),
resWindowBuffer_(new Buf2dAligned(resWindow)), resWindowBufferSplit_{nullptr, nullptr},
resWindowBufferHighestResREL_(resWindowHighestResREL),
resWindowBufferREL_(new Buf2dAligned(resWindow.width(), resWindow.height())),
resWindowBufferSplitREL_{nullptr, nullptr}
{
resWindowBuffer_->setOrigin(tileCompAtRes_, true);
uint8_t numDecomps =
(resno == 0) ? (uint8_t)(numresolutions - 1U) : (uint8_t)(numresolutions - resno);
grk_rect32 resWindowPadded;
for(uint8_t orient = 0; orient < ((resno) > 0 ? BAND_NUM_ORIENTATIONS : 1); orient++)
{
// todo: should only need padding equal to FILTER_WIDTH, not 2*FILTER_WIDTH
auto bandWindow =
getPaddedBandWindow(numDecomps, orient, tileCompWindowUnreduced, tileCompUnreduced,
2 * FILTER_WIDTH, resWindowPadded);
grk_rect32 band = tileCompAtRes_.tileBand[BAND_ORIENT_LL];
if(resno > 0)
band = orient == BAND_ORIENT_LL ? grk_rect32(tileCompAtLowerRes_)
: tileCompAtRes_.tileBand[orient - 1];
bandWindow.setOrigin(band, true);
assert(bandWindow.intersection(band).setOrigin(bandWindow, true) == bandWindow);
bandWindowsBoundsPadded_.push_back(bandWindow);
}
// windowed decompression
if(FILTER_WIDTH)
{
if(tileCompAtLowerRes_.numTileBandWindows)
{
assert(resno > 0);
resWindowBuffer_->setRect(resWindowPadded);
resWindowBufferREL_->setRect(resWindowBuffer_->toRelative());
resWindowBuffer_->toAbsolute();
for(uint8_t orient = 0; orient < BAND_NUM_ORIENTATIONS; orient++)
{
auto bandWindow = bandWindowsBoundsPadded_[orient];
bandWindowsBuffersPadded_.push_back(new Buf2dAligned(bandWindow, true));
bandWindowsBuffersPaddedREL_.push_back(
new Buf2dAligned(bandWindow.toRelative(), true));
}
genSplitWindowBuffers(resWindowBufferSplit_, resWindowBuffer_,
bandWindowsBuffersPadded_[BAND_ORIENT_LL],
bandWindowsBuffersPadded_[BAND_ORIENT_LH], true);
genSplitWindowBuffers(resWindowBufferSplitREL_, resWindowBuffer_,
bandWindowsBuffersPadded_[BAND_ORIENT_LL],
bandWindowsBuffersPadded_[BAND_ORIENT_LH], false);
}
}
else
{
assert(tileCompAtRes_.numTileBandWindows == 3 ||
!tileCompAtLowerRes.numTileBandWindows);
// dummy LL band window
if(tileCompAtLowerRes_.numTileBandWindows && tileCompAtLowerRes_.valid())
{
bandWindowsBuffersPadded_.push_back(new Buf2dAligned(0, 0));
bandWindowsBuffersPaddedREL_.push_back(new Buf2dAligned(0, 0));
for(uint32_t i = 0; i < tileCompAtRes_.numTileBandWindows; ++i)
{
auto tileCompBand = tileCompAtRes_.tileBand + i;
auto band = grk_rect32(tileCompBand);
bandWindowsBuffersPadded_.push_back(new Buf2dAligned(band));
bandWindowsBuffersPaddedREL_.push_back(new Buf2dAligned(band.toRelative()));
}
for(uint8_t i = 0; i < SPLIT_NUM_ORIENTATIONS; i++)
{
grk_rect32 split = resWindowBuffer_;
split.y0 = (resWindowBuffer_->y0 == 0
? 0
: ceildivpow2<uint32_t>(resWindowBuffer_->y0 - i, 1));
split.y1 = (resWindowBuffer_->y1 == 0
? 0
: ceildivpow2<uint32_t>(resWindowBuffer_->y1 - i, 1));
resWindowBufferSplit_[i] = new Buf2dAligned(split);
resWindowBufferSplitREL_[i] = new Buf2dAligned(resWindowBufferSplit_[i]);
}
}
}
}
~ResWindow()
{
delete resWindowBufferREL_;
for(auto& b : bandWindowsBuffersPaddedREL_)
delete b;
for(uint32_t i = 0; i < SPLIT_NUM_ORIENTATIONS; ++i)
delete resWindowBufferSplitREL_[i];
delete resWindowBuffer_;
for(auto& b : bandWindowsBuffersPadded_)
delete b;
for(uint32_t i = 0; i < SPLIT_NUM_ORIENTATIONS; ++i)
delete resWindowBufferSplit_[i];
}
void genSplitWindowBuffers(Buf2dAligned** resWindowBufferSplit, Buf2dAligned* resWindowBuffer,
Buf2dAligned* bandWindowsBuffersPaddedXL,
Buf2dAligned* bandWindowsBuffersPaddedXH, bool absolute)
{
if(!absolute)
{
tileCompAtLowerRes_.toRelative();
bandWindowsBuffersPaddedXL->toRelative();
bandWindowsBuffersPaddedXH->toRelative();
}
// two windows formed by horizontal pass and used as input for vertical pass
auto splitResWindowBounds = grk_rect32(resWindowBuffer->x0, bandWindowsBuffersPaddedXL->y0,
resWindowBuffer->x1, bandWindowsBuffersPaddedXL->y1);
resWindowBufferSplit[SPLIT_L] = new Buf2dAligned(splitResWindowBounds);
splitResWindowBounds = grk_rect32(
resWindowBuffer->x0, tileCompAtLowerRes_.y1 + bandWindowsBuffersPaddedXH->y0,
resWindowBuffer->x1, tileCompAtLowerRes_.y1 + bandWindowsBuffersPaddedXH->y1);
resWindowBufferSplit[SPLIT_H] = new Buf2dAligned(splitResWindowBounds);
if(!absolute)
{
tileCompAtLowerRes_.toAbsolute();
bandWindowsBuffersPaddedXL->toAbsolute();
bandWindowsBuffersPaddedXH->toAbsolute();
}
}
bool alloc(bool clear)
{
if(allocated_)
return true;
// if top level window is present, then all buffers attach to this window
if(resWindowBufferHighestResREL_)
{
// ensure that top level window is allocated
if(!resWindowBufferHighestResREL_->alloc2d(clear))
return false;
// don't allocate bandWindows for windowed decompression
if(filterWidth_)
return true;
// attach to top level window
if(resWindowBufferREL_ != resWindowBufferHighestResREL_)
resWindowBufferREL_->attach(resWindowBufferHighestResREL_);
// tileCompResLower_ is null for lowest resolution
if(tileCompAtLowerRes_.numTileBandWindows)
{
for(uint8_t orientation = 0; orientation < bandWindowsBuffersPaddedREL_.size();
++orientation)
{
switch(orientation)
{
case BAND_ORIENT_HL:
bandWindowsBuffersPaddedREL_[orientation]->attach(
resWindowBufferHighestResREL_, tileCompAtLowerRes_.width(), 0);
break;
case BAND_ORIENT_LH:
bandWindowsBuffersPaddedREL_[orientation]->attach(
resWindowBufferHighestResREL_, 0, tileCompAtLowerRes_.height());
break;
case BAND_ORIENT_HH:
bandWindowsBuffersPaddedREL_[orientation]->attach(
resWindowBufferHighestResREL_, tileCompAtLowerRes_.width(),
tileCompAtLowerRes_.height());
break;
default:
break;
}
}
resWindowBufferSplit_[SPLIT_L]->attach(resWindowBufferHighestResREL_);
resWindowBufferSplit_[SPLIT_H]->attach(resWindowBufferHighestResREL_, 0,
tileCompAtLowerRes_.height());
}
// attach canvas windows to relative windows
for(uint8_t orientation = 0; orientation < bandWindowsBuffersPaddedREL_.size();
++orientation)
{
bandWindowsBuffersPadded_[orientation]->attach(
bandWindowsBuffersPaddedREL_[orientation]);
}
resWindowBuffer_->attach(resWindowBufferREL_);
for(uint8_t i = 0; i < SPLIT_NUM_ORIENTATIONS; ++i)
{
if(resWindowBufferSplitREL_[i])
resWindowBufferSplitREL_[i]->attach(resWindowBufferSplit_[i]);
}
}
else
{
// 1. allocate resolution window
// resolution window is always allocated
if(!resWindowBufferREL_->alloc2d(clear))
return false;
resWindowBuffer_->attach(resWindowBufferREL_);
// 2, allocate padded band windows
// band windows are allocated if present
for(auto& b : bandWindowsBuffersPadded_)
{
if(!b->alloc2d(clear))
return false;
}
for(uint8_t orientation = 0; orientation < bandWindowsBuffersPaddedREL_.size();
++orientation)
{
bandWindowsBuffersPaddedREL_[orientation]->attach(
bandWindowsBuffersPaddedREL_[orientation]);
}
// 3. allocate split windows
if(tileCompAtLowerRes_.numTileBandWindows)
{
if(resWindowBufferHighestResREL_)
{
resWindowBufferSplit_[SPLIT_L]->attach(resWindowBuffer_);
resWindowBufferSplit_[SPLIT_H]->attach(resWindowBuffer_, 0,
tileCompAtLowerRes_.height());
}
else
{
resWindowBufferSplit_[SPLIT_L]->alloc2d(clear);
resWindowBufferSplit_[SPLIT_H]->alloc2d(clear);
}
for(uint8_t i = 0; i < SPLIT_NUM_ORIENTATIONS; ++i)
{
if(resWindowBufferSplitREL_[i])
resWindowBufferSplitREL_[i]->attach(resWindowBufferSplit_[i]);
}
}
}
allocated_ = true;
return true;
}
static grk_rect32 getPaddedBandWindow(uint8_t numDecomps, uint8_t orientation,
grk_rect32 unreducedTileCompWindow,
grk_rect32 unreducedTileComp, uint32_t padding,
grk_rect32& paddedResWindow)
{
assert(orientation < BAND_NUM_ORIENTATIONS);
if(numDecomps == 0)
{
assert(orientation == 0);
return unreducedTileCompWindow.grow_IN_PLACE(padding).intersection(&unreducedTileComp);
}
paddedResWindow = unreducedTileCompWindow;
auto oneLessDecompTile = unreducedTileComp;
if(numDecomps > 1)
{
paddedResWindow = ResSimple::getBandWindow(numDecomps - 1, 0, unreducedTileCompWindow);
oneLessDecompTile = ResSimple::getBandWindow(numDecomps - 1, 0, unreducedTileComp);
}
paddedResWindow.grow_IN_PLACE(2 * padding).clip_IN_PLACE(&oneLessDecompTile);
paddedResWindow.setOrigin(oneLessDecompTile, true);
return ResSimple::getBandWindow(1, orientation, paddedResWindow);
}
grk_buf2d_simple<int32_t> getResWindowBufferSimple(void) const
{
return resWindowBuffer_->simple();
}
grk_buf2d_simple<float> getResWindowBufferSimpleF(void) const
{
return resWindowBuffer_->simpleF();
}
void disableBandWindowAllocation(void)
{
resWindowBufferHighestResREL_ = resWindowBufferREL_;
}
Buf2dAligned* getResWindowBufferSplitREL(eSplitOrientation orientation) const
{
return resWindowBufferSplitREL_[orientation];
}
const grk_rect32* getBandWindowPadded(eBandOrientation orientation) const
{
return &bandWindowsBoundsPadded_[orientation];
}
const Buf2dAligned* getBandWindowBufferPaddedREL(eBandOrientation orientation) const
{
return bandWindowsBuffersPaddedREL_[orientation];
}
const grk_buf2d_simple<int32_t>
getBandWindowBufferPaddedSimple(eBandOrientation orientation) const
{
return bandWindowsBuffersPadded_[orientation]->simple();
}
const grk_buf2d_simple<float>
getBandWindowBufferPaddedSimpleF(eBandOrientation orientation) const
{
return bandWindowsBuffersPadded_[orientation]->simpleF();
}
Buf2dAligned* getResWindowBufferREL(void) const
{
return resWindowBufferREL_;
}
bool allocated_;
uint32_t filterWidth_;
ResSimple tileCompAtRes_; // numTileBandWindows> 0 will trigger creation of band window buffers
ResSimple tileCompAtLowerRes_; // numTileBandWindows==0 for lowest resolution
Buf2dAligned* resWindowBuffer_;
Buf2dAligned* resWindowBufferSplit_[SPLIT_NUM_ORIENTATIONS];
std::vector<Buf2dAligned*> bandWindowsBuffersPadded_;
/*
bandWindowsBoundsPadded_ is used for determining which precincts and code blocks overlap
the window of interest, in each respective resolution
*/
std::vector<grk_rect32> bandWindowsBoundsPadded_;
Buf2dAligned* resWindowBufferHighestResREL_;
Buf2dAligned* resWindowBufferREL_;
Buf2dAligned* resWindowBufferSplitREL_[SPLIT_NUM_ORIENTATIONS];
std::vector<Buf2dAligned*> bandWindowsBuffersPaddedREL_;
};
} // namespace grk
grk_includes.h
grk
Copyright (C) 2016-2023 Grok Image Compression Inc.
Definition ICacheable.h:20
grk::grk_read
void grk_read(const uint8_t *buffer, TYPE *value, uint32_t numBytes)
Definition BufferedStream.h:239
grk::eSplitOrientation
eSplitOrientation
Definition ResWindow.h:45
grk::SPLIT_H
@ SPLIT_H
Definition ResWindow.h:47
grk::SPLIT_L
@ SPLIT_L
Definition ResWindow.h:46
grk::SPLIT_NUM_ORIENTATIONS
@ SPLIT_NUM_ORIENTATIONS
Definition ResWindow.h:48
grk::grk_rect32
grk_rect< uint32_t > grk_rect32
Definition geometry.h:61
grk::eBandOrientation
eBandOrientation
Definition ResSimple.h:23
grk::BAND_ORIENT_HH
@ BAND_ORIENT_HH
Definition ResSimple.h:27
grk::BAND_ORIENT_HL
@ BAND_ORIENT_HL
Definition ResSimple.h:25
grk::BAND_NUM_ORIENTATIONS
@ BAND_NUM_ORIENTATIONS
Definition ResSimple.h:28
grk::BAND_ORIENT_LH
@ BAND_ORIENT_LH
Definition ResSimple.h:26
grk::BAND_ORIENT_LL
@ BAND_ORIENT_LL
Definition ResSimple.h:24
grk::ResSimple
Definition ResSimple.h:43
grk::ResSimple::tileBand
grk_rect32 tileBand[BAND_NUM_INDICES]
Definition ResSimple.h:110
grk::ResSimple::numTileBandWindows
uint8_t numTileBandWindows
Definition ResSimple.h:111
grk::ResSimple::getBandWindow
static grk_rect32 getBandWindow(uint8_t numDecomps, uint8_t orientation, grk_rect32 tileCompWindowUnreduced)
Get band window (in tile component coordinates) for specified number of decompositions.
Definition ResSimple.h:77
grk::ResWindow
ResWindow.
Definition ResWindow.h:70
grk::ResWindow::genSplitWindowBuffers
void genSplitWindowBuffers(Buf2dAligned **resWindowBufferSplit, Buf2dAligned *resWindowBuffer, Buf2dAligned *bandWindowsBuffersPaddedXL, Buf2dAligned *bandWindowsBuffersPaddedXH, bool absolute)
Definition ResWindow.h:177
grk::ResWindow::filterWidth_
uint32_t filterWidth_
Definition ResWindow.h:388
grk::ResWindow::getResWindowBufferSimpleF
grk_buf2d_simple< float > getResWindowBufferSimpleF(void) const
Definition ResWindow.h:353
grk::ResWindow::tileCompAtRes_
ResSimple tileCompAtRes_
Definition ResWindow.h:390
grk::ResWindow::ResWindow
ResWindow(uint8_t numresolutions, uint8_t resno, Buf2dAligned *resWindowHighestResREL, ResSimple tileCompAtRes, ResSimple tileCompAtLowerRes, grk_rect32 resWindow, grk_rect32 tileCompWindowUnreduced, grk_rect32 tileCompUnreduced, uint32_t FILTER_WIDTH)
Definition ResWindow.h:76
grk::ResWindow::getBandWindowPadded
const grk_rect32 * getBandWindowPadded(eBandOrientation orientation) const
Definition ResWindow.h:365
grk::ResWindow::resWindowBufferSplit_
Buf2dAligned * resWindowBufferSplit_[SPLIT_NUM_ORIENTATIONS]
Definition ResWindow.h:394
grk::ResWindow::allocated_
bool allocated_
Definition ResWindow.h:387
grk::ResWindow::resWindowBufferHighestResREL_
Buf2dAligned * resWindowBufferHighestResREL_
Definition ResWindow.h:403
grk::ResWindow::bandWindowsBuffersPadded_
std::vector< Buf2dAligned * > bandWindowsBuffersPadded_
Definition ResWindow.h:395
grk::ResWindow::getBandWindowBufferPaddedSimpleF
const grk_buf2d_simple< float > getBandWindowBufferPaddedSimpleF(eBandOrientation orientation) const
Definition ResWindow.h:379
grk::ResWindow::~ResWindow
~ResWindow()
Definition ResWindow.h:163
grk::ResWindow::getBandWindowBufferPaddedSimple
const grk_buf2d_simple< int32_t > getBandWindowBufferPaddedSimple(eBandOrientation orientation) const
Definition ResWindow.h:374
grk::ResWindow::resWindowBufferSplitREL_
Buf2dAligned * resWindowBufferSplitREL_[SPLIT_NUM_ORIENTATIONS]
Definition ResWindow.h:405
grk::ResWindow::getResWindowBufferSimple
grk_buf2d_simple< int32_t > getResWindowBufferSimple(void) const
Definition ResWindow.h:349
grk::ResWindow::getResWindowBufferSplitREL
Buf2dAligned * getResWindowBufferSplitREL(eSplitOrientation orientation) const
Definition ResWindow.h:361
grk::ResWindow::resWindowBufferREL_
Buf2dAligned * resWindowBufferREL_
Definition ResWindow.h:404
grk::ResWindow::disableBandWindowAllocation
void disableBandWindowAllocation(void)
Definition ResWindow.h:357
grk::ResWindow::bandWindowsBoundsPadded_
std::vector< grk_rect32 > bandWindowsBoundsPadded_
Definition ResWindow.h:401
grk::ResWindow::tileCompAtLowerRes_
ResSimple tileCompAtLowerRes_
Definition ResWindow.h:391
grk::ResWindow::getPaddedBandWindow
static grk_rect32 getPaddedBandWindow(uint8_t numDecomps, uint8_t orientation, grk_rect32 unreducedTileCompWindow, grk_rect32 unreducedTileComp, uint32_t padding, grk_rect32 &paddedResWindow)
Get band window (in tile component coordinates) for specified number of decompositions (with padding)
Definition ResWindow.h:325
grk::ResWindow::resWindowBuffer_
Buf2dAligned * resWindowBuffer_
Definition ResWindow.h:393
grk::ResWindow::alloc
bool alloc(bool clear)
Definition ResWindow.h:205
grk::ResWindow::getResWindowBufferREL
Buf2dAligned * getResWindowBufferREL(void) const
Definition ResWindow.h:383
grk::ResWindow::Buf2dAligned
grk_buf2d< T, AllocatorAligned > Buf2dAligned
Definition ResWindow.h:73
grk::ResWindow::getBandWindowBufferPaddedREL
const Buf2dAligned * getBandWindowBufferPaddedREL(eBandOrientation orientation) const
Definition ResWindow.h:369
grk::ResWindow::bandWindowsBuffersPaddedREL_
std::vector< Buf2dAligned * > bandWindowsBuffersPaddedREL_
Definition ResWindow.h:406
grk::TileComponentWindowBase
Definition TileComponentWindow.h:54
grk::TileComponentWindow
Definition TileComponentWindow.h:160
grk::grk_buf2d_simple
Definition buffer.h:206
grk::grk_buf2d
Definition buffer.h:230
grk::grk_buf2d::attach
void attach(T *buffer, uint32_t strd)
Definition buffer.h:293
grk::grk_buf2d::alloc2d
bool alloc2d(bool clear)
Definition buffer.h:271
grk::grk_buf2d::simpleF
grk_buf2d_simple< float > simpleF(void) const
Definition buffer.h:252
grk::grk_buf2d::simple
grk_buf2d_simple< T > simple(void) const
Definition buffer.h:248
grk::grk_rect< uint32_t >
grk::grk_rect::width
T width() const
Definition geometry.h:335
grk::grk_rect::y1
T y1
Definition geometry.h:124
grk::grk_rect::setOrigin
grk_rect< T > & setOrigin(T origx, T origy, bool absolute)
Definition geometry.h:126
grk::grk_rect::toRelative
grk_rect< T > & toRelative(void)
Definition geometry.h:156
grk::grk_rect::height
T height() const
Definition geometry.h:339
grk::grk_rect::valid
bool valid(void) const
Definition geometry.h:185
grk::grk_rect::toAbsolute
grk_rect< T > & toAbsolute(void)
Definition geometry.h:166
grk::grk_rect::setRect
void setRect(grk_rect< T > *rhs)
Definition geometry.h:228
grk::grk_rect::y0
T y0
Definition geometry.h:124