Skip to content

Commit

Permalink
Major update of debug mode to allow requests to be made directly on t…
Browse files Browse the repository at this point in the history
…he command line using standard input with output sent directly to a file without the need for a web server or FCGI. Debug mode activated when DEBUG defined in pre-processor during compilation.

Also updated debugging information handling for both JPEG2000 codecs, which are now activated through separate KAKADU_DEBUG and OPENJPEG_DEBUG defines.
  • Loading branch information
ruven committed Sep 21, 2023
1 parent ff415f5 commit 37aebe6
Show file tree
Hide file tree
Showing 6 changed files with 157 additions and 108 deletions.
8 changes: 8 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
21/09/2023:
- Major update of debug mode to allow requests to be made directly on the command line using standard input with
output sent directly to a file without the need for a web server or FCGI. Debug mode activated when DEBUG
defined in pre-processor during compilation.
Also updated debugging information handling for both JPEG2000 codecs, which are now activated through separate
KAKADU_DEBUG and OPENJPEG_DEBUG defines.


11/09/2023:
- Added extra check for untiled TIFF images

Expand Down
41 changes: 41 additions & 0 deletions README
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,47 @@ For Apache, load mod_proxy and mod_proxy_fcgi and add the following line to Apac
ProxyPass "/fcgi-bin/iipsrv.fcgi" "fcgi://192.168.0.1:9000/"



DEBUGGING
---------

Basic debugging can be carried out by simply using the server logs. Verbose logging can be obtained
by increasing the VERBOSITY startup variable. Implemented levels of verbosity range from 0 (no logging)
to 6 (maximum amount of logging). The pre-processor defines KAKADU_DEBUG and OPENJPEG_DEBUG can
additionally be set at compile time to generate additional detailed logging from these particular decoders.

It is also possible to test iipsrv without the use of FCGI or a web server. In this case, you will need to
compile iipsrv with DEBUG defined for the pre-processor. This can be done during the ./configure stage before
building using make:

CXXFLAGS="-DDEBUG" ./configure
make

The resulting binary can be started on the command line and will accept any supported imaging protocol requests
(IIP, IIIF, Deepzoom or Zoomify) without any HTTP prefix or domain name (e.g. FIF=test.tif&WID=500&CVT=JPEG) as
standard input on the command line and output the image or data to the file "iipsrv.debug" in the same directory.
Successive requests will replace the contents of iipsrv.debug with the output of the new request. For example:

% ./src/iipsrv.fcgi
FIF=test.tif&WID=500&CVT=JPEG
IIIF=/test.tif/full/500,/0/default.jpg
FIF=test.tif&WID=600&ROT=90&&CVT=PNG

On Linux/Unix based systems, it's also possible to use pipes or redirection to send a list of requests within a file
with iipsrv automatically terminating at the end of the list:

iipsrv.fcgi < request_list.txt

Debugging using memory testing tools, such as valgrind (https://valgrind.org/), can be performed by starting
iipsrv on the command-line through the testing tool. For example:

valgrind iipsrv.fcgi --bind 0.0.0.0:9000

This can work in conjunction with debugging mode or together with a web server in normal FCGI-mode. In this case
the web server must be setup to proxy forward FCGI requests to the address and port specified when starting iipsrv.



------------------------------------------------------------------------------------
Please refer to the project site https://iipimage.sourceforge.io for further details

Expand Down
11 changes: 5 additions & 6 deletions src/JTL.cc
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ void JTL::send( Session* session, int resolution, int tile ){
*(session->logfile) << "JTL :: Tile size: " << rawtile.width << " x " << rawtile.height << endl
<< "JTL :: Channels per sample: " << rawtile.channels << endl
<< "JTL :: Bits per channel: " << rawtile.bpc << endl
<< "JTL :: Data size is " << len << " bytes" << endl;
<< "JTL :: Data size: " << len << " bytes" << endl;
}


Expand Down Expand Up @@ -418,9 +418,8 @@ void JTL::send( Session* session, int resolution, int tile ){
}
len = compressor->Compress( rawtile );
if( session->loglevel >= 4 ){
*(session->logfile) << " in " << function_timer.getTime() << " microseconds to "
<< rawtile.dataLength << " bytes" << endl;

*(session->logfile) << " to " << rawtile.dataLength << " bytes in "
<< function_timer.getTime() << " microseconds" << endl;
}
}

Expand All @@ -441,14 +440,14 @@ void JTL::send( Session* session, int resolution, int tile ){

if( session->out->putStr( static_cast<const char*>(rawtile.data), len ) != len ){
if( session->loglevel >= 1 ){
*(session->logfile) << "JTL :: Error writing JPEG tile" << endl;
*(session->logfile) << "JTL :: Error writing tile" << endl;
}
}


if( session->out->flush() == -1 ) {
if( session->loglevel >= 1 ){
*(session->logfile) << "JTL :: Error flushing JPEG tile" << endl;
*(session->logfile) << "JTL :: Error flushing tile" << endl;
}
}

Expand Down
69 changes: 34 additions & 35 deletions src/KakaduImage.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
Culture of the Czech Republic.
Copyright (C) 2009-2022 IIPImage.
Copyright (C) 2009-2023 IIPImage.
Author: Ruven Pillay
This program is free software; you can redistribute it and/or modify
Expand Down Expand Up @@ -70,7 +70,6 @@ static unsigned int get_concurrency(){ return 0; }


#include "Timer.h"
//#define DEBUG 1


using namespace std;
Expand Down Expand Up @@ -130,7 +129,7 @@ void KakaduImage::openImage()
updateTimestamp( filename );


#ifdef DEBUG
#ifdef KAKADU_DEBUG
Timer timer;
timer.start();
#endif
Expand Down Expand Up @@ -185,7 +184,7 @@ void KakaduImage::openImage()
// Load our metadata if not already loaded
if( bpc == 0 ) loadImageInfo( currentX, currentY );

#ifdef DEBUG
#ifdef KAKADU_DEBUG
logfile << "Kakadu :: openImage() :: " << timer.getTime() << " microseconds" << endl;
#endif

Expand All @@ -202,12 +201,12 @@ void KakaduImage::loadImageInfo( int seq, int ang )
jpx_layer_source jpx_layer;

// Check for High Throughput JPEG2000 codestream
#ifdef DEBUG
siz_params *siz = codestream.access_siz();
int pcap_value = 0;
siz->get( Scap, 0, 0, pcap_value );
if( pcap_value & 0x00020000 ) logfile << "Kakadu :: HTJ2K codestream" << endl;
#endif
if( IIPImage::logging ){
siz_params *siz = codestream.access_siz();
int pcap_value = 0;
siz->get( Scap, 0, 0, pcap_value );
if( pcap_value & 0x00020000 ) logfile << "Kakadu :: HTJ2K codestream" << endl;
}

// Malformed images can throw exceptions here with older versions of Kakadu
try{
Expand Down Expand Up @@ -245,7 +244,7 @@ void KakaduImage::loadImageInfo( int seq, int ang )
unsigned int w = layer_size.x;
unsigned int h = layer_size.y;

#ifdef DEBUG
#ifdef KAKADU_DEBUG
logfile << "Kakadu :: DWT Levels: " << numResolutions << endl;
logfile << "Kakadu :: Pixel Resolution : " << w << "x" << h << endl;
logfile << "Kakadu :: Capture Resolution : " << dpi_x << "x" << dpi_y << " pixels/cm" << endl;
Expand All @@ -264,7 +263,7 @@ void KakaduImage::loadImageInfo( int seq, int ang )
h = floor( h/2.0 );
image_widths.push_back(w);
image_heights.push_back(h);
#ifdef DEBUG
#ifdef KAKADU_DEBUG
logfile << "Kakadu :: Resolution : " << w << "x" << h << endl;
#endif
}
Expand All @@ -287,7 +286,7 @@ void KakaduImage::loadImageInfo( int seq, int ang )
}

if( n > numResolutions ){
#ifdef DEBUG
#ifdef KAKADU_DEBUG
logfile << "Kakadu :: Warning! Insufficient resolution levels in JPEG2000 stream. Will generate " << n-numResolutions << " extra levels dynamically -" << endl
<< "Kakadu :: However, you are advised to regenerate the file with at least " << n << " levels" << endl;
#endif
Expand Down Expand Up @@ -317,7 +316,7 @@ void KakaduImage::loadImageInfo( int seq, int ang )
lut.push_back((int)((lt[n]+0.5)*255));
}
delete[] lt;
#ifdef DEBUG
#ifdef KAKADU_DEBUG
logfile << "Kakadu :: Palette with " << j2k_palette.get_num_luts() << " LUT and " << entries
<< " entries/LUT with values " << lut[0] << "," << lut[1] << endl;
#endif
Expand All @@ -339,7 +338,7 @@ void KakaduImage::loadImageInfo( int seq, int ang )
if( cs == JP2_sRGB_SPACE || cs == JP2_iccRGB_SPACE || cs == JP2_esRGB_SPACE || cs == JP2_CIELab_SPACE ) colourspace = sRGB;
//else if ( cs == JP2_CIELab_SPACE ) colourspace = CIELAB;
else {
#ifdef DEBUG
#ifdef KAKADU_DEBUG
logfile << "WARNING : colour space not found, setting sRGB colour space value" << endl;
#endif
colourspace = sRGB;
Expand All @@ -350,7 +349,7 @@ void KakaduImage::loadImageInfo( int seq, int ang )
// Get the number of quality layers - must first open a tile, however
kdu_tile kt = codestream.open_tile(kdu_coords(0,0),NULL);
quality_layers = codestream.get_max_tile_layers();
#ifdef DEBUG
#ifdef KAKADU_DEBUG
string cs;
switch( j2k_colour.get_space() ){
case JP2_sRGB_SPACE:
Expand Down Expand Up @@ -401,7 +400,7 @@ void KakaduImage::loadImageInfo( int seq, int ang )
kdu_long bs = box.get_box_bytes();
kdu_long hs = box.get_box_header_length();
kdu_long xmp_size = bs - hs;
#if DEBUG
#if KAKADU_DEBUG
logfile << "Kakadu :: XML metadata size: " << xmp_size << endl;
#endif
// Skip box header
Expand All @@ -423,7 +422,7 @@ void KakaduImage::loadImageInfo( int seq, int ang )
// Close our image descriptors
void KakaduImage::closeImage()
{
#ifdef DEBUG
#ifdef KAKADU_DEBUG
Timer timer;
timer.start();
#endif
Expand All @@ -435,7 +434,7 @@ void KakaduImage::closeImage()
src.close();
jpx_input.close();

#ifdef DEBUG
#ifdef KAKADU_DEBUG
logfile << "Kakadu :: closeImage() :: " << timer.getTime() << " microseconds" << endl;
#endif
}
Expand All @@ -450,7 +449,7 @@ RawTile KakaduImage::getTile( int seq, int ang, unsigned int res, int layers, un
if( bpc <= 16 && bpc > 8 ) obpc = 16;
else if( bpc <= 8 ) obpc = 8;

#ifdef DEBUG
#ifdef KAKADU_DEBUG
Timer timer;
timer.start();
#endif
Expand Down Expand Up @@ -498,7 +497,7 @@ RawTile KakaduImage::getTile( int seq, int ang, unsigned int res, int layers, un
int xoffset = (tile % ntlx) * tile_widths[0];
int yoffset = (unsigned int) floor((double)(tile/ntlx)) * tile_heights[0];

#ifdef DEBUG
#ifdef KAKADU_DEBUG
logfile << "Kakadu :: Tile size: " << tw << "x" << th << "@" << channels << endl;
#endif

Expand All @@ -516,7 +515,7 @@ RawTile KakaduImage::getTile( int seq, int ang, unsigned int res, int layers, un
process( res, layers, xoffset, yoffset, tw, th, rawtile.data );


#ifdef DEBUG
#ifdef KAKADU_DEBUG
logfile << "Kakadu :: bytes parsed: " << codestream.get_total_bytes(true) << endl;
logfile << "Kakadu :: getTile() :: " << timer.getTime() << " microseconds" << endl;
#endif
Expand All @@ -534,7 +533,7 @@ RawTile KakaduImage::getRegion( int seq, int ang, unsigned int res, int layers,
if( bpc <= 16 && bpc > 8 ) obpc = 16;
else if( bpc <= 8 ) obpc = 8;

#ifdef DEBUG
#ifdef KAKADU_DEBUG
Timer timer;
timer.start();
#endif
Expand All @@ -549,7 +548,7 @@ RawTile KakaduImage::getRegion( int seq, int ang, unsigned int res, int layers,

process( res, layers, x, y, w, h, rawtile.data );

#ifdef DEBUG
#ifdef KAKADU_DEBUG
logfile << "Kakadu :: getRegion() :: " << timer.getTime() << " microseconds" << endl;
#endif

Expand Down Expand Up @@ -577,7 +576,7 @@ void KakaduImage::process( unsigned int res, int layers, int xoffset, int yoffse
tw *= factor;
th *= factor;
vipsres = numResolutions - 1 - virtual_levels;
#ifdef DEBUG
#ifdef KAKADU_DEBUG
logfile << "Kakadu :: using smallest existing resolution " << virtual_levels << endl;
#endif
}
Expand Down Expand Up @@ -620,7 +619,7 @@ void KakaduImage::process( unsigned int res, int layers, int xoffset, int yoffse



#ifdef DEBUG
#ifdef KAKADU_DEBUG
logfile << "Kakadu :: decompressor init with " << num_threads << " threads" << endl;
logfile << "Kakadu :: decoding " << layers << " quality layers" << endl;
#endif
Expand All @@ -641,7 +640,7 @@ void KakaduImage::process( unsigned int res, int layers, int xoffset, int yoffse
stripe_heights = new int[channels];
codestream.get_dims(0,comp_dims,true);

#ifdef DEBUG
#ifdef KAKADU_DEBUG
logfile << "Kakadu :: decompressor starting" << endl;

logfile << "Kakadu :: requested region on high resolution canvas: position: "
Expand All @@ -654,7 +653,7 @@ void KakaduImage::process( unsigned int res, int layers, int xoffset, int yoffse

// Make sure we don't have zero or negative sized images
if( comp_dims.size.x <= 0 || comp_dims.size.y <= 0 ){
#ifdef DEBUG
#ifdef KAKADU_DEBUG
logfile << "Kakadu :: Error: region of zero size requested" << endl;
#endif
throw 1;
Expand All @@ -668,7 +667,7 @@ void KakaduImage::process( unsigned int res, int layers, int xoffset, int yoffse
decompressor.get_recommended_stripe_heights( comp_dims.size.y,
1024, stripe_heights, NULL );

#ifdef DEBUG
#ifdef KAKADU_DEBUG
logfile << "Kakadu :: Allocating memory for stripe height " << stripe_heights[0] << endl;
#endif

Expand Down Expand Up @@ -706,14 +705,14 @@ void KakaduImage::process( unsigned int res, int layers, int xoffset, int yoffse
stripe_buffer = new kdu_byte[tw*stripe_heights[0]*channels];
}

#ifdef DEBUG
#ifdef KAKADU_DEBUG
logfile << "Kakadu :: Stripe height increase: re-allocating memory for height " << stripe_heights[0] << endl;
#endif
}

// Check for zero height, which can occur with incorrect position or size parameters
if( stripe_heights[0] == 0 ){
#ifdef DEBUG
#ifdef KAKADU_DEBUG
logfile << "Kakadu :: Error: Zero stripe height" << endl;
#endif
throw 1;
Expand All @@ -730,7 +729,7 @@ void KakaduImage::process( unsigned int res, int layers, int xoffset, int yoffse
}


#ifdef DEBUG
#ifdef KAKADU_DEBUG
logfile << "Kakadu :: stripe pulled" << endl;
#endif

Expand Down Expand Up @@ -773,7 +772,7 @@ void KakaduImage::process( unsigned int res, int layers, int xoffset, int yoffse
// Advance our output buffer pointer
index += tw * stripe_heights[0] * channels;

#ifdef DEBUG
#ifdef KAKADU_DEBUG
logfile << "Kakadu :: stripe complete with height " << stripe_heights[0] << endl;
#endif

Expand All @@ -788,7 +787,7 @@ void KakaduImage::process( unsigned int res, int layers, int xoffset, int yoffse
// Shrink virtual resolution tiles
if( res < virtual_levels ){

#ifdef DEBUG
#ifdef KAKADU_DEBUG
logfile << "Kakadu :: resizing tile to virtual resolution with factor " << (1 << (virtual_levels-res)) << endl;
#endif

Expand All @@ -813,7 +812,7 @@ void KakaduImage::process( unsigned int res, int layers, int xoffset, int yoffse
// Delete our local buffer
delete_buffer( buffer );

#ifdef DEBUG
#ifdef KAKADU_DEBUG
logfile << "Kakadu :: decompressor completed" << endl;
#endif

Expand Down
Loading

0 comments on commit 37aebe6

Please sign in to comment.