1 // ==========================================================
2 // Pixel access 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 // - Riley McNiff (rmcniff@marexgroup.com)
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 
30 BYTE * DLL_CALLCONV
FreeImage_GetScanLine(FIBITMAP * dib,int scanline)31 FreeImage_GetScanLine(FIBITMAP *dib, int scanline) {
32 	if(!FreeImage_HasPixels(dib)) {
33 		return NULL;
34 	}
35 	return CalculateScanLine(FreeImage_GetBits(dib), FreeImage_GetPitch(dib), scanline);
36 }
37 
38 BOOL DLL_CALLCONV
FreeImage_GetPixelIndex(FIBITMAP * dib,unsigned x,unsigned y,BYTE * value)39 FreeImage_GetPixelIndex(FIBITMAP *dib, unsigned x, unsigned y, BYTE *value) {
40 	BYTE shift;
41 
42 	if(!FreeImage_HasPixels(dib) || (FreeImage_GetImageType(dib) != FIT_BITMAP))
43 		return FALSE;
44 
45 	if((x < FreeImage_GetWidth(dib)) && (y < FreeImage_GetHeight(dib))) {
46 		BYTE *bits = FreeImage_GetScanLine(dib, y);
47 
48 		switch(FreeImage_GetBPP(dib)) {
49 			case 1:
50 				*value = (bits[x >> 3] & (0x80 >> (x & 0x07))) != 0;
51 				break;
52 			case 4:
53 				shift = (BYTE)((1 - x % 2) << 2);
54 				*value = (bits[x >> 1] & (0x0F << shift)) >> shift;
55 				break;
56 			case 8:
57 				*value = bits[x];
58 				break;
59 			default:
60 				return FALSE;
61 		}
62 
63 		return TRUE;
64 	}
65 
66 	return FALSE;
67 }
68 
69 BOOL DLL_CALLCONV
FreeImage_GetPixelColor(FIBITMAP * dib,unsigned x,unsigned y,RGBQUAD * value)70 FreeImage_GetPixelColor(FIBITMAP *dib, unsigned x, unsigned y, RGBQUAD *value) {
71 	if(!FreeImage_HasPixels(dib) || (FreeImage_GetImageType(dib) != FIT_BITMAP))
72 		return FALSE;
73 
74 	if((x < FreeImage_GetWidth(dib)) && (y < FreeImage_GetHeight(dib))) {
75 		BYTE *bits = FreeImage_GetScanLine(dib, y);
76 
77 		switch(FreeImage_GetBPP(dib)) {
78 			case 16:
79 			{
80 				bits += 2*x;
81 				WORD *pixel = (WORD *)bits;
82 				if((FreeImage_GetRedMask(dib) == FI16_565_RED_MASK) && (FreeImage_GetGreenMask(dib) == FI16_565_GREEN_MASK) && (FreeImage_GetBlueMask(dib) == FI16_565_BLUE_MASK)) {
83 					value->rgbBlue		= (BYTE)((((*pixel & FI16_565_BLUE_MASK) >> FI16_565_BLUE_SHIFT) * 0xFF) / 0x1F);
84 					value->rgbGreen		= (BYTE)((((*pixel & FI16_565_GREEN_MASK) >> FI16_565_GREEN_SHIFT) * 0xFF) / 0x3F);
85 					value->rgbRed		= (BYTE)((((*pixel & FI16_565_RED_MASK) >> FI16_565_RED_SHIFT) * 0xFF) / 0x1F);
86 					value->rgbReserved	= 0;
87 				} else {
88 					value->rgbBlue		= (BYTE)((((*pixel & FI16_555_BLUE_MASK) >> FI16_555_BLUE_SHIFT) * 0xFF) / 0x1F);
89 					value->rgbGreen		= (BYTE)((((*pixel & FI16_555_GREEN_MASK) >> FI16_555_GREEN_SHIFT) * 0xFF) / 0x1F);
90 					value->rgbRed		= (BYTE)((((*pixel & FI16_555_RED_MASK) >> FI16_555_RED_SHIFT) * 0xFF) / 0x1F);
91 					value->rgbReserved	= 0;
92 				}
93 				break;
94 			}
95 			case 24:
96 				bits += 3*x;
97 				value->rgbBlue		= bits[FI_RGBA_BLUE];	// B
98 				value->rgbGreen		= bits[FI_RGBA_GREEN];	// G
99 				value->rgbRed		= bits[FI_RGBA_RED];	// R
100 				value->rgbReserved	= 0;
101 				break;
102 			case 32:
103 				bits += 4*x;
104 				value->rgbBlue		= bits[FI_RGBA_BLUE];	// B
105 				value->rgbGreen		= bits[FI_RGBA_GREEN];	// G
106 				value->rgbRed		= bits[FI_RGBA_RED];	// R
107 				value->rgbReserved	= bits[FI_RGBA_ALPHA];	// A
108 				break;
109 			default:
110 				return FALSE;
111 		}
112 
113 		return TRUE;
114 	}
115 
116 	return FALSE;
117 }
118 
119 BOOL DLL_CALLCONV
FreeImage_SetPixelIndex(FIBITMAP * dib,unsigned x,unsigned y,BYTE * value)120 FreeImage_SetPixelIndex(FIBITMAP *dib, unsigned x, unsigned y, BYTE *value) {
121 	BYTE shift;
122 
123 	if(!FreeImage_HasPixels(dib) || (FreeImage_GetImageType(dib) != FIT_BITMAP))
124 		return FALSE;
125 
126 	if((x < FreeImage_GetWidth(dib)) && (y < FreeImage_GetHeight(dib))) {
127 		BYTE *bits = FreeImage_GetScanLine(dib, y);
128 
129 		switch(FreeImage_GetBPP(dib)) {
130 			case 1:
131 				*value ? bits[x >> 3] |= (0x80 >> (x & 0x7)) : bits[x >> 3] &= (0xFF7F >> (x & 0x7));
132 				break;
133 			case 4:
134 				shift = (BYTE)((1 - x % 2) << 2);
135 				bits[x >> 1] &= ~(0x0F << shift);
136 				bits[x >> 1] |= ((*value & 0x0F) << shift);
137 				break;
138 			case 8:
139 				bits[x] = *value;
140 				break;
141 			default:
142 				return FALSE;
143 		}
144 
145 		return TRUE;
146 	}
147 
148 	return FALSE;
149 }
150 
151 BOOL DLL_CALLCONV
FreeImage_SetPixelColor(FIBITMAP * dib,unsigned x,unsigned y,RGBQUAD * value)152 FreeImage_SetPixelColor(FIBITMAP *dib, unsigned x, unsigned y, RGBQUAD *value) {
153 	if(!FreeImage_HasPixels(dib) || (FreeImage_GetImageType(dib) != FIT_BITMAP))
154 		return FALSE;
155 
156 	if((x < FreeImage_GetWidth(dib)) && (y < FreeImage_GetHeight(dib))) {
157 		BYTE *bits = FreeImage_GetScanLine(dib, y);
158 
159 		switch(FreeImage_GetBPP(dib)) {
160 			case 16:
161 			{
162 				bits += 2*x;
163 				WORD *pixel = (WORD *)bits;
164 				if((FreeImage_GetRedMask(dib) == FI16_565_RED_MASK) && (FreeImage_GetGreenMask(dib) == FI16_565_GREEN_MASK) && (FreeImage_GetBlueMask(dib) == FI16_565_BLUE_MASK)) {
165 					*pixel = ((value->rgbBlue >> 3) << FI16_565_BLUE_SHIFT) |
166 						((value->rgbGreen >> 2) << FI16_565_GREEN_SHIFT) |
167 						((value->rgbRed >> 3) << FI16_565_RED_SHIFT);
168 				} else {
169 					*pixel = ((value->rgbBlue >> 3) << FI16_555_BLUE_SHIFT) |
170 						((value->rgbGreen >> 3) << FI16_555_GREEN_SHIFT) |
171 						((value->rgbRed >> 3) << FI16_555_RED_SHIFT);
172 				}
173 				break;
174 			}
175 			case 24:
176 				bits += 3*x;
177 				bits[FI_RGBA_BLUE]	= value->rgbBlue;	// B
178 				bits[FI_RGBA_GREEN] = value->rgbGreen;	// G
179 				bits[FI_RGBA_RED]	= value->rgbRed;	// R
180 				break;
181 			case 32:
182 				bits += 4*x;
183 				bits[FI_RGBA_BLUE]	= value->rgbBlue;		// B
184 				bits[FI_RGBA_GREEN] = value->rgbGreen;		// G
185 				bits[FI_RGBA_RED]	= value->rgbRed;		// R
186 				bits[FI_RGBA_ALPHA] = value->rgbReserved;	// A
187 				break;
188 			default:
189 				return FALSE;
190 		}
191 
192 		return TRUE;
193 	}
194 
195 	return FALSE;
196 }
197 
198