Skip to content

Commit

Permalink
Changes to how the requested width and height are handled by View cla…
Browse files Browse the repository at this point in the history
…ss as well as how the resolution level is calculated.

Fixes problems with fitting images into bounding boxes and now correctly selects appropriate resolution level in all cases. Fixes #273
  • Loading branch information
ruven committed Oct 16, 2024
1 parent ffd9c35 commit 7743d82
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 71 deletions.
6 changes: 6 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
16/10/2024:
- Changes to how the requested width and height are handled by View class as well as how the resolution level
is calculated. Fixes problems with fitting images into bounding boxes and now correctly selects appropriate
resolution level in all cases. Fixes https://github.com/ruven/iipsrv/issues/273


02/10/2024:
- Re-factoring of tile byte size check to work cleanly for both JPEG and WEBP and to avoid having to sometimes
reallocate memory
Expand Down
23 changes: 6 additions & 17 deletions src/CVT.cc
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,9 @@ void CVT::send( Session* session ){
view_width = session->view->getViewWidth();
view_height = session->view->getViewHeight();

resampled_width = session->view->getRequestWidth();
resampled_height = session->view->getRequestHeight();
vector<unsigned int> requestSize = session->view->getRequestSize();
resampled_width = requestSize[0];
resampled_height = requestSize[1];

if( session->loglevel >= 3 ){
*(session->logfile) << "CVT :: Region: " << view_left << "," << view_top
Expand All @@ -116,8 +117,9 @@ void CVT::send( Session* session ){
view_top = 0;
view_width = im_width;
view_height = im_height;
resampled_width = session->view->getRequestWidth();
resampled_height = session->view->getRequestHeight();
vector<unsigned int> requestSize = session->view->getRequestSize();
resampled_width = requestSize[0];
resampled_height = requestSize[1];
}


Expand All @@ -128,19 +130,6 @@ void CVT::send( Session* session ){
if(resampled_height > im_height) resampled_height = im_height;
}

// If we have requested that the aspect ratio be maintained, make sure the final image fits *within* the requested size.
// Don't adjust images if we have less than 0.1% difference as this is often due to rounding in resolution levels
if( session->view->maintain_aspect ){
vector<float> size = session->view->getViewSize();
float ratio = ((float)resampled_width/size[0]) / ((float)resampled_height/size[1]);
if( ratio < 0.999 ){
resampled_height = (unsigned int) round( ((float)resampled_width/size[0]) * size[1] );
}
else if( ratio > 1.001 ){
resampled_width = (unsigned int) round( ((float)resampled_height/size[1]) * size[0] );
}
}


// Make sure we don't have zero sized dimensions
if( resampled_width == 0 ) resampled_width = session->view->getMinSize();
Expand Down
2 changes: 1 addition & 1 deletion src/IIIF.cc
Original file line number Diff line number Diff line change
Expand Up @@ -543,7 +543,7 @@ void IIIF::run( Session* session, const string& src )
// Check for malformed upscaling request
if( iiif_version >= 3 ){
if( session->view->allow_upscaling == false &&
( requested_width > width || requested_height > height ) ){
( requested_width > (width*region[2]) || requested_height > (height*region[3]) ) ){
throw invalid_argument( "IIIF: upscaling should be prefixed with ^" );
}
}
Expand Down
73 changes: 41 additions & 32 deletions src/View.cc
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,9 @@ unsigned int View::getResolution(){
unsigned int i;

// Note that we use floor() as that is how our resolutions are calculated
if( requested_width ) View::calculateResolution( width, floor((float)requested_width/(float)view_width) );
if( requested_height ) View::calculateResolution( height, floor((float)requested_height/(float)view_height) );
vector<unsigned int> requested_size = View::getRequestSize();
View::calculateResolution( width, floor((float)requested_size[0]/(float)view_width) );
View::calculateResolution( height, floor((float)requested_size[1]/(float)view_height) );

res_width = width;
res_height = height;
Expand Down Expand Up @@ -224,45 +225,53 @@ unsigned int View::getViewHeight(){
}


unsigned int View::getRequestWidth(){
vector<unsigned int> View::getRequestSize(){

// If our requested width has not been set, but height has, return a width proportional to
// this requested height
unsigned int w = requested_width;
if( requested_width == 0 ){
if( requested_height != 0 ){
w = (unsigned int) round( (float)(getViewWidth()*requested_height) / (float)getViewHeight() );
}

// If no width or height has been set, use the full image size
else if( requested_height==0 ) w = width;
}
unsigned int h = requested_height;

// Limit our requested width to the maximum export size if we have set a limit
if( max_size > 0 && w > (unsigned int) max_size ) w = max_size;

return w;
}
// Calculate aspect ratio
float ratio = (view_width * width) / (view_height * height);

if( requested_width == 0 && requested_height != 0 ){
w = (unsigned int) round( (float)requested_height * ratio );
}
else if( requested_height == 0 && requested_width != 0 ){
h = (unsigned int) round( (float)requested_width / ratio );
}
else if( requested_width == 0 && requested_height == 0 ){
w = width;
h = height;
}
// If both width and height are set, restrict image to this bounding box
else if( requested_width != 0 && requested_height != 0 && maintain_aspect ){
float xscale = requested_width / (view_width*width);
float yscale = requested_height / (view_height*height);
// Fit to the axis requiring the most scaling (smallest factor)
if( xscale > yscale ) w = (unsigned int) (unsigned int) round( (float)requested_height * ratio );
else h = (unsigned int) round( (float)requested_width / ratio );
}

unsigned int View::getRequestHeight(){

// If our requested height has not been set, but the width has, return a height proportional to
// this requested width
unsigned int h = requested_height;
if( requested_height == 0 ){
if( requested_width != 0 ){
h = (unsigned int) round( (float)(getViewHeight()*requested_width) / (float)getViewWidth() );
// Limit our requested size to the maximum output size
if( max_size > 0 && (w > (unsigned int) max_size || h > (unsigned int) max_size) ){
if( w > h ){
w = max_size;
h = round( (float)requested_width / ratio );
}
else if( h > w ){
h = max_size;
w = round( (float)requested_height * ratio );
}
else{
w = max_size;
h = max_size;
}

// If no width or height has been set, use the full image size
else if( requested_width==0 ) h = height;
}

// Limit our requested height to the maximum export size
if( max_size > 0 && h > (unsigned int) max_size ) h = max_size;

return h;
// Create and return our result
std::vector<unsigned int> size = { w, h };
return size;
}


Expand Down
37 changes: 16 additions & 21 deletions src/View.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,12 +115,12 @@ class View{


/// Get the maximum allowed output size
/* @return maximum output dimension */
/** @return maximum output dimension */
int getMaxSize(){ return max_size; };


/// Get the minimum allowed output size
/* @return minimum output dimension */
/** @return minimum output dimension */
unsigned int getMinSize(){ return min_size; };


Expand All @@ -130,7 +130,7 @@ class View{


/// Get the allow_upscaling flag
/* @return true or false */
/** @return true or false */
bool allowUpscaling(){ return allow_upscaling; };


Expand All @@ -155,21 +155,16 @@ class View{
void setMaxResolutions( unsigned int r ){ max_resolutions = r; resolution=r-1; };


/// Get the size of the requested width
/* @return requested width */
unsigned int getRequestWidth();


/// Set the size of the requested width
/** @param w requested image width */
void setRequestWidth( unsigned int w ){
requested_width = w;
};


/// Get the size of the requested height
/* @return requested height */
unsigned int getRequestHeight();
/// Get requested image size
/** @return output size as a vector */
std::vector<unsigned int> getRequestSize();


/// Set the size of the requested height
Expand All @@ -180,12 +175,12 @@ class View{


/// Return the resolution level needed for the requested view
/* @return requested resolution level */
/** @return requested resolution level */
unsigned int getResolution();


/// Return the scaling required in case our requested width or height is in between available resolutions
/* @return scaling factor */
/** @return scaling factor */
float getScale();


Expand Down Expand Up @@ -236,39 +231,39 @@ class View{
int getLayers();

/// Return the image width at our requested resolution
/* @return image width */
/** @return image width */
unsigned int getImageWidth(){ return width; };

/// Return the image height at our requested resolution
/* @return image height */
/** @return image height */
unsigned int getImageHeight(){ return height; };

/// Return the left pixel of the viewport
/* @return position of left of viewport in pixels */
/** @return position of left of viewport in pixels */
unsigned int getViewLeft() ;

/// Return the top pixel of the viewport
/* @return position of top of viewport in pixels */
/** @return position of top of viewport in pixels */
unsigned int getViewTop();

/// Return the pixel width of the viewport
/* @return width of viewport in pixels */
/** @return width of viewport in pixels */
unsigned int getViewWidth();

/// Return the pixel height of the viewport
/* @return height of viewport in pixels */
/** @return height of viewport in pixels */
unsigned int getViewHeight();

/// Indicate whether the viewport has been set
/* @return boolean indicating whether viewport specified */
/** @return boolean indicating whether viewport specified */
bool viewPortSet();

/// Set rotation
/** @param r angle of rotation in degrees */
void setRotation( float r ){ rotation = r; };

/// Get rotation
/* @return requested rotation angle in degrees */
/** @return requested rotation angle in degrees */
float getRotation(){ return rotation; };

/// Whether view requires floating point processing
Expand Down

0 comments on commit 7743d82

Please sign in to comment.