Coverage Report

Created: 2023-12-08 06:53

/src/freeimage-svn/FreeImage/trunk/Source/Utilities.h
Line
Count
Source (jump to first uncovered line)
1
// ==========================================================
2
// Utility functions
3
//
4
// Design and implementation by
5
// - Floris van den Berg (flvdberg@wxs.nl)
6
// - Hervé Drolon <drolon@infonie.fr>
7
// - Ryan Rubley (ryan@lostreality.org)
8
// - Mihail Naydenov (mnaydenov@users.sourceforge.net)
9
//
10
// This file is part of FreeImage 3
11
//
12
// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
13
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
14
// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
15
// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
16
// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
17
// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
18
// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
19
// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
20
// THIS DISCLAIMER.
21
//
22
// Use at your own risk!
23
// ==========================================================
24
25
#ifndef FREEIMAGE_UTILITIES_H
26
#define FREEIMAGE_UTILITIES_H
27
28
// ==========================================================
29
//   Standard includes used by the library
30
// ==========================================================
31
32
#include <math.h>
33
#include <stdlib.h> 
34
#include <memory.h>
35
#include <stdio.h>
36
#include <string.h>
37
#include <stdarg.h>
38
#include <ctype.h>
39
#include <assert.h>
40
#include <errno.h>
41
#include <float.h>
42
#include <limits.h>
43
44
#include <string>
45
#include <list>
46
#include <map>
47
#include <set>
48
#include <vector>
49
#include <stack>
50
#include <sstream>
51
#include <algorithm>
52
#include <limits>
53
#include <memory>
54
55
// ==========================================================
56
//   Bitmap palette and pixels alignment
57
// ==========================================================
58
59
158M
#define FIBITMAP_ALIGNMENT  16  // We will use a 16 bytes alignment boundary
60
61
// Memory allocation on a specified alignment boundary
62
// defined in BitmapAccess.cpp
63
64
void* FreeImage_Aligned_Malloc(size_t amount, size_t alignment);
65
void FreeImage_Aligned_Free(void* mem);
66
67
#if defined(__cplusplus)
68
extern "C" {
69
#endif
70
71
/**
72
Allocate a FIBITMAP with possibly no pixel data 
73
(i.e. only header data and some or all metadata)
74
@param header_only If TRUE, allocate a 'header only' FIBITMAP, otherwise allocate a full FIBITMAP
75
@param type Image type
76
@param width Image width
77
@param height Image height
78
@param bpp Number of bits per pixel
79
@param red_mask Image red mask 
80
@param green_mask Image green mask
81
@param blue_mask Image blue mask
82
@return Returns the allocated FIBITMAP
83
@see FreeImage_AllocateT
84
*/
85
DLL_API FIBITMAP * DLL_CALLCONV FreeImage_AllocateHeaderT(BOOL header_only, FREE_IMAGE_TYPE type, int width, int height, int bpp FI_DEFAULT(8), unsigned red_mask FI_DEFAULT(0), unsigned green_mask FI_DEFAULT(0), unsigned blue_mask FI_DEFAULT(0));
86
87
/**
88
Allocate a FIBITMAP of type FIT_BITMAP, with possibly no pixel data 
89
(i.e. only header data and some or all metadata)
90
@param header_only If TRUE, allocate a 'header only' FIBITMAP, otherwise allocate a full FIBITMAP
91
@param width Image width
92
@param height Image height
93
@param bpp Number of bits per pixel
94
@param red_mask Image red mask 
95
@param green_mask Image green mask
96
@param blue_mask Image blue mask
97
@return Returns the allocated FIBITMAP
98
@see FreeImage_Allocate
99
*/
100
DLL_API FIBITMAP * DLL_CALLCONV FreeImage_AllocateHeader(BOOL header_only, int width, int height, int bpp, unsigned red_mask FI_DEFAULT(0), unsigned green_mask FI_DEFAULT(0), unsigned blue_mask FI_DEFAULT(0));
101
102
/**
103
Allocate a FIBITMAP with no pixel data and wrap a user provided pixel buffer
104
@param ext_bits Pointer to external user's pixel buffer
105
@param ext_pitch Pointer to external user's pixel buffer pitch
106
@param type Image type
107
@param width Image width
108
@param height Image height
109
@param bpp Number of bits per pixel
110
@param red_mask Image red mask 
111
@param green_mask Image green mask
112
@param blue_mask Image blue mask
113
@return Returns the allocated FIBITMAP
114
@see FreeImage_ConvertFromRawBitsEx
115
*/
116
DLL_API FIBITMAP * DLL_CALLCONV FreeImage_AllocateHeaderForBits(BYTE *ext_bits, unsigned ext_pitch, FREE_IMAGE_TYPE type, int width, int height, int bpp, unsigned red_mask, unsigned green_mask, unsigned blue_mask);
117
118
/**
119
Helper for 16-bit FIT_BITMAP
120
@see FreeImage_GetRGBMasks
121
*/
122
DLL_API BOOL DLL_CALLCONV FreeImage_HasRGBMasks(FIBITMAP *dib);
123
124
#if defined(__cplusplus)
125
}
126
#endif
127
128
129
// ==========================================================
130
//   File I/O structs
131
// ==========================================================
132
133
// these structs are for file I/O and should not be confused with similar
134
// structs in FreeImage.h which are for in-memory bitmap handling
135
136
#ifdef _WIN32
137
#pragma pack(push, 1)
138
#else
139
#pragma pack(1)
140
#endif // _WIN32
141
142
typedef struct tagFILE_RGBA {
143
  unsigned char r,g,b,a;
144
} FILE_RGBA;
145
146
typedef struct tagFILE_BGRA {
147
  unsigned char b,g,r,a;
148
} FILE_BGRA;
149
150
typedef struct tagFILE_RGB {
151
  unsigned char r,g,b;
152
} FILE_RGB;
153
154
typedef struct tagFILE_BGR {
155
  unsigned char b,g,r;
156
} FILE_BGR;
157
158
#ifdef _WIN32
159
#pragma pack(pop)
160
#else
161
#pragma pack()
162
#endif // _WIN32
163
164
// ==========================================================
165
//   Template utility functions
166
// ==========================================================
167
168
/// Max function
169
0
template <class T> T MAX(const T &a, const T &b) {
170
0
  return (a > b) ? a: b;
171
0
}
Unexecuted instantiation: int MAX<int>(int const&, int const&)
Unexecuted instantiation: double MAX<double>(double const&, double const&)
Unexecuted instantiation: unsigned int MAX<unsigned int>(unsigned int const&, unsigned int const&)
Unexecuted instantiation: unsigned long MAX<unsigned long>(unsigned long const&, unsigned long const&)
172
173
/// Min function
174
9.26k
template <class T> T MIN(const T &a, const T &b) {
175
9.26k
  return (a < b) ? a: b;
176
9.26k
}
int MIN<int>(int const&, int const&)
Line
Count
Source
174
5.24k
template <class T> T MIN(const T &a, const T &b) {
175
5.24k
  return (a < b) ? a: b;
176
5.24k
}
unsigned long MIN<unsigned long>(unsigned long const&, unsigned long const&)
Line
Count
Source
174
4.02k
template <class T> T MIN(const T &a, const T &b) {
175
4.02k
  return (a < b) ? a: b;
176
4.02k
}
Unexecuted instantiation: unsigned int MIN<unsigned int>(unsigned int const&, unsigned int const&)
Unexecuted instantiation: long MIN<long>(long const&, long const&)
Unexecuted instantiation: unsigned short MIN<unsigned short>(unsigned short const&, unsigned short const&)
Unexecuted instantiation: double MIN<double>(double const&, double const&)
177
178
/// INPLACESWAP adopted from codeguru.com 
179
0
template <class T> void INPLACESWAP(T& a, T& b) {
180
0
  a ^= b; b ^= a; a ^= b;
181
0
}
182
183
/// Clamp function
184
0
template <class T> T CLAMP(const T &value, const T &min_value, const T &max_value) {
185
0
  return ((value < min_value) ? min_value : (value > max_value) ? max_value : value);
186
0
}
Unexecuted instantiation: unsigned int CLAMP<unsigned int>(unsigned int const&, unsigned int const&, unsigned int const&)
Unexecuted instantiation: float CLAMP<float>(float const&, float const&, float const&)
187
188
/** This procedure computes minimum min and maximum max
189
 of n numbers using only (3n/2) - 2 comparisons.
190
 min = L[i1] and max = L[i2].
191
 ref: Aho A.V., Hopcroft J.E., Ullman J.D., 
192
 The design and analysis of computer algorithms, 
193
 Addison-Wesley, Reading, 1974.
194
*/
195
template <class T> void 
196
MAXMIN(const T* L, long n, T& max, T& min) {
197
  long i1, i2, i, j;
198
  T x1, x2;
199
  long k1, k2;
200
201
  i1 = 0; i2 = 0; min = L[0]; max = L[0]; j = 0;
202
  if((n % 2) != 0)  j = 1;
203
  for(i = j; i < n; i+= 2) {
204
    k1 = i; k2 = i+1;
205
    x1 = L[k1]; x2 = L[k2];
206
    if(x1 > x2) {
207
      k1 = k2;  k2 = i;
208
      x1 = x2;  x2 = L[k2];
209
    }
210
    if(x1 < min) {
211
      min = x1;  i1 = k1;
212
    }
213
    if(x2 > max) {
214
      max = x2;  i2 = k2;
215
    }
216
  }
217
}
218
219
// ==========================================================
220
//   Utility functions
221
// ==========================================================
222
223
#ifndef _WIN32
224
inline char*
225
0
i2a(unsigned i, char *a, unsigned r) {
226
0
  if (i/r > 0) a = i2a(i/r,a,r);
227
0
  *a = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[i%r];
228
0
  return a+1;
229
0
}
230
231
/** 
232
 Transforms integer i into an ascii string and stores the result in a; 
233
 string is encoded in the base indicated by r.
234
 @param i Number to be converted
235
 @param a String result
236
 @param r Base of value; must be in the range 2 - 36
237
 @return Returns a
238
*/
239
inline char *
240
0
_itoa(int i, char *a, int r) {
241
0
  r = ((r < 2) || (r > 36)) ? 10 : r;
242
0
  if(i < 0) {
243
0
    *a = '-';
244
0
    *i2a(-i, a+1, r) = 0;
245
0
  }
246
0
  else *i2a(i, a, r) = 0;
247
0
  return a;
248
0
}
249
250
#endif // !_WIN32
251
252
inline unsigned char
253
0
HINIBBLE (unsigned char byte) {
254
0
  return byte & 0xF0;
255
0
}
256
257
inline unsigned char
258
0
LOWNIBBLE (unsigned char byte) {
259
0
  return byte & 0x0F;
260
0
}
261
262
inline int
263
0
CalculateUsedBits(int bits) {
264
0
  int bit_count = 0;
265
0
  unsigned bit = 1;
266
0
267
0
  for (unsigned i = 0; i < 32; i++) {
268
0
    if ((bits & bit) == bit) {
269
0
      bit_count++;
270
0
    }
271
0
272
0
    bit <<= 1;
273
0
  }
274
0
275
0
  return bit_count;
276
0
}
277
278
inline unsigned
279
109
CalculateLine(const unsigned width, const unsigned bitdepth) {
280
109
  return (unsigned)( ((unsigned long long)width * bitdepth + 7) / 8 );
281
109
}
282
283
inline unsigned
284
109
CalculatePitch(const unsigned line) {
285
109
  return (line + 3) & ~3;
286
109
}
287
288
inline unsigned
289
188
CalculateUsedPaletteEntries(const unsigned bit_count) {
290
188
  if ((bit_count >= 1) && (bit_count <= 8)) {
291
170
    return 1 << bit_count;
292
170
  }
293
294
18
  return 0;
295
188
}
296
297
inline BYTE*
298
6.10M
CalculateScanLine(BYTE *bits, const unsigned pitch, const int scanline) {
299
6.10M
  return bits ? (bits + ((size_t)pitch * scanline)) : NULL;
300
6.10M
}
301
302
// ----------------------------------------------------------
303
304
/**
305
Fast generic assign (faster than for loop)
306
@param dst Destination pixel
307
@param src Source pixel
308
@param bytesperpixel # of bytes per pixel
309
*/
310
inline void 
311
0
AssignPixel(BYTE* dst, const BYTE* src, unsigned bytesperpixel) {
312
0
  switch (bytesperpixel) {
313
0
    case 1: // FIT_BITMAP (8-bit)
314
0
      *dst = *src;
315
0
      break;
316
317
0
    case 2: // FIT_UINT16 / FIT_INT16 / 16-bit
318
0
      *(reinterpret_cast<WORD*>(dst)) = *(reinterpret_cast<const WORD*> (src));
319
0
      break;
320
321
0
    case 3: // FIT_BITMAP (24-bit)
322
0
      *(reinterpret_cast<WORD*>(dst)) = *(reinterpret_cast<const WORD*> (src));
323
0
      dst[2] = src[2];
324
0
      break;
325
326
0
    case 4: // FIT_BITMAP (32-bit) / FIT_UINT32 / FIT_INT32 / FIT_FLOAT
327
0
      *(reinterpret_cast<DWORD*>(dst)) = *(reinterpret_cast<const DWORD*> (src));
328
0
      break;
329
330
0
    case 6: // FIT_RGB16 (3 x 16-bit)
331
0
      *(reinterpret_cast<DWORD*>(dst)) = *(reinterpret_cast<const DWORD*> (src));
332
0
      *(reinterpret_cast<WORD*>(dst + 4)) = *(reinterpret_cast<const WORD*> (src + 4)); 
333
0
      break;
334
335
    // the rest can be speeded up with int64
336
      
337
0
    case 8: // FIT_RGBA16 (4 x 16-bit)
338
0
      *(reinterpret_cast<DWORD*>(dst)) = *(reinterpret_cast<const DWORD*> (src));
339
0
      *(reinterpret_cast<DWORD*>(dst + 4)) = *(reinterpret_cast<const DWORD*> (src + 4)); 
340
0
      break;
341
    
342
0
    case 12: // FIT_RGBF (3 x 32-bit IEEE floating point)
343
0
      *(reinterpret_cast<float*>(dst)) = *(reinterpret_cast<const float*> (src));
344
0
      *(reinterpret_cast<float*>(dst + 4)) = *(reinterpret_cast<const float*> (src + 4));
345
0
      *(reinterpret_cast<float*>(dst + 8)) = *(reinterpret_cast<const float*> (src + 8));
346
0
      break;
347
    
348
0
    case 16: // FIT_RGBAF (4 x 32-bit IEEE floating point)
349
0
      *(reinterpret_cast<float*>(dst)) = *(reinterpret_cast<const float*> (src));
350
0
      *(reinterpret_cast<float*>(dst + 4)) = *(reinterpret_cast<const float*> (src + 4));
351
0
      *(reinterpret_cast<float*>(dst + 8)) = *(reinterpret_cast<const float*> (src + 8));
352
0
      *(reinterpret_cast<float*>(dst + 12)) = *(reinterpret_cast<const float*> (src + 12));
353
0
      break;
354
      
355
0
    default:
356
0
      assert(FALSE);
357
0
  }
358
0
}
359
360
/**
361
Swap red and blue channels in a 24- or 32-bit dib. 
362
@return Returns TRUE if successful, returns FALSE otherwise
363
@see See definition in Conversion.cpp
364
*/
365
BOOL SwapRedBlue32(FIBITMAP* dib);
366
367
/**
368
Inplace convert CMYK to RGBA.(8- and 16-bit). 
369
Alpha is filled with the first extra channel if any or white otherwise.
370
@return Returns TRUE if successful, returns FALSE otherwise
371
@see See definition in Conversion.cpp
372
*/
373
BOOL ConvertCMYKtoRGBA(FIBITMAP* dib);
374
375
/**
376
Inplace convert CIELab to RGBA (8- and 16-bit).
377
@return Returns TRUE if successful, returns FALSE otherwise
378
@see See definition in Conversion.cpp
379
*/
380
BOOL ConvertLABtoRGB(FIBITMAP* dib);
381
382
/**
383
RGBA to RGB conversion
384
@see See definition in Conversion.cpp
385
*/
386
FIBITMAP* RemoveAlphaChannel(FIBITMAP* dib);
387
388
/**
389
Rotate a dib according to Exif info
390
@param dib Input / Output dib to rotate
391
@see Exif.cpp, PluginJPEG.cpp
392
*/
393
void RotateExif(FIBITMAP **dib);
394
395
396
// ==========================================================
397
//   Big Endian / Little Endian utility functions
398
// ==========================================================
399
400
inline WORD 
401
0
__SwapUInt16(WORD arg) { 
402
#if defined(_MSC_VER) && _MSC_VER >= 1310 
403
  return _byteswap_ushort(arg); 
404
#elif defined(__i386__) && defined(__GNUC__) 
405
  __asm__("xchgb %b0, %h0" : "+q" (arg)); 
406
  return arg; 
407
#elif defined(__ppc__) && defined(__GNUC__) 
408
  WORD result; 
409
  __asm__("lhbrx %0,0,%1" : "=r" (result) : "r" (&arg), "m" (arg)); 
410
  return result; 
411
#else 
412
  // swap bytes 
413
0
  WORD result;
414
0
  result = ((arg << 8) & 0xFF00) | ((arg >> 8) & 0x00FF); 
415
0
  return result; 
416
0
#endif 
417
0
} 
418
 
419
inline DWORD 
420
29.9k
__SwapUInt32(DWORD arg) { 
421
#if defined(_MSC_VER) && _MSC_VER >= 1310 
422
  return _byteswap_ulong(arg); 
423
#elif defined(__i386__) && defined(__GNUC__) 
424
  __asm__("bswap %0" : "+r" (arg)); 
425
  return arg; 
426
#elif defined(__ppc__) && defined(__GNUC__) 
427
  DWORD result; 
428
  __asm__("lwbrx %0,0,%1" : "=r" (result) : "r" (&arg), "m" (arg)); 
429
  return result; 
430
#else 
431
  // swap words then bytes
432
29.9k
  DWORD result; 
433
29.9k
  result = ((arg & 0x000000FF) << 24) | ((arg & 0x0000FF00) << 8) | ((arg >> 8) & 0x0000FF00) | ((arg >> 24) & 0x000000FF); 
434
29.9k
  return result; 
435
29.9k
#endif 
436
29.9k
} 
437
438
inline void
439
0
SwapShort(WORD *sp) {
440
0
  *sp = __SwapUInt16(*sp);
441
0
}
442
443
inline void
444
29.9k
SwapLong(DWORD *lp) {
445
29.9k
  *lp = __SwapUInt32(*lp);
446
29.9k
}
447
 
448
inline void
449
0
SwapInt64(UINT64 *arg) {
450
#if defined(_MSC_VER) && _MSC_VER >= 1310
451
  *arg = _byteswap_uint64(*arg);
452
#else
453
0
  union Swap {
454
0
    UINT64 sv;
455
0
    DWORD ul[2];
456
0
  } tmp, result;
457
0
  tmp.sv = *arg;
458
0
  SwapLong(&tmp.ul[0]);
459
0
  SwapLong(&tmp.ul[1]);
460
0
  result.ul[0] = tmp.ul[1];
461
0
  result.ul[1] = tmp.ul[0];
462
0
  *arg = result.sv;
463
0
#endif
464
0
}
465
466
// ==========================================================
467
//   Greyscale and color conversion
468
// ==========================================================
469
470
/**
471
Extract the luminance channel L from a RGBF image. 
472
Luminance is calculated from the sRGB model using a D65 white point, using the Rec.709 formula : 
473
L = ( 0.2126 * r ) + ( 0.7152 * g ) + ( 0.0722 * b )
474
Reference : 
475
A Standard Default Color Space for the Internet - sRGB. 
476
[online] http://www.w3.org/Graphics/Color/sRGB
477
*/
478
0
#define LUMA_REC709(r, g, b)  (0.2126F * r + 0.7152F * g + 0.0722F * b)
479
480
0
#define GREY(r, g, b) (BYTE)(LUMA_REC709(r, g, b) + 0.5F)
481
/*
482
#define GREY(r, g, b) (BYTE)(((WORD)r * 77 + (WORD)g * 150 + (WORD)b * 29) >> 8)  // .299R + .587G + .114B
483
*/
484
/*
485
#define GREY(r, g, b) (BYTE)(((WORD)r * 169 + (WORD)g * 256 + (WORD)b * 87) >> 9) // .33R + 0.5G + .17B
486
*/
487
488
/**
489
Convert a RGB 24-bit value to a 16-bit 565 value
490
*/
491
0
#define RGB565(b, g, r) ((((b) >> 3) << FI16_565_BLUE_SHIFT) | (((g) >> 2) << FI16_565_GREEN_SHIFT) | (((r) >> 3) << FI16_565_RED_SHIFT))
492
493
/**
494
Convert a RGB 24-bit value to a 16-bit 555 value
495
*/
496
0
#define RGB555(b, g, r) ((((b) >> 3) << FI16_555_BLUE_SHIFT) | (((g) >> 3) << FI16_555_GREEN_SHIFT) | (((r) >> 3) << FI16_555_RED_SHIFT))
497
498
/**
499
Returns TRUE if the format of a dib is RGB565
500
*/
501
0
#define IS_FORMAT_RGB565(dib) ((FreeImage_GetRedMask(dib) == FI16_565_RED_MASK) && (FreeImage_GetGreenMask(dib) == FI16_565_GREEN_MASK) && (FreeImage_GetBlueMask(dib) == FI16_565_BLUE_MASK))
502
503
/**
504
Convert a RGB565 or RGB555 RGBQUAD pixel to a WORD
505
*/
506
0
#define RGBQUAD_TO_WORD(dib, color) (IS_FORMAT_RGB565(dib) ? RGB565((color)->rgbBlue, (color)->rgbGreen, (color)->rgbRed) : RGB555((color)->rgbBlue, (color)->rgbGreen, (color)->rgbRed))
507
508
/**
509
Create a greyscale palette
510
*/
511
#define CREATE_GREYSCALE_PALETTE(palette, entries) \
512
  for (unsigned i = 0, v = 0; i < entries; i++, v += 0x00FFFFFF / (entries - 1)) { \
513
    ((unsigned *)palette)[i] = v; \
514
  }
515
516
/**
517
Create a reverse greyscale palette
518
*/
519
#define CREATE_GREYSCALE_PALETTE_REVERSE(palette, entries) \
520
0
  for (unsigned i = 0, v = 0x00FFFFFF; i < entries; i++, v -= (0x00FFFFFF / (entries - 1))) { \
521
0
    ((unsigned *)palette)[i] = v; \
522
0
  }
523
524
// ==========================================================
525
//   Generic error messages
526
// ==========================================================
527
528
static const char *FI_MSG_ERROR_MEMORY = "Memory allocation failed";
529
static const char *FI_MSG_ERROR_DIB_MEMORY = "DIB allocation failed, maybe caused by an invalid image size or by a lack of memory";
530
static const char *FI_MSG_ERROR_PARSING = "Parsing error";
531
static const char *FI_MSG_ERROR_MAGIC_NUMBER = "Invalid magic number";
532
static const char *FI_MSG_ERROR_UNSUPPORTED_FORMAT = "Unsupported image format";
533
static const char *FI_MSG_ERROR_INVALID_FORMAT = "Invalid file format";
534
static const char *FI_MSG_ERROR_CORRUPTED_IMAGE = "Image is corrupted";
535
static const char *FI_MSG_ERROR_UNSUPPORTED_COMPRESSION = "Unsupported compression type";
536
static const char *FI_MSG_WARNING_INVALID_THUMBNAIL = "Warning: attached thumbnail cannot be written to output file (invalid format) - Thumbnail saving aborted";
537
538
#endif // FREEIMAGE_UTILITIES_H