Subversion Repositories gelsvn

Rev

Rev 369 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 369 Rev 373
1
/*
1
/*
2
    Jonathan Dummer
2
    Jonathan Dummer
3

3

4
    image helper functions
4
    image helper functions
5

5

6
    MIT license
6
    MIT license
7
*/
7
*/
8
 
8
 
9
#include "image_helper.h"
9
#include "image_helper.h"
10
#include <stdlib.h>
10
#include <stdlib.h>
11
#include <math.h>
11
#include <math.h>
12
 
12
 
13
/*	Upscaling the image uses simple bilinear interpolation	*/
13
/*	Upscaling the image uses simple bilinear interpolation	*/
14
int
14
int
15
	up_scale_image
15
	up_scale_image
16
	(
16
	(
17
		const unsigned char* const orig,
17
		const unsigned char* const orig,
18
		int width, int height, int channels,
18
		int width, int height, int channels,
19
		unsigned char* resampled,
19
		unsigned char* resampled,
20
		int resampled_width, int resampled_height
20
		int resampled_width, int resampled_height
21
	)
21
	)
22
{
22
{
23
	float dx, dy;
23
	float dx, dy;
24
	int x, y, c;
24
	int x, y, c;
25
 
25
 
26
    /* error(s) check	*/
26
    /* error(s) check	*/
27
    if ( 	(width < 1) || (height < 1) ||
27
    if ( 	(width < 1) || (height < 1) ||
28
            (resampled_width < 2) || (resampled_height < 2) ||
28
            (resampled_width < 2) || (resampled_height < 2) ||
29
            (channels < 1) ||
29
            (channels < 1) ||
30
            (NULL == orig) || (NULL == resampled) )
30
            (NULL == orig) || (NULL == resampled) )
31
    {
31
    {
32
        /*	signify badness	*/
32
        /*	signify badness	*/
33
        return 0;
33
        return 0;
34
    }
34
    }
35
    /*
35
    /*
36
		for each given pixel in the new map, find the exact location
36
		for each given pixel in the new map, find the exact location
37
		from the original map which would contribute to this guy
37
		from the original map which would contribute to this guy
38
	*/
38
	*/
39
    dx = (width - 1.0f) / (resampled_width - 1.0f);
39
    dx = (width - 1.0f) / (resampled_width - 1.0f);
40
    dy = (height - 1.0f) / (resampled_height - 1.0f);
40
    dy = (height - 1.0f) / (resampled_height - 1.0f);
41
    for ( y = 0; y < resampled_height; ++y )
41
    for ( y = 0; y < resampled_height; ++y )
42
    {
42
    {
43
    	/* find the base y index and fractional offset from that	*/
43
    	/* find the base y index and fractional offset from that	*/
44
    	float sampley = y * dy;
44
    	float sampley = y * dy;
45
    	int inty = (int)sampley;
45
    	int inty = (int)sampley;
46
    	/*	if( inty < 0 ) { inty = 0; } else	*/
46
    	/*	if( inty < 0 ) { inty = 0; } else	*/
47
		if( inty > height - 2 ) { inty = height - 2; }
47
		if( inty > height - 2 ) { inty = height - 2; }
48
		sampley -= inty;
48
		sampley -= inty;
49
        for ( x = 0; x < resampled_width; ++x )
49
        for ( x = 0; x < resampled_width; ++x )
50
        {
50
        {
51
			float samplex = x * dx;
51
			float samplex = x * dx;
52
			int intx = (int)samplex;
52
			int intx = (int)samplex;
53
			int base_index;
53
			int base_index;
54
			/* find the base x index and fractional offset from that	*/
54
			/* find the base x index and fractional offset from that	*/
55
			/*	if( intx < 0 ) { intx = 0; } else	*/
55
			/*	if( intx < 0 ) { intx = 0; } else	*/
56
			if( intx > width - 2 ) { intx = width - 2; }
56
			if( intx > width - 2 ) { intx = width - 2; }
57
			samplex -= intx;
57
			samplex -= intx;
58
			/*	base index into the original image	*/
58
			/*	base index into the original image	*/
59
			base_index = (inty * width + intx) * channels;
59
			base_index = (inty * width + intx) * channels;
60
            for ( c = 0; c < channels; ++c )
60
            for ( c = 0; c < channels; ++c )
61
            {
61
            {
62
            	/*	do the sampling	*/
62
            	/*	do the sampling	*/
63
				float value = 0.5f;
63
				float value = 0.5f;
64
				value += orig[base_index]
64
				value += orig[base_index]
65
							*(1.0f-samplex)*(1.0f-sampley);
65
							*(1.0f-samplex)*(1.0f-sampley);
66
				value += orig[base_index+channels]
66
				value += orig[base_index+channels]
67
							*(samplex)*(1.0f-sampley);
67
							*(samplex)*(1.0f-sampley);
68
				value += orig[base_index+width*channels]
68
				value += orig[base_index+width*channels]
69
							*(1.0f-samplex)*(sampley);
69
							*(1.0f-samplex)*(sampley);
70
				value += orig[base_index+width*channels+channels]
70
				value += orig[base_index+width*channels+channels]
71
							*(samplex)*(sampley);
71
							*(samplex)*(sampley);
72
				/*	move to the next channel	*/
72
				/*	move to the next channel	*/
73
				++base_index;
73
				++base_index;
74
            	/*	save the new value	*/
74
            	/*	save the new value	*/
75
            	resampled[y*resampled_width*channels+x*channels+c] =
75
            	resampled[y*resampled_width*channels+x*channels+c] =
76
						(unsigned char)(value);
76
						(unsigned char)(value);
77
            }
77
            }
78
        }
78
        }
79
    }
79
    }
80
    /*	done	*/
80
    /*	done	*/
81
    return 1;
81
    return 1;
82
}
82
}
83
 
83
 
84
int
84
int
85
	mipmap_image
85
	mipmap_image
86
	(
86
	(
87
		const unsigned char* const orig,
87
		const unsigned char* const orig,
88
		int width, int height, int channels,
88
		int width, int height, int channels,
89
		unsigned char* resampled,
89
		unsigned char* resampled,
90
		int block_size_x, int block_size_y
90
		int block_size_x, int block_size_y
91
	)
91
	)
92
{
92
{
93
	int mip_width, mip_height;
93
	int mip_width, mip_height;
94
	int i, j, c;
94
	int i, j, c;
95
 
95
 
96
	/*	error check	*/
96
	/*	error check	*/
97
	if( (width < 1) || (height < 1) ||
97
	if( (width < 1) || (height < 1) ||
98
		(channels < 1) || (orig == NULL) ||
98
		(channels < 1) || (orig == NULL) ||
99
		(resampled == NULL) ||
99
		(resampled == NULL) ||
100
		(block_size_x < 1) || (block_size_y < 1) )
100
		(block_size_x < 1) || (block_size_y < 1) )
101
	{
101
	{
102
		/*	nothing to do	*/
102
		/*	nothing to do	*/
103
		return 0;
103
		return 0;
104
	}
104
	}
105
	mip_width = width / block_size_x;
105
	mip_width = width / block_size_x;
106
	mip_height = height / block_size_y;
106
	mip_height = height / block_size_y;
107
	if( mip_width < 1 )
107
	if( mip_width < 1 )
108
	{
108
	{
109
		mip_width = 1;
109
		mip_width = 1;
110
	}
110
	}
111
	if( mip_height < 1 )
111
	if( mip_height < 1 )
112
	{
112
	{
113
		mip_height = 1;
113
		mip_height = 1;
114
	}
114
	}
115
	for( j = 0; j < mip_height; ++j )
115
	for( j = 0; j < mip_height; ++j )
116
	{
116
	{
117
		for( i = 0; i < mip_width; ++i )
117
		for( i = 0; i < mip_width; ++i )
118
		{
118
		{
119
			for( c = 0; c < channels; ++c )
119
			for( c = 0; c < channels; ++c )
120
			{
120
			{
121
				const int index = (j*block_size_y)*width*channels + (i*block_size_x)*channels + c;
121
				const int index = (j*block_size_y)*width*channels + (i*block_size_x)*channels + c;
122
				int sum_value;
122
				int sum_value;
123
				int u,v;
123
				int u,v;
124
				int u_block = block_size_x;
124
				int u_block = block_size_x;
125
				int v_block = block_size_y;
125
				int v_block = block_size_y;
126
				int block_area;
126
				int block_area;
127
				/*	do a bit of checking so we don't over-run the boundaries
127
				/*	do a bit of checking so we don't over-run the boundaries
128
					(necessary for non-square textures!)	*/
128
					(necessary for non-square textures!)	*/
129
				if( block_size_x * (i+1) > width )
129
				if( block_size_x * (i+1) > width )
130
				{
130
				{
131
					u_block = width - i*block_size_y;
131
					u_block = width - i*block_size_y;
132
				}
132
				}
133
				if( block_size_y * (j+1) > height )
133
				if( block_size_y * (j+1) > height )
134
				{
134
				{
135
					v_block = height - j*block_size_y;
135
					v_block = height - j*block_size_y;
136
				}
136
				}
137
				block_area = u_block*v_block;
137
				block_area = u_block*v_block;
138
				/*	for this pixel, see what the average
138
				/*	for this pixel, see what the average
139
					of all the values in the block are.
139
					of all the values in the block are.
140
					note: start the sum at the rounding value, not at 0	*/
140
					note: start the sum at the rounding value, not at 0	*/
141
				sum_value = block_area >> 1;
141
				sum_value = block_area >> 1;
142
				for( v = 0; v < v_block; ++v )
142
				for( v = 0; v < v_block; ++v )
143
				for( u = 0; u < u_block; ++u )
143
				for( u = 0; u < u_block; ++u )
144
				{
144
				{
145
					sum_value += orig[index + v*width*channels + u*channels];
145
					sum_value += orig[index + v*width*channels + u*channels];
146
				}
146
				}
147
				resampled[j*mip_width*channels + i*channels + c] = sum_value / block_area;
147
				resampled[j*mip_width*channels + i*channels + c] = sum_value / block_area;
148
			}
148
			}
149
		}
149
		}
150
	}
150
	}
151
	return 1;
151
	return 1;
152
}
152
}
153
 
153
 
154
int
154
int
155
	scale_image_RGB_to_NTSC_safe
155
	scale_image_RGB_to_NTSC_safe
156
	(
156
	(
157
		unsigned char* orig,
157
		unsigned char* orig,
158
		int width, int height, int channels
158
		int width, int height, int channels
159
	)
159
	)
160
{
160
{
161
	const float scale_lo = 16.0f - 0.499f;
161
	const float scale_lo = 16.0f - 0.499f;
162
	const float scale_hi = 235.0f + 0.499f;
162
	const float scale_hi = 235.0f + 0.499f;
163
	int i, j;
163
	int i, j;
164
	int nc = channels;
164
	int nc = channels;
165
	unsigned char scale_LUT[256];
165
	unsigned char scale_LUT[256];
166
	/*	error check	*/
166
	/*	error check	*/
167
	if( (width < 1) || (height < 1) ||
167
	if( (width < 1) || (height < 1) ||
168
		(channels < 1) || (orig == NULL) )
168
		(channels < 1) || (orig == NULL) )
169
	{
169
	{
170
		/*	nothing to do	*/
170
		/*	nothing to do	*/
171
		return 0;
171
		return 0;
172
	}
172
	}
173
	/*	set up the scaling Look Up Table	*/
173
	/*	set up the scaling Look Up Table	*/
174
	for( i = 0; i < 256; ++i )
174
	for( i = 0; i < 256; ++i )
175
	{
175
	{
176
		scale_LUT[i] = (unsigned char)((scale_hi - scale_lo) * i / 255.0f + scale_lo);
176
		scale_LUT[i] = (unsigned char)((scale_hi - scale_lo) * i / 255.0f + scale_lo);
177
	}
177
	}
178
	/*	for channels = 2 or 4, ignore the alpha component	*/
178
	/*	for channels = 2 or 4, ignore the alpha component	*/
179
	nc -= 1 - (channels & 1);
179
	nc -= 1 - (channels & 1);
180
	/*	OK, go through the image and scale any non-alpha components	*/
180
	/*	OK, go through the image and scale any non-alpha components	*/
181
	for( i = 0; i < width*height*channels; i += channels )
181
	for( i = 0; i < width*height*channels; i += channels )
182
	{
182
	{
183
		for( j = 0; j < nc; ++j )
183
		for( j = 0; j < nc; ++j )
184
		{
184
		{
185
			orig[i+j] = scale_LUT[orig[i+j]];
185
			orig[i+j] = scale_LUT[orig[i+j]];
186
		}
186
		}
187
	}
187
	}
188
	return 1;
188
	return 1;
189
}
189
}
190
 
190
 
191
unsigned char clamp_byte( int x ) { return ( (x) < 0 ? (0) : ( (x) > 255 ? 255 : (x) ) ); }
191
unsigned char clamp_byte( int x ) { return ( (x) < 0 ? (0) : ( (x) > 255 ? 255 : (x) ) ); }
192
 
192
 
193
/*
193
/*
194
	This function takes the RGB components of the image
194
	This function takes the RGB components of the image
195
	and converts them into YCoCg.  3 components will be
195
	and converts them into YCoCg.  3 components will be
196
	re-ordered to CoYCg (for optimum DXT1 compression),
196
	re-ordered to CoYCg (for optimum DXT1 compression),
197
	while 4 components will be ordered CoCgAY (for DXT5
197
	while 4 components will be ordered CoCgAY (for DXT5
198
	compression).
198
	compression).
199
*/
199
*/
200
int
200
int
201
	convert_RGB_to_YCoCg
201
	convert_RGB_to_YCoCg
202
	(
202
	(
203
		unsigned char* orig,
203
		unsigned char* orig,
204
		int width, int height, int channels
204
		int width, int height, int channels
205
	)
205
	)
206
{
206
{
207
	int i;
207
	int i;
208
	/*	error check	*/
208
	/*	error check	*/
209
	if( (width < 1) || (height < 1) ||
209
	if( (width < 1) || (height < 1) ||
210
		(channels < 3) || (channels > 4) ||
210
		(channels < 3) || (channels > 4) ||
211
		(orig == NULL) )
211
		(orig == NULL) )
212
	{
212
	{
213
		/*	nothing to do	*/
213
		/*	nothing to do	*/
214
		return -1;
214
		return -1;
215
	}
215
	}
216
	/*	do the conversion	*/
216
	/*	do the conversion	*/
217
	if( channels == 3 )
217
	if( channels == 3 )
218
	{
218
	{
219
		for( i = 0; i < width*height*3; i += 3 )
219
		for( i = 0; i < width*height*3; i += 3 )
220
		{
220
		{
221
			int r = orig[i+0];
221
			int r = orig[i+0];
222
			int g = (orig[i+1] + 1) >> 1;
222
			int g = (orig[i+1] + 1) >> 1;
223
			int b = orig[i+2];
223
			int b = orig[i+2];
224
			int tmp = (2 + r + b) >> 2;
224
			int tmp = (2 + r + b) >> 2;
225
			/*	Co	*/
225
			/*	Co	*/
226
			orig[i+0] = clamp_byte( 128 + ((r - b + 1) >> 1) );
226
			orig[i+0] = clamp_byte( 128 + ((r - b + 1) >> 1) );
227
			/*	Y	*/
227
			/*	Y	*/
228
			orig[i+1] = clamp_byte( g + tmp );
228
			orig[i+1] = clamp_byte( g + tmp );
229
			/*	Cg	*/
229
			/*	Cg	*/
230
			orig[i+2] = clamp_byte( 128 + g - tmp );
230
			orig[i+2] = clamp_byte( 128 + g - tmp );
231
		}
231
		}
232
	} else
232
	} else
233
	{
233
	{
234
		for( i = 0; i < width*height*4; i += 4 )
234
		for( i = 0; i < width*height*4; i += 4 )
235
		{
235
		{
236
			int r = orig[i+0];
236
			int r = orig[i+0];
237
			int g = (orig[i+1] + 1) >> 1;
237
			int g = (orig[i+1] + 1) >> 1;
238
			int b = orig[i+2];
238
			int b = orig[i+2];
239
			unsigned char a = orig[i+3];
239
			unsigned char a = orig[i+3];
240
			int tmp = (2 + r + b) >> 2;
240
			int tmp = (2 + r + b) >> 2;
241
			/*	Co	*/
241
			/*	Co	*/
242
			orig[i+0] = clamp_byte( 128 + ((r - b + 1) >> 1) );
242
			orig[i+0] = clamp_byte( 128 + ((r - b + 1) >> 1) );
243
			/*	Cg	*/
243
			/*	Cg	*/
244
			orig[i+1] = clamp_byte( 128 + g - tmp );
244
			orig[i+1] = clamp_byte( 128 + g - tmp );
245
			/*	Alpha	*/
245
			/*	Alpha	*/
246
			orig[i+2] = a;
246
			orig[i+2] = a;
247
			/*	Y	*/
247
			/*	Y	*/
248
			orig[i+3] = clamp_byte( g + tmp );
248
			orig[i+3] = clamp_byte( g + tmp );
249
		}
249
		}
250
	}
250
	}
251
	/*	done	*/
251
	/*	done	*/
252
	return 0;
252
	return 0;
253
}
253
}
254
 
254
 
255
/*
255
/*
256
	This function takes the YCoCg components of the image
256
	This function takes the YCoCg components of the image
257
	and converts them into RGB.  See above.
257
	and converts them into RGB.  See above.
258
*/
258
*/
259
int
259
int
260
	convert_YCoCg_to_RGB
260
	convert_YCoCg_to_RGB
261
	(
261
	(
262
		unsigned char* orig,
262
		unsigned char* orig,
263
		int width, int height, int channels
263
		int width, int height, int channels
264
	)
264
	)
265
{
265
{
266
	int i;
266
	int i;
267
	/*	error check	*/
267
	/*	error check	*/
268
	if( (width < 1) || (height < 1) ||
268
	if( (width < 1) || (height < 1) ||
269
		(channels < 3) || (channels > 4) ||
269
		(channels < 3) || (channels > 4) ||
270
		(orig == NULL) )
270
		(orig == NULL) )
271
	{
271
	{
272
		/*	nothing to do	*/
272
		/*	nothing to do	*/
273
		return -1;
273
		return -1;
274
	}
274
	}
275
	/*	do the conversion	*/
275
	/*	do the conversion	*/
276
	if( channels == 3 )
276
	if( channels == 3 )
277
	{
277
	{
278
		for( i = 0; i < width*height*3; i += 3 )
278
		for( i = 0; i < width*height*3; i += 3 )
279
		{
279
		{
280
			int co = orig[i+0] - 128;
280
			int co = orig[i+0] - 128;
281
			int y  = orig[i+1];
281
			int y  = orig[i+1];
282
			int cg = orig[i+2] - 128;
282
			int cg = orig[i+2] - 128;
283
			/*	R	*/
283
			/*	R	*/
284
			orig[i+0] = clamp_byte( y + co - cg );
284
			orig[i+0] = clamp_byte( y + co - cg );
285
			/*	G	*/
285
			/*	G	*/
286
			orig[i+1] = clamp_byte( y + cg );
286
			orig[i+1] = clamp_byte( y + cg );
287
			/*	B	*/
287
			/*	B	*/
288
			orig[i+2] = clamp_byte( y - co - cg );
288
			orig[i+2] = clamp_byte( y - co - cg );
289
		}
289
		}
290
	} else
290
	} else
291
	{
291
	{
292
		for( i = 0; i < width*height*4; i += 4 )
292
		for( i = 0; i < width*height*4; i += 4 )
293
		{
293
		{
294
			int co = orig[i+0] - 128;
294
			int co = orig[i+0] - 128;
295
			int cg = orig[i+1] - 128;
295
			int cg = orig[i+1] - 128;
296
			unsigned char a  = orig[i+2];
296
			unsigned char a  = orig[i+2];
297
			int y  = orig[i+3];
297
			int y  = orig[i+3];
298
			/*	R	*/
298
			/*	R	*/
299
			orig[i+0] = clamp_byte( y + co - cg );
299
			orig[i+0] = clamp_byte( y + co - cg );
300
			/*	G	*/
300
			/*	G	*/
301
			orig[i+1] = clamp_byte( y + cg );
301
			orig[i+1] = clamp_byte( y + cg );
302
			/*	B	*/
302
			/*	B	*/
303
			orig[i+2] = clamp_byte( y - co - cg );
303
			orig[i+2] = clamp_byte( y - co - cg );
304
			/*	A	*/
304
			/*	A	*/
305
			orig[i+3] = a;
305
			orig[i+3] = a;
306
		}
306
		}
307
	}
307
	}
308
	/*	done	*/
308
	/*	done	*/
309
	return 0;
309
	return 0;
310
}
310
}
311
 
311
 
312
float
312
float
313
find_max_RGBE
313
find_max_RGBE
314
(
314
(
315
	unsigned char *image,
315
	unsigned char *image,
316
    int width, int height
316
    int width, int height
317
)
317
)
318
{
318
{
319
	float max_val = 0.0f;
319
	float max_val = 0.0f;
320
	unsigned char *img = image;
320
	unsigned char *img = image;
321
	int i, j;
321
	int i, j;
322
	for( i = width * height; i > 0; --i )
322
	for( i = width * height; i > 0; --i )
323
	{
323
	{
324
		/* float scale = powf( 2.0f, img[3] - 128.0f ) / 255.0f; */
324
		/* float scale = powf( 2.0f, img[3] - 128.0f ) / 255.0f; */
325
		float scale = ldexp( 1.0f / 255.0f, (int)(img[3]) - 128 );
325
		float scale = (float)ldexp( 1.0f / 255.0f, (int)(img[3]) - 128 );
326
		for( j = 0; j < 3; ++j )
326
		for( j = 0; j < 3; ++j )
327
		{
327
		{
328
			if( img[j] * scale > max_val )
328
			if( img[j] * scale > max_val )
329
			{
329
			{
330
				max_val = img[j] * scale;
330
				max_val = img[j] * scale;
331
			}
331
			}
332
		}
332
		}
333
		/* next pixel */
333
		/* next pixel */
334
		img += 4;
334
		img += 4;
335
	}
335
	}
336
	return max_val;
336
	return max_val;
337
}
337
}
338
 
338
 
339
int
339
int
340
RGBE_to_RGBdivA
340
RGBE_to_RGBdivA
341
(
341
(
342
    unsigned char *image,
342
    unsigned char *image,
343
    int width, int height,
343
    int width, int height,
344
    int rescale_to_max
344
    int rescale_to_max
345
)
345
)
346
{
346
{
347
	/* local variables */
347
	/* local variables */
348
	int i, iv;
348
	int i, iv;
349
	unsigned char *img = image;
349
	unsigned char *img = image;
350
	float scale = 1.0f;
350
	float scale = 1.0f;
351
	/* error check */
351
	/* error check */
352
	if( (!image) || (width < 1) || (height < 1) )
352
	if( (!image) || (width < 1) || (height < 1) )
353
	{
353
	{
354
		return 0;
354
		return 0;
355
	}
355
	}
356
	/* convert (note: no negative numbers, but 0.0 is possible) */
356
	/* convert (note: no negative numbers, but 0.0 is possible) */
357
	if( rescale_to_max )
357
	if( rescale_to_max )
358
	{
358
	{
359
		scale = 255.0f / find_max_RGBE( image, width, height );
359
		scale = 255.0f / find_max_RGBE( image, width, height );
360
	}
360
	}
361
	for( i = width * height; i > 0; --i )
361
	for( i = width * height; i > 0; --i )
362
	{
362
	{
363
		/* decode this pixel, and find the max */
363
		/* decode this pixel, and find the max */
364
		float r,g,b,e, m;
364
		float r,g,b,e, m;
365
		/* e = scale * powf( 2.0f, img[3] - 128.0f ) / 255.0f; */
365
		/* e = scale * powf( 2.0f, img[3] - 128.0f ) / 255.0f; */
366
		e = scale * ldexp( 1.0f / 255.0f, (int)(img[3]) - 128 );
366
		e = scale * (float)ldexp( 1.0f / 255.0f, (int)(img[3]) - 128 );
367
		r = e * img[0];
367
		r = e * img[0];
368
		g = e * img[1];
368
		g = e * img[1];
369
		b = e * img[2];
369
		b = e * img[2];
370
		m = (r > g) ? r : g;
370
		m = (r > g) ? r : g;
371
		m = (b > m) ? b : m;
371
		m = (b > m) ? b : m;
372
		/* and encode it into RGBdivA */
372
		/* and encode it into RGBdivA */
373
		iv = (m != 0.0f) ? (int)(255.0f / m) : 1.0f;
373
		iv = (m != 0.0f) ? (int)(255.0f / m) : 1;
374
		iv = (iv < 1) ? 1 : iv;
374
		iv = (iv < 1) ? 1 : iv;
375
		img[3] = (iv > 255) ? 255 : iv;
375
		img[3] = (iv > 255) ? 255 : iv;
376
		iv = (int)(img[3] * r + 0.5f);
376
		iv = (int)(img[3] * r + 0.5f);
377
		img[0] = (iv > 255) ? 255 : iv;
377
		img[0] = (iv > 255) ? 255 : iv;
378
		iv = (int)(img[3] * g + 0.5f);
378
		iv = (int)(img[3] * g + 0.5f);
379
		img[1] = (iv > 255) ? 255 : iv;
379
		img[1] = (iv > 255) ? 255 : iv;
380
		iv = (int)(img[3] * b + 0.5f);
380
		iv = (int)(img[3] * b + 0.5f);
381
		img[2] = (iv > 255) ? 255 : iv;
381
		img[2] = (iv > 255) ? 255 : iv;
382
		/* and on to the next pixel */
382
		/* and on to the next pixel */
383
		img += 4;
383
		img += 4;
384
	}
384
	}
385
	return 1;
385
	return 1;
386
}
386
}
387
 
387
 
388
int
388
int
389
RGBE_to_RGBdivA2
389
RGBE_to_RGBdivA2
390
(
390
(
391
    unsigned char *image,
391
    unsigned char *image,
392
    int width, int height,
392
    int width, int height,
393
    int rescale_to_max
393
    int rescale_to_max
394
)
394
)
395
{
395
{
396
	/* local variables */
396
	/* local variables */
397
	int i, iv;
397
	int i, iv;
398
	unsigned char *img = image;
398
	unsigned char *img = image;
399
	float scale = 1.0f;
399
	float scale = 1.0f;
400
	/* error check */
400
	/* error check */
401
	if( (!image) || (width < 1) || (height < 1) )
401
	if( (!image) || (width < 1) || (height < 1) )
402
	{
402
	{
403
		return 0;
403
		return 0;
404
	}
404
	}
405
	/* convert (note: no negative numbers, but 0.0 is possible) */
405
	/* convert (note: no negative numbers, but 0.0 is possible) */
406
	if( rescale_to_max )
406
	if( rescale_to_max )
407
	{
407
	{
408
		scale = 255.0f * 255.0f / find_max_RGBE( image, width, height );
408
		scale = 255.0f * 255.0f / find_max_RGBE( image, width, height );
409
	}
409
	}
410
	for( i = width * height; i > 0; --i )
410
	for( i = width * height; i > 0; --i )
411
	{
411
	{
412
		/* decode this pixel, and find the max */
412
		/* decode this pixel, and find the max */
413
		float r,g,b,e, m;
413
		float r,g,b,e, m;
414
		/* e = scale * powf( 2.0f, img[3] - 128.0f ) / 255.0f; */
414
		/* e = scale * powf( 2.0f, img[3] - 128.0f ) / 255.0f; */
415
		e = scale * ldexp( 1.0f / 255.0f, (int)(img[3]) - 128 );
415
		e = scale * (float)ldexp( 1.0f / 255.0f, (int)(img[3]) - 128 );
416
		r = e * img[0];
416
		r = e * img[0];
417
		g = e * img[1];
417
		g = e * img[1];
418
		b = e * img[2];
418
		b = e * img[2];
419
		m = (r > g) ? r : g;
419
		m = (r > g) ? r : g;
420
		m = (b > m) ? b : m;
420
		m = (b > m) ? b : m;
421
		/* and encode it into RGBdivA */
421
		/* and encode it into RGBdivA */
422
		iv = (m != 0.0f) ? (int)sqrtf( 255.0f * 255.0f / m ) : 1.0f;
422
		iv = (m != 0.0f) ? (int)sqrtf( 255.0f * 255.0f / m ) : 1;
423
		iv = (iv < 1) ? 1 : iv;
423
		iv = (iv < 1) ? 1 : iv;
424
		img[3] = (iv > 255) ? 255 : iv;
424
		img[3] = (iv > 255) ? 255 : iv;
425
		iv = (int)(img[3] * img[3] * r / 255.0f + 0.5f);
425
		iv = (int)(img[3] * img[3] * r / 255.0f + 0.5f);
426
		img[0] = (iv > 255) ? 255 : iv;
426
		img[0] = (iv > 255) ? 255 : iv;
427
		iv = (int)(img[3] * img[3] * g / 255.0f + 0.5f);
427
		iv = (int)(img[3] * img[3] * g / 255.0f + 0.5f);
428
		img[1] = (iv > 255) ? 255 : iv;
428
		img[1] = (iv > 255) ? 255 : iv;
429
		iv = (int)(img[3] * img[3] * b / 255.0f + 0.5f);
429
		iv = (int)(img[3] * img[3] * b / 255.0f + 0.5f);
430
		img[2] = (iv > 255) ? 255 : iv;
430
		img[2] = (iv > 255) ? 255 : iv;
431
		/* and on to the next pixel */
431
		/* and on to the next pixel */
432
		img += 4;
432
		img += 4;
433
	}
433
	}
434
	return 1;
434
	return 1;
435
}
435
}
436
 
436