iipsrv 1.3
iipsrv is an advanced high-performance feature-rich image server for web-based streamed viewing and zooming of ultra high-resolution images
RawTile.h
1
2
3/* IIPImage Server
4
5 Copyright (C) 2000-2024 Ruven Pillay.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software Foundation,
19 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
20*/
21
22
23#ifndef _RAWTILE_H
24#define _RAWTILE_H
25#include <cstring>
26#include <string>
27#include <cstdlib>
28#include <cstdint>
29#include <ctime>
30
31
32
34enum class ColorSpace { NONE, GREYSCALE, sRGB, CIELAB, BINARY };
35
37enum class ImageEncoding { UNSUPPORTED, RAW, TIFF, JPEG2000, JPEG, DEFLATE, PNG, WEBP, AVIF };
38
40enum class SampleType { FIXEDPOINT, FLOATINGPOINT };
41
42
43
45class RawTile {
46
47 public:
48
50 std::string filename;
51
53 unsigned int width;
54
56 unsigned int height;
57
60
62 int bpc;
63
65 SampleType sampleType;
66
68 ImageEncoding compressionType;
69
72
74 time_t timestamp;
75
78
81
84
87
89 uint32_t capacity;
90
92 uint32_t dataLength;
93
96
98
100 void *data;
101
102
104
113 RawTile( int tn = 0, int res = 0, int hs = 0, int vs = 0,
114 int w = 0, int h = 0, int c = 0, int b = 0 )
115 : width( w ),
116 height( h ),
117 channels( c ),
118 bpc( b ),
119 sampleType( SampleType::FIXEDPOINT ),
120 compressionType( ImageEncoding::RAW ),
121 quality( 0 ),
122 timestamp( 0 ),
123 tileNum( tn ),
124 resolution( res ),
125 hSequence( hs ),
126 vSequence( vs ),
127 capacity( 0 ),
128 dataLength( 0 ),
129 memoryManaged( 1 ),
130 data( NULL ) {};
131
132
133
137 }
138
139
140
142 RawTile( const RawTile& tile )
143 : filename( tile.filename ),
144 width( tile.width ),
145 height( tile.height ),
146 channels( tile.channels ),
147 bpc( tile.bpc ),
148 sampleType( tile.sampleType ),
150 quality( tile.quality ),
151 timestamp( tile.timestamp ),
152 tileNum( tile.tileNum ),
153 resolution( tile.resolution ),
154 hSequence( tile.hSequence ),
155 vSequence( tile.vSequence ),
156 capacity( tile.capacity ),
157 dataLength( tile.dataLength ),
159 data( NULL )
160 {
161
162 if( tile.data && tile.dataLength > 0 ){
163 allocate( tile.dataLength );
164 memcpy( data, tile.data, tile.dataLength );
165 memoryManaged = 1;
166 }
167
168 }
169
170
171
173 RawTile& operator= ( const RawTile& tile ) {
174
175 if( this != &tile ){
176
177 tileNum = tile.tileNum;
178 resolution = tile.resolution;
179 hSequence = tile.hSequence;
180 vSequence = tile.vSequence;
182 quality = tile.quality;
183 filename = tile.filename;
184 timestamp = tile.timestamp;
186 dataLength = tile.dataLength;
187 width = tile.width;
188 height = tile.height;
189 channels = tile.channels;
190 bpc = tile.bpc;
191 sampleType = tile.sampleType;
192 capacity = tile.capacity;
193
194 if( tile.data && tile.dataLength > 0 ){
195 allocate( tile.dataLength );
196 memcpy( data, tile.data, tile.dataLength );
197 memoryManaged = 1;
198 }
199 }
200
201 return *this;
202 }
203
204
205
207
209 void allocate( uint32_t size = 0 ) {
210
211 if( size == 0 ) size = (uint32_t) width * height * channels * (bpc/8);
212
213 switch( bpc ){
214 case 32:
215 if( sampleType == SampleType::FLOATINGPOINT ) data = new float[size/4];
216 else data = new int[size/4];
217 break;
218 case 16:
219 data = new unsigned short[size/2];
220 break;
221 default:
222 data = new unsigned char[size];
223 break;
224 }
225
226 memoryManaged = 1;
227 capacity = size;
228 };
229
230
231
233 void deallocate( void* buffer ) {
234
235 if( buffer ){
236 switch( bpc ){
237 case 32:
238 if( sampleType == SampleType::FLOATINGPOINT ) delete[] (float*) buffer;
239 else delete[] (unsigned int*) buffer;
240 break;
241 case 16:
242 delete[] (unsigned short*) buffer;
243 break;
244 default:
245 delete[] (unsigned char*) buffer;
246 break;
247 }
248
249 buffer = NULL;
250 capacity = 0;
251 dataLength = 0;
252 }
253 };
254
255
256
258
261 void crop( const unsigned int w, const unsigned int h ) {
262
263 // Keep track of original data buffer and whether we manage it
264 void* buffer = data;
265 int mm = memoryManaged;
266
267 // Create a new buffer with the new size
268 unsigned int len = w * h * channels * (bpc/8);
269 allocate( len );
270
271 unsigned char* src_ptr = (unsigned char*) buffer;
272 unsigned char* dst_ptr = (unsigned char*) data;
273
274 // Copy one entire scanline at a time
275 unsigned int dlen = w * channels * (bpc/8);
276 unsigned int slen = width * channels * (bpc/8);
277
278 for( unsigned int i=0; i<h; i++ ){
279 memcpy( dst_ptr, src_ptr, dlen );
280 dst_ptr += dlen;
281 src_ptr += slen;
282 }
283
284 // Delete original memory buffer
285 if( mm ) deallocate( buffer );
286
287 // Set the new tile dimensions and data storage size
288 capacity = len; // Need to set this manually as deallocate sets this to zero
289 dataLength = len;
290 width = w;
291 height = h;
292 };
293
294
295
297 void triplicate() {
298
299 if( channels != 1 ) return;
300
301 // Keep track of original data buffer and whether we manage it
302 void* buffer = data;
303 int mm = memoryManaged;
304
305 // Create a new buffer with the new size - make sure we update channel number first
306 channels = 3;
307 allocate();
308
309 // Loop through each pixel and duplicate
310 unsigned int len = width * height;
311 uint32_t n = 0;
312 for( uint32_t i=0; i<len; i++ ){
313 for( uint8_t k=0; k<3; k++ ){
314 if( bpc == 32 ){
315 if( sampleType == SampleType::FLOATINGPOINT ) ((float*) data)[n+k] = ((float*) buffer)[i];
316 else ((unsigned int*) data)[n+k] = ((unsigned int*) buffer)[i];
317 }
318 else if( bpc == 16 ) ((unsigned short*) data)[n+k] = ((unsigned short*) buffer)[i];
319 else ((unsigned char*) data)[n+k] = ((unsigned char*) buffer)[i];
320 }
321 n += 3;
322 }
323
324 // Delete original memory buffer
325 if( mm ) deallocate( buffer );
326
327 // Set the new tile dimensions and data storage size
328 capacity = len; // Need to set this manually as deallocate sets this to zero
329 dataLength = len;
330 };
331
332
333
335 friend int operator == ( const RawTile& A, const RawTile& B ) {
336 if( (A.tileNum == B.tileNum) &&
337 (A.resolution == B.resolution) &&
338 (A.hSequence == B.hSequence) &&
339 (A.vSequence == B.vSequence) &&
341 (A.quality == B.quality) &&
342 (A.filename == B.filename) ){
343 return 1;
344 }
345 else return 0;
346 }
347
348
349
351 friend int operator != ( const RawTile& A, const RawTile& B ) {
352 if( (A.tileNum == B.tileNum) &&
353 (A.resolution == B.resolution) &&
354 (A.hSequence == B.hSequence) &&
355 (A.vSequence == B.vSequence) &&
357 (A.quality == B.quality) &&
358 (A.filename == B.filename) ){
359 return 0;
360 }
361 else return 1;
362 }
363
364
365
366 // Memory efficient move operators possible in C++11 onwards
367#if (__cplusplus >= 201103L) || ((defined(_MSC_VER) && _MSC_VER >= 1900))
368
370 RawTile( RawTile&& tile ) noexcept
371 : filename( tile.filename ),
372 width( tile.width ),
373 height( tile.height ),
374 channels( tile.channels ),
375 bpc( tile.bpc ),
376 sampleType( tile.sampleType ),
377 compressionType( tile.compressionType ),
378 quality( tile.quality ),
379 timestamp( tile.timestamp ),
380 tileNum( tile.tileNum ),
381 resolution( tile.resolution ),
382 hSequence( tile.hSequence ),
383 vSequence( tile.vSequence ),
384 capacity( tile.capacity ),
385 dataLength( tile.dataLength ),
386 memoryManaged( tile.memoryManaged ),
387 data( NULL )
388 {
389
390 if( tile.memoryManaged == 1 ){
391
392 // Transfer ownership of data
393 data = tile.data;
394
395 // Free data from other RawTile
396 tile.data = nullptr;
397 tile.dataLength = 0;
398 tile.capacity = 0;
399 tile.memoryManaged = 0;
400 }
401 // Need to copy data if other tile is not owner of its data
402 else if( tile.data && tile.dataLength > 0 ){
403 allocate( tile.dataLength );
404 memcpy( data, tile.data, tile.dataLength );
405 memoryManaged = 1;
406 }
407 }
408
409
410
412 RawTile& operator= ( RawTile&& tile ) noexcept {
413
414 if( this != &tile ){
415
416 if( data && dataLength>0 ) delete this;
417
418 // Use move for std::string. The other fields are of basic type
419 filename = std::move( tile.filename );
420 tileNum = tile.tileNum;
421 resolution = tile.resolution;
422 hSequence = tile.hSequence;
423 vSequence = tile.vSequence;
424 compressionType = tile.compressionType;
425 quality = tile.quality;
426 timestamp = tile.timestamp;
427 memoryManaged = tile.memoryManaged;
428 capacity = tile.capacity;
429 dataLength = tile.dataLength;
430 width = tile.width;
431 height = tile.height;
432 channels = tile.channels;
433 bpc = tile.bpc;
434 sampleType = tile.sampleType;
435
436 if( tile.memoryManaged == 1 ){
437
438 // Transfer ownership of raw data
439 data = tile.data;
440
441 // Free data from other tile
442 tile.data = nullptr;
443 tile.dataLength = 0;
444 tile.capacity = 0;
445 tile.memoryManaged = 0;
446 }
447 else if( tile.data && tile.dataLength > 0 ){
448 allocate( tile.dataLength );
449 memcpy( data, tile.data, tile.dataLength );
450 memoryManaged = 1;
451 }
452 }
453
454 return *this;
455 }
456
457#endif
458
459};
460
461
462#endif
Class to represent a single image tile.
Definition RawTile.h:45
RawTile(int tn=0, int res=0, int hs=0, int vs=0, int w=0, int h=0, int c=0, int b=0)
Main constructor.
Definition RawTile.h:113
unsigned int width
The width in pixels of this tile.
Definition RawTile.h:53
uint32_t dataLength
The size of the data pointed to by the data pointer in bytes.
Definition RawTile.h:92
ImageEncoding compressionType
Compression type.
Definition RawTile.h:68
std::string filename
Name of the file from which this tile comes.
Definition RawTile.h:50
int bpc
The number of bits per channel for this tile.
Definition RawTile.h:62
void allocate(uint32_t size=0)
Allocate memory for the tile.
Definition RawTile.h:209
friend int operator!=(const RawTile &A, const RawTile &B)
Overloaded non-equality operator.
Definition RawTile.h:351
time_t timestamp
Tile timestamp.
Definition RawTile.h:74
int vSequence
The vertical angle to which this tile belongs.
Definition RawTile.h:86
RawTile & operator=(const RawTile &tile)
Copy assignment constructor.
Definition RawTile.h:173
friend int operator==(const RawTile &A, const RawTile &B)
Overloaded equality operator.
Definition RawTile.h:335
~RawTile()
Destructor to free the data array if is has previously be allocated locally.
Definition RawTile.h:135
uint32_t capacity
Amount of memory actually allocated in bytes.
Definition RawTile.h:89
void crop(const unsigned int w, const unsigned int h)
Crop tile to the defined dimensions.
Definition RawTile.h:261
int tileNum
The tile number for this tile.
Definition RawTile.h:77
int resolution
The resolution number to which this tile belongs.
Definition RawTile.h:80
void triplicate()
Expand monochrome 1 band image to 3 by duplicating channels.
Definition RawTile.h:297
void deallocate(void *buffer)
Free our data buffer.
Definition RawTile.h:233
void * data
Pointer to the image data.
Definition RawTile.h:100
RawTile(const RawTile &tile)
Copy constructor - handles copying of data buffer.
Definition RawTile.h:142
SampleType sampleType
Sample format type (fixed or floating point)
Definition RawTile.h:65
int memoryManaged
Definition RawTile.h:97
int channels
The number of channels for this tile.
Definition RawTile.h:59
int quality
Compression rate or quality.
Definition RawTile.h:71
int hSequence
The horizontal angle to which this tile belongs.
Definition RawTile.h:83
unsigned int height
The height in pixels of this tile.
Definition RawTile.h:56