Coverage Report

Created: 2025-06-13 06:50

/src/freeimage-svn/FreeImage/trunk/Source/FreeImage/Conversion8.cpp
Line
Count
Source (jump to first uncovered line)
1
// ==========================================================
2
// Bitmap conversion routines
3
//
4
// Design and implementation by
5
// - Floris van den Berg (flvdberg@wxs.nl)
6
// - Hervé Drolon (drolon@infonie.fr)
7
// - Jani Kajala (janik@remedy.fi)
8
// - Karl-Heinz Bussian (khbussian@moss.de)
9
// - Carsten Klein (cklein05@users.sourceforge.net)
10
//
11
// This file is part of FreeImage 3
12
//
13
// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
14
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
15
// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
16
// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
17
// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
18
// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
19
// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
20
// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
21
// THIS DISCLAIMER.
22
//
23
// Use at your own risk!
24
// ==========================================================
25
26
#include "FreeImage.h"
27
#include "Utilities.h"
28
29
// ----------------------------------------------------------
30
//  internal conversions X to 8 bits
31
// ----------------------------------------------------------
32
33
void DLL_CALLCONV
34
0
FreeImage_ConvertLine1To8(BYTE *target, BYTE *source, int width_in_pixels) {
35
0
  for (unsigned cols = 0; cols < (unsigned)width_in_pixels; cols++)
36
0
    target[cols] = (source[cols >> 3] & (0x80 >> (cols & 0x07))) != 0 ? 255 : 0; 
37
0
}
38
39
void DLL_CALLCONV
40
0
FreeImage_ConvertLine4To8(BYTE *target, BYTE *source, int width_in_pixels) {
41
0
  unsigned count_new = 0;
42
0
  unsigned count_org = 0;
43
0
  BOOL hinibble = TRUE;
44
45
0
  while (count_new < (unsigned)width_in_pixels) {
46
0
    if (hinibble) {
47
0
      target[count_new] = (source[count_org] >> 4);
48
0
    } else {
49
0
      target[count_new] = (source[count_org] & 0x0F);
50
0
      count_org++;
51
0
    }
52
0
    hinibble = !hinibble;
53
0
    count_new++;
54
0
  }
55
0
}
56
57
void DLL_CALLCONV
58
0
FreeImage_ConvertLine16To8_555(BYTE *target, BYTE *source, int width_in_pixels) {
59
0
  const WORD *const bits = (WORD *)source;
60
0
  for (unsigned cols = 0; cols < (unsigned)width_in_pixels; cols++) {
61
0
    target[cols] = GREY((((bits[cols] & FI16_555_RED_MASK) >> FI16_555_RED_SHIFT) * 0xFF) / 0x1F,
62
0
                      (((bits[cols] & FI16_555_GREEN_MASK) >> FI16_555_GREEN_SHIFT) * 0xFF) / 0x1F,
63
0
              (((bits[cols] & FI16_555_BLUE_MASK) >> FI16_555_BLUE_SHIFT) * 0xFF) / 0x1F);
64
0
  }
65
0
}
66
67
void DLL_CALLCONV
68
0
FreeImage_ConvertLine16To8_565(BYTE *target, BYTE *source, int width_in_pixels) {
69
0
  const WORD *const bits = (WORD *)source;
70
0
  for (unsigned cols = 0; cols < (unsigned)width_in_pixels; cols++) {
71
0
    target[cols] = GREY((((bits[cols] & FI16_565_RED_MASK) >> FI16_565_RED_SHIFT) * 0xFF) / 0x1F,
72
0
              (((bits[cols] & FI16_565_GREEN_MASK) >> FI16_565_GREEN_SHIFT) * 0xFF) / 0x3F,
73
0
          (((bits[cols] & FI16_565_BLUE_MASK) >> FI16_565_BLUE_SHIFT) * 0xFF) / 0x1F);
74
0
  }
75
0
}
76
77
void DLL_CALLCONV
78
0
FreeImage_ConvertLine24To8(BYTE *target, BYTE *source, int width_in_pixels) {
79
0
  for (unsigned cols = 0; cols < (unsigned)width_in_pixels; cols++) {
80
0
    target[cols] = GREY(source[FI_RGBA_RED], source[FI_RGBA_GREEN], source[FI_RGBA_BLUE]);
81
0
    source += 3;
82
0
  }
83
0
}
84
85
void DLL_CALLCONV
86
0
FreeImage_ConvertLine32To8(BYTE *target, BYTE *source, int width_in_pixels) {
87
0
  for (unsigned cols = 0; cols < (unsigned)width_in_pixels; cols++) {
88
0
    target[cols] = GREY(source[FI_RGBA_RED], source[FI_RGBA_GREEN], source[FI_RGBA_BLUE]);
89
0
    source += 4;
90
0
  }
91
0
}
92
93
// ----------------------------------------------------------
94
//   smart convert X to 8 bits
95
// ----------------------------------------------------------
96
97
FIBITMAP * DLL_CALLCONV
98
0
FreeImage_ConvertTo8Bits(FIBITMAP *dib) {
99
0
  if (!FreeImage_HasPixels(dib)) {
100
0
    return NULL;
101
0
  }
102
103
0
  const FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib);
104
0
  if (image_type != FIT_BITMAP && image_type != FIT_UINT16) {
105
0
    return NULL;
106
0
  }
107
108
0
  const unsigned bpp = FreeImage_GetBPP(dib);
109
110
0
  if (bpp != 8) {
111
112
0
    const unsigned width = FreeImage_GetWidth(dib);
113
0
    const unsigned height = FreeImage_GetHeight(dib);
114
115
    // Allocate a destination image
116
0
    FIBITMAP *new_dib = FreeImage_Allocate(width, height, 8);
117
0
    if (new_dib == NULL) {
118
0
      return NULL;
119
0
    }
120
121
    // Copy metadata from src to dst
122
0
    FreeImage_CloneMetadata(new_dib, dib);
123
124
    // Palette of destination image has already been initialized
125
0
    RGBQUAD *new_pal = FreeImage_GetPalette(new_dib);
126
127
0
    const FREE_IMAGE_COLOR_TYPE color_type = FreeImage_GetColorType(dib);
128
129
0
    if (image_type == FIT_BITMAP) {
130
131
0
      switch(bpp) {
132
0
        case 1:
133
0
        {
134
0
          if (color_type == FIC_PALETTE) {
135
            // Copy the palette
136
0
            RGBQUAD *old_pal = FreeImage_GetPalette(dib);
137
0
            new_pal[0] = old_pal[0];
138
0
            new_pal[255] = old_pal[1];
139
140
0
          } else if (color_type == FIC_MINISWHITE) {
141
            // Create a reverse grayscale palette
142
0
            CREATE_GREYSCALE_PALETTE_REVERSE(new_pal, 256);
143
0
          }
144
145
          // Expand and copy the bitmap data
146
0
          for (unsigned rows = 0; rows < height; rows++) {
147
0
            FreeImage_ConvertLine1To8(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width);
148
0
          }
149
0
          return new_dib;
150
0
        }
151
152
0
        case 4 :
153
0
        {
154
0
          if (color_type == FIC_PALETTE) {
155
            // Copy the palette
156
0
            memcpy(new_pal, FreeImage_GetPalette(dib), 16 * sizeof(RGBQUAD));
157
0
          }
158
159
          // Expand and copy the bitmap data
160
0
          for (unsigned rows = 0; rows < height; rows++) {
161
0
            FreeImage_ConvertLine4To8(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width);         
162
0
          }
163
0
          return new_dib;
164
0
        }
165
166
0
        case 16 :
167
0
        {
168
          // Expand and copy the bitmap data
169
0
          if (IS_FORMAT_RGB565(dib)) {
170
0
            for (unsigned rows = 0; rows < height; rows++) {
171
0
              FreeImage_ConvertLine16To8_565(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width);
172
0
            }
173
0
          } else {
174
0
            for (unsigned rows = 0; rows < height; rows++) {
175
0
              FreeImage_ConvertLine16To8_555(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width);
176
0
            }
177
0
          }
178
0
          return new_dib;
179
0
        }
180
181
0
        case 24 :
182
0
        {
183
          // Expand and copy the bitmap data
184
0
          for (unsigned rows = 0; rows < height; rows++) {
185
0
            FreeImage_ConvertLine24To8(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width);          
186
0
          }
187
0
          return new_dib;
188
0
        }
189
190
0
        case 32 :
191
0
        {
192
          // Expand and copy the bitmap data
193
0
          for (unsigned rows = 0; rows < height; rows++) {
194
0
            FreeImage_ConvertLine32To8(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width);
195
0
          }
196
0
          return new_dib;
197
0
        }
198
0
      }
199
200
0
    } else if (image_type == FIT_UINT16) {
201
202
0
      const unsigned src_pitch = FreeImage_GetPitch(dib);
203
0
      const unsigned dst_pitch = FreeImage_GetPitch(new_dib);
204
0
      const BYTE *src_bits = FreeImage_GetBits(dib);
205
0
      BYTE *dst_bits = FreeImage_GetBits(new_dib);
206
207
0
      for (unsigned rows = 0; rows < height; rows++) {
208
0
        const WORD *const src_pixel = (WORD*)src_bits;
209
0
        BYTE *dst_pixel = (BYTE*)dst_bits;
210
0
        for(unsigned cols = 0; cols < width; cols++) {
211
0
          dst_pixel[cols] = (BYTE)(src_pixel[cols] >> 8);
212
0
        }
213
0
        src_bits += src_pitch;
214
0
        dst_bits += dst_pitch;
215
0
      }
216
0
      return new_dib;
217
0
    } 
218
219
0
  } // bpp != 8
220
221
0
  return FreeImage_Clone(dib);
222
0
}
223
224
FIBITMAP * DLL_CALLCONV
225
0
FreeImage_ConvertToGreyscale(FIBITMAP *dib) {
226
0
  if (!FreeImage_HasPixels(dib)) {
227
0
    return NULL;
228
0
  }
229
230
0
  const FREE_IMAGE_COLOR_TYPE color_type = FreeImage_GetColorType(dib);
231
232
0
  if (color_type == FIC_PALETTE || color_type == FIC_MINISWHITE) {
233
234
0
    const unsigned bpp = FreeImage_GetBPP(dib);
235
0
    const unsigned width  = FreeImage_GetWidth(dib);
236
0
    const unsigned height = FreeImage_GetHeight(dib);
237
238
0
    FIBITMAP *new_dib = FreeImage_Allocate(width, height, 8);
239
0
    if (new_dib == NULL) {
240
0
      return NULL;
241
0
    }
242
243
    // Copy metadata from src to dst
244
0
    FreeImage_CloneMetadata(new_dib, dib);
245
246
    // Create a greyscale palette
247
0
    BYTE grey_pal[256];
248
0
    const RGBQUAD *pal = FreeImage_GetPalette(dib);
249
0
    const unsigned size = CalculateUsedPaletteEntries(bpp);
250
0
    for (unsigned i = 0; i < size; i++) {
251
0
      grey_pal[i] = GREY(pal->rgbRed, pal->rgbGreen, pal->rgbBlue);
252
0
      pal++;
253
0
    }
254
255
0
    const BYTE *src_bits = FreeImage_GetBits(dib);
256
0
    BYTE *dst_bits = FreeImage_GetBits(new_dib);
257
258
0
    const unsigned src_pitch = FreeImage_GetPitch(dib);
259
0
    const unsigned dst_pitch = FreeImage_GetPitch(new_dib);
260
261
0
    switch(bpp) {
262
0
      case 1:
263
0
      {
264
0
        for (unsigned y = 0; y < height; y++) {
265
0
          for (unsigned x = 0; x < width; x++) {
266
0
            const unsigned pixel = (src_bits[x >> 3] & (0x80 >> (x & 0x07))) != 0;
267
0
            dst_bits[x] = grey_pal[pixel];
268
0
          }
269
0
          src_bits += src_pitch;
270
0
          dst_bits += dst_pitch;
271
0
        }
272
0
      }
273
0
      break;
274
275
0
      case 4:
276
0
      {
277
0
        for (unsigned y = 0; y < height; y++) {
278
0
          for (unsigned x = 0; x < width; x++) {
279
0
            const unsigned pixel = x & 0x01 ? src_bits[x >> 1] & 0x0F : src_bits[x >> 1] >> 4;
280
0
            dst_bits[x] = grey_pal[pixel];
281
0
          }
282
0
          src_bits += src_pitch;
283
0
          dst_bits += dst_pitch;
284
0
        }
285
0
      }
286
0
      break;
287
288
0
      case 8:
289
0
      {
290
0
        for (unsigned y = 0; y < height; y++) {
291
0
          for (unsigned x = 0; x < width; x++) {
292
0
            dst_bits[x] = grey_pal[src_bits[x]];
293
0
          }
294
0
          src_bits += src_pitch;
295
0
          dst_bits += dst_pitch;
296
0
        }
297
0
      }
298
0
      break;
299
0
    }
300
0
    return new_dib;
301
0
  } 
302
  
303
  // Convert the bitmap to 8-bit greyscale
304
0
  return FreeImage_ConvertTo8Bits(dib);
305
0
}