Coverage Report

Created: 2026-06-09 06:12

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/freeimage-svn/FreeImage/trunk/Source/FreeImage/ConversionRGBF.cpp
Line
Count
Source
1
// ==========================================================
2
// Bitmap conversion routines
3
//
4
// Design and implementation by
5
// - Hervé Drolon (drolon@infonie.fr)
6
//
7
// This file is part of FreeImage 3
8
//
9
// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
10
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
11
// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
12
// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
13
// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
14
// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
15
// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
16
// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
17
// THIS DISCLAIMER.
18
//
19
// Use at your own risk!
20
// ==========================================================
21
22
#include "FreeImage.h"
23
#include "Utilities.h"
24
25
// ----------------------------------------------------------
26
//   smart convert X to RGBF
27
// ----------------------------------------------------------
28
29
FIBITMAP * DLL_CALLCONV
30
0
FreeImage_ConvertToRGBF(FIBITMAP *dib) {
31
0
  FIBITMAP *src = NULL;
32
0
  FIBITMAP *dst = NULL;
33
34
0
  if(!FreeImage_HasPixels(dib)) return NULL;
35
36
0
  const FREE_IMAGE_TYPE src_type = FreeImage_GetImageType(dib);
37
38
  // check for allowed conversions 
39
0
  switch(src_type) {
40
0
    case FIT_BITMAP:
41
0
    {
42
      // allow conversion from 24- and 32-bit
43
0
      const FREE_IMAGE_COLOR_TYPE color_type = FreeImage_GetColorType(dib);
44
0
      if((color_type != FIC_RGB) && (color_type != FIC_RGBALPHA)) {
45
0
        src = FreeImage_ConvertTo24Bits(dib);
46
0
        if(!src) return NULL;
47
0
      } else {
48
0
        src = dib;
49
0
      }
50
0
      break;
51
0
    }
52
0
    case FIT_UINT16:
53
      // allow conversion from 16-bit
54
0
      src = dib;
55
0
      break;
56
0
    case FIT_RGB16:
57
      // allow conversion from 48-bit RGB
58
0
      src = dib;
59
0
      break;
60
0
    case FIT_RGBA16:
61
      // allow conversion from 64-bit RGBA (ignore the alpha channel)
62
0
      src = dib;
63
0
      break;
64
0
    case FIT_FLOAT:
65
      // allow conversion from 32-bit float
66
0
      src = dib;
67
0
      break;
68
0
    case FIT_RGBAF:
69
      // allow conversion from 128-bit RGBAF
70
0
      src = dib;
71
0
      break;
72
0
    case FIT_RGBF:
73
      // RGBF type : clone the src
74
0
      return FreeImage_Clone(dib);
75
0
      break;
76
0
    default:
77
0
      return NULL;
78
0
  }
79
80
  // allocate dst image
81
82
0
  const unsigned width = FreeImage_GetWidth(src);
83
0
  const unsigned height = FreeImage_GetHeight(src);
84
85
0
  dst = FreeImage_AllocateT(FIT_RGBF, width, height);
86
0
  if(!dst) {
87
0
    if(src != dib) {
88
0
      FreeImage_Unload(src);
89
0
    }
90
0
    return NULL;
91
0
  }
92
93
  // copy metadata from src to dst
94
0
  FreeImage_CloneMetadata(dst, src);
95
96
  // convert from src type to RGBF
97
98
0
  const unsigned src_pitch = FreeImage_GetPitch(src);
99
0
  const unsigned dst_pitch = FreeImage_GetPitch(dst);
100
101
0
  switch(src_type) {
102
0
    case FIT_BITMAP:
103
0
    {
104
      // calculate the number of bytes per pixel (3 for 24-bit or 4 for 32-bit)
105
0
      const unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src);
106
107
0
      const BYTE *src_bits = (BYTE*)FreeImage_GetBits(src);
108
0
      BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst);
109
110
0
      for(unsigned y = 0; y < height; y++) {
111
0
        const BYTE   *src_pixel = (BYTE*)src_bits;
112
0
        FIRGBF *dst_pixel = (FIRGBF*)dst_bits;
113
0
        for(unsigned x = 0; x < width; x++) {
114
          // convert and scale to the range [0..1]
115
0
          dst_pixel->red   = (float)(src_pixel[FI_RGBA_RED])   / 255.0F;
116
0
          dst_pixel->green = (float)(src_pixel[FI_RGBA_GREEN]) / 255.0F;
117
0
          dst_pixel->blue  = (float)(src_pixel[FI_RGBA_BLUE])  / 255.0F;
118
119
0
          src_pixel += bytespp;
120
0
          dst_pixel ++;
121
0
        }
122
0
        src_bits += src_pitch;
123
0
        dst_bits += dst_pitch;
124
0
      }
125
0
    }
126
0
    break;
127
128
0
    case FIT_UINT16:
129
0
    {
130
0
      const BYTE *src_bits = (BYTE*)FreeImage_GetBits(src);
131
0
      BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst);
132
133
0
      for(unsigned y = 0; y < height; y++) {
134
0
        const WORD *src_pixel = (WORD*)src_bits;
135
0
        FIRGBF *dst_pixel = (FIRGBF*)dst_bits;
136
137
0
        for(unsigned x = 0; x < width; x++) {
138
          // convert and scale to the range [0..1]
139
0
          const float dst_value = (float)src_pixel[x] / 65535.0F;
140
0
          dst_pixel[x].red   = dst_value;
141
0
          dst_pixel[x].green = dst_value;
142
0
          dst_pixel[x].blue  = dst_value;
143
0
        }
144
0
        src_bits += src_pitch;
145
0
        dst_bits += dst_pitch;
146
0
      }
147
0
    }
148
0
    break;
149
150
0
    case FIT_RGB16:
151
0
    {
152
0
      const BYTE *src_bits = (BYTE*)FreeImage_GetBits(src);
153
0
      BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst);
154
155
0
      for(unsigned y = 0; y < height; y++) {
156
0
        const FIRGB16 *src_pixel = (FIRGB16*) src_bits;
157
0
        FIRGBF  *dst_pixel = (FIRGBF*)  dst_bits;
158
159
0
        for(unsigned x = 0; x < width; x++) {
160
          // convert and scale to the range [0..1]
161
0
          dst_pixel[x].red   = (float)(src_pixel[x].red)   / 65535.0F;
162
0
          dst_pixel[x].green = (float)(src_pixel[x].green) / 65535.0F;
163
0
          dst_pixel[x].blue  = (float)(src_pixel[x].blue)  / 65535.0F;
164
0
        }
165
0
        src_bits += src_pitch;
166
0
        dst_bits += dst_pitch;
167
0
      }
168
0
    }
169
0
    break;
170
171
0
    case FIT_RGBA16:
172
0
    {
173
0
      const BYTE *src_bits = (BYTE*)FreeImage_GetBits(src);
174
0
      BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst);
175
176
0
      for(unsigned y = 0; y < height; y++) {
177
0
        const FIRGBA16 *src_pixel = (FIRGBA16*) src_bits;
178
0
        FIRGBF  *dst_pixel = (FIRGBF*)  dst_bits;
179
180
0
        for(unsigned x = 0; x < width; x++) {
181
          // convert and scale to the range [0..1]
182
0
          dst_pixel[x].red   = (float)(src_pixel[x].red)   / 65535.0F;
183
0
          dst_pixel[x].green = (float)(src_pixel[x].green) / 65535.0F;
184
0
          dst_pixel[x].blue  = (float)(src_pixel[x].blue)  / 65535.0F;
185
0
        }
186
0
        src_bits += src_pitch;
187
0
        dst_bits += dst_pitch;
188
0
      }
189
0
    }
190
0
    break;
191
192
0
    case FIT_FLOAT:
193
0
    {
194
0
      const BYTE *src_bits = (BYTE*)FreeImage_GetBits(src);
195
0
      BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst);
196
197
0
      for(unsigned y = 0; y < height; y++) {
198
0
        const float *src_pixel = (float*) src_bits;
199
0
        FIRGBF  *dst_pixel = (FIRGBF*)  dst_bits;
200
201
0
        for(unsigned x = 0; x < width; x++) {
202
          // convert by copying greyscale channel to each R, G, B channels
203
          // assume float values are in [0..1]
204
0
          const float value = CLAMP(src_pixel[x], 0.0F, 1.0F);
205
0
          dst_pixel[x].red   = value;
206
0
          dst_pixel[x].green = value;
207
0
          dst_pixel[x].blue  = value;
208
0
        }
209
0
        src_bits += src_pitch;
210
0
        dst_bits += dst_pitch;
211
0
      }
212
0
    }
213
0
    break;
214
215
0
    case FIT_RGBAF:
216
0
    {
217
0
      const BYTE *src_bits = (BYTE*)FreeImage_GetBits(src);
218
0
      BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst);
219
220
0
      for(unsigned y = 0; y < height; y++) {
221
0
        const FIRGBAF *src_pixel = (FIRGBAF*) src_bits;
222
0
        FIRGBF  *dst_pixel = (FIRGBF*)  dst_bits;
223
224
0
        for(unsigned x = 0; x < width; x++) {
225
          // convert and skip alpha channel
226
0
          dst_pixel[x].red   = CLAMP(src_pixel[x].red, 0.0F, 1.0F);
227
0
          dst_pixel[x].green = CLAMP(src_pixel[x].green, 0.0F, 1.0F);
228
0
          dst_pixel[x].blue  = CLAMP(src_pixel[x].blue, 0.0F, 1.0F);
229
0
        }
230
0
        src_bits += src_pitch;
231
0
        dst_bits += dst_pitch;
232
0
      }
233
0
    }
234
0
    break;
235
0
  }
236
237
0
  if(src != dib) {
238
0
    FreeImage_Unload(src);
239
0
  }
240
241
0
  return dst;
242
0
}
243