PageRenderTime 44ms CodeModel.GetById 17ms app.highlight 24ms RepoModel.GetById 1ms app.codeStats 0ms

/src/FreeImage/Source/FreeImage/Conversion8.cpp

https://bitbucket.org/cabalistic/ogredeps/
C++ | 327 lines | 210 code | 73 blank | 44 comment | 60 complexity | 479f0ff8553b04b0735ec09ecf5160ee MD5 | raw file
  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//
 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#include "FreeImage.h"
 26#include "Utilities.h"
 27
 28// ----------------------------------------------------------
 29//  internal conversions X to 8 bits
 30// ----------------------------------------------------------
 31
 32void DLL_CALLCONV
 33FreeImage_ConvertLine1To8(BYTE *target, BYTE *source, int width_in_pixels) {
 34	for (int cols = 0; cols < width_in_pixels; cols++)
 35		target[cols] = (source[cols >> 3] & (0x80 >> (cols & 0x07))) != 0 ? 255 : 0;	
 36}
 37
 38void DLL_CALLCONV
 39FreeImage_ConvertLine4To8(BYTE *target, BYTE *source, int width_in_pixels) {
 40	int count_new = 0;
 41	int count_org = 0;
 42	BOOL hinibble = TRUE;
 43
 44	while (count_new < width_in_pixels) {
 45		if (hinibble) {
 46			target[count_new] = (source[count_org] & 0xF0) >> 4;
 47		} else {
 48			target[count_new] = (source[count_org] & 0x0F);
 49
 50			count_org++;
 51		}
 52
 53		hinibble = !hinibble;
 54
 55		count_new++;
 56	}
 57}
 58
 59void DLL_CALLCONV
 60FreeImage_ConvertLine16To8_555(BYTE *target, BYTE *source, int width_in_pixels) {
 61	WORD *bits = (WORD *)source;
 62
 63	for (int cols = 0; cols < width_in_pixels; cols++) {
 64		target[cols] = GREY((((bits[cols] & FI16_555_RED_MASK) >> FI16_555_RED_SHIFT) * 0xFF) / 0x1F,
 65			                (((bits[cols] & FI16_555_GREEN_MASK) >> FI16_555_GREEN_SHIFT) * 0xFF) / 0x1F,
 66							(((bits[cols] & FI16_555_BLUE_MASK) >> FI16_555_BLUE_SHIFT) * 0xFF) / 0x1F);
 67	}
 68}
 69
 70void DLL_CALLCONV
 71FreeImage_ConvertLine16To8_565(BYTE *target, BYTE *source, int width_in_pixels) {
 72	WORD *bits = (WORD *)source;
 73
 74	for (int cols = 0; cols < width_in_pixels; cols++)
 75		target[cols] = GREY((((bits[cols] & FI16_565_RED_MASK) >> FI16_565_RED_SHIFT) * 0xFF) / 0x1F,
 76			        (((bits[cols] & FI16_565_GREEN_MASK) >> FI16_565_GREEN_SHIFT) * 0xFF) / 0x3F,
 77					(((bits[cols] & FI16_565_BLUE_MASK) >> FI16_565_BLUE_SHIFT) * 0xFF) / 0x1F);	
 78}
 79
 80void DLL_CALLCONV
 81FreeImage_ConvertLine24To8(BYTE *target, BYTE *source, int width_in_pixels) {
 82	for (int cols = 0; cols < width_in_pixels; cols++) {
 83		target[cols] = GREY(source[FI_RGBA_RED], source[FI_RGBA_GREEN], source[FI_RGBA_BLUE]);
 84
 85		source += 3;
 86	}
 87}
 88
 89void DLL_CALLCONV
 90FreeImage_ConvertLine32To8(BYTE *target, BYTE *source, int width_in_pixels) {
 91	for (int cols = 0; cols < width_in_pixels; cols++) {
 92		target[cols] = GREY(source[FI_RGBA_RED], source[FI_RGBA_GREEN], source[FI_RGBA_BLUE]);
 93
 94		source += 4;
 95	}
 96}
 97
 98// ----------------------------------------------------------
 99//   smart convert X to 8 bits
100// ----------------------------------------------------------
101
102FIBITMAP * DLL_CALLCONV
103FreeImage_ConvertTo8Bits(FIBITMAP *dib) {
104	if(!FreeImage_HasPixels(dib)) return NULL;
105
106	const int bpp = FreeImage_GetBPP(dib);
107
108	const FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib);
109	if((image_type != FIT_BITMAP) && (image_type != FIT_UINT16)) {
110		return NULL;
111	}
112
113	if(bpp != 8) {
114		const int width  = FreeImage_GetWidth(dib);
115		const int height = FreeImage_GetHeight(dib);
116		FIBITMAP *new_dib = FreeImage_Allocate(width, height, 8);
117
118		if(new_dib == NULL) {
119			return NULL;
120		}
121
122		// copy metadata from src to dst
123		FreeImage_CloneMetadata(new_dib, dib);
124
125		// Build a greyscale palette (*always* needed for image processing)
126
127		RGBQUAD *new_pal = FreeImage_GetPalette(new_dib);
128
129		for(int i = 0; i < 256; i++) {
130			new_pal[i].rgbRed	= (BYTE)i;
131			new_pal[i].rgbGreen = (BYTE)i;
132			new_pal[i].rgbBlue	= (BYTE)i;
133		}
134
135		if(image_type == FIT_BITMAP) {
136
137			switch(bpp) {
138				case 1:
139				{
140					if(FreeImage_GetColorType(dib) == FIC_PALETTE) {
141
142						// Copy the palette
143
144						RGBQUAD *old_pal = FreeImage_GetPalette(dib);
145						memcpy(&new_pal[0], &old_pal[0], sizeof(RGBQUAD));
146						memcpy(&new_pal[255], &old_pal[1], sizeof(RGBQUAD));
147
148					}
149					else if(FreeImage_GetColorType(dib) == FIC_MINISWHITE) {
150						
151						// Reverse the grayscale palette
152
153						for(int i = 0; i < 256; i++) {
154							new_pal[i].rgbRed = new_pal[i].rgbGreen = new_pal[i].rgbBlue = (BYTE)(255 - i);
155						}
156					}
157
158
159					// Expand and copy the bitmap data
160
161					for (int rows = 0; rows < height; rows++) {
162						FreeImage_ConvertLine1To8(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width);
163					}
164					return new_dib;
165				}
166
167				case 4 :
168				{
169					if(FreeImage_GetColorType(dib) == FIC_PALETTE) {
170
171						// Copy the palette
172
173						RGBQUAD *old_pal = FreeImage_GetPalette(dib);
174
175						for (int i = 0; i < 16; i++) {
176							new_pal[i].rgbRed	= old_pal[i].rgbRed;
177							new_pal[i].rgbGreen = old_pal[i].rgbGreen;
178							new_pal[i].rgbBlue	= old_pal[i].rgbBlue;
179						}
180					}
181
182					// Expand and copy the bitmap data
183
184					for (int rows = 0; rows < height; rows++) {
185						FreeImage_ConvertLine4To8(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width);					
186					}
187					return new_dib;
188				}
189
190				case 16 :
191				{
192					// Expand and copy the bitmap data
193
194					for (int rows = 0; rows < height; rows++) {
195						if ((FreeImage_GetRedMask(dib) == FI16_565_RED_MASK) && (FreeImage_GetGreenMask(dib) == FI16_565_GREEN_MASK) && (FreeImage_GetBlueMask(dib) == FI16_565_BLUE_MASK)) {
196							FreeImage_ConvertLine16To8_565(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width);
197						} else {
198							FreeImage_ConvertLine16To8_555(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width);
199						}
200					}
201					
202					return new_dib;
203				}
204
205				case 24 :
206				{
207					// Expand and copy the bitmap data
208
209					for (int rows = 0; rows < height; rows++) {
210						FreeImage_ConvertLine24To8(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width);					
211					}
212					return new_dib;
213				}
214
215				case 32 :
216				{
217					// Expand and copy the bitmap data
218
219					for (int rows = 0; rows < height; rows++) {
220						FreeImage_ConvertLine32To8(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width);
221					}
222					return new_dib;
223				}
224			}
225
226		} else if(image_type == FIT_UINT16) {
227
228			const unsigned src_pitch = FreeImage_GetPitch(dib);
229			const unsigned dst_pitch = FreeImage_GetPitch(new_dib);
230			const BYTE *src_bits = FreeImage_GetBits(dib);
231			BYTE *dst_bits = FreeImage_GetBits(new_dib);
232			for (int rows = 0; rows < height; rows++) {
233				const WORD *src_pixel = (WORD*)src_bits;
234				BYTE *dst_pixel = (BYTE*)dst_bits;
235				for(int cols = 0; cols < width; cols++) {
236					dst_pixel[cols] = (BYTE)(src_pixel[cols] >> 8);
237				}
238				src_bits += src_pitch;
239				dst_bits += dst_pitch;
240			}
241
242			return new_dib;
243
244		} 
245
246	} // bpp != 8
247
248	return FreeImage_Clone(dib);
249}
250
251FIBITMAP * DLL_CALLCONV
252FreeImage_ConvertToGreyscale(FIBITMAP *dib) {
253	if(!FreeImage_HasPixels(dib)) return NULL;
254
255	const FREE_IMAGE_COLOR_TYPE color_type = FreeImage_GetColorType(dib);
256	const int bpp = FreeImage_GetBPP(dib);
257
258	if((color_type == FIC_PALETTE) || (color_type == FIC_MINISWHITE)) {
259		const int width  = FreeImage_GetWidth(dib);
260		const int height = FreeImage_GetHeight(dib);
261		FIBITMAP *new_dib = FreeImage_Allocate(width, height, 8);
262
263		if(new_dib == NULL) {
264			return NULL;
265		}
266
267		// copy metadata from src to dst
268		FreeImage_CloneMetadata(new_dib, dib);
269
270		// Build a greyscale palette
271
272		RGBQUAD *new_pal = FreeImage_GetPalette(new_dib);
273
274		for(int i = 0; i < 256; i++) {
275			new_pal[i].rgbRed	= (BYTE)i;
276			new_pal[i].rgbGreen = (BYTE)i;
277			new_pal[i].rgbBlue	= (BYTE)i;
278		}
279
280		// allocate a 24-bit buffer
281
282		BYTE *buffer = (BYTE*)malloc( CalculatePitch(CalculateLine(width, 24)) * sizeof(BYTE) );
283		if(NULL == buffer) {
284			FreeImage_Unload(new_dib);
285			return NULL;
286		}
287
288		// Convert the palette to 24-bit, then to 8-bit
289
290		switch(bpp) {
291			case 1:
292			{
293				for (int rows = 0; rows < height; rows++) {
294					FreeImage_ConvertLine1To24(buffer, FreeImage_GetScanLine(dib, rows), width, FreeImage_GetPalette(dib));
295					FreeImage_ConvertLine24To8(FreeImage_GetScanLine(new_dib, rows), buffer, width);
296				}
297			}
298			break;
299
300			case 4:
301			{
302				for (int rows = 0; rows < height; rows++) {
303					FreeImage_ConvertLine4To24(buffer, FreeImage_GetScanLine(dib, rows), width, FreeImage_GetPalette(dib));
304					FreeImage_ConvertLine24To8(FreeImage_GetScanLine(new_dib, rows), buffer, width);
305				}
306			}
307			break;
308
309			case 8:
310			{
311				for (int rows = 0; rows < height; rows++) {
312					FreeImage_ConvertLine8To24(buffer, FreeImage_GetScanLine(dib, rows), width, FreeImage_GetPalette(dib));
313					FreeImage_ConvertLine24To8(FreeImage_GetScanLine(new_dib, rows), buffer, width);
314				}
315			}
316			break;
317
318		}
319		free(buffer);
320
321		return new_dib;
322
323	} 
324	
325	// Convert the bitmap to 8-bit greyscale
326	return FreeImage_ConvertTo8Bits(dib);
327}