1 /*---------------------------------------------------------------------*
2 Project: tc library
3 File: TCLayer.cpp
4
5 Copyright 1998-2001 Nintendo. All rights reserved.
6
7 These coded instructions, statements and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 Change History:
14
15 $Log: TCLayer.cpp,v $
16 Revision 1.1 2006/02/17 09:01:53 mitu
17 1st version
18
19
20 4 4/11/01 3:08p John
21 Updated header copyrights and pathname.
22
23 3 8/10/00 6:02p Mikepc
24
25 2 3/17/00 1:19p Mikepc
26 change tc to use indices numbered from 0.
27
28 1 12/03/99 3:45p Ryan
29
30 15 10/08/99 2:45p Mikepc
31 update for tplConv portability: altered data structures, replaced
32 references to 'read tga code' with ' *fileFn, removed redundant
33 functions. Changed some file conversion paths.
34
35 14 10/01/99 12:20p Mikepc
36 Integrated s3.lib code to generate s3 textures 'on the fly' as direct
37 draw surfaces. Removed .dds file reading code. Changed CMP texture
38 generation 'order of operations' to- rgb layer->s3->CMPR format per
39 mipmap LOD.
40
41 13 9/16/99 8:47p Mikepc
42 updated code for auto-palette generation
43
44 12 9/02/99 11:12a Mikepc
45 some code re-organization between files.
46 added code (verify.cpp) to invoke s3tc.exe from within tc program.
47 changed some routines to accommodate the new texture creation path.
48
49 11 8/30/99 5:07p Mikepc
50 changes to dds/cmp processing code to allow odd sized images and images
51 smaller than 8x8 texel.
52
53 10 8/30/99 11:19a Mikepc
54 added a descriptive comment to a necessary but misleading code block in
55 MakeLayer() (line 50). The comment describes the difference between
56 the layer type passed to the function and the one that is finally set
57 from within the function.
58
59 9 8/26/99 4:59p Mikepc
60 renamed file extensions from .c to .cpp.
61 .cpp extension allows addition of namespace protection to remove
62 potential name collisions with tool code. Exceptions are CreateTplFile
63 and QuickConvert. These are extern "C" linked.
64
65 8 8/26/99 11:38a Mikepc
66
67 7 8/26/99 11:03a Mikepc
68 tplCon rewrite for efficient memory usage, batch file processing
69 ability.
70
71 $NoKeywords: $
72
73 -----------------------------------------------------------------------*/
74
75 #include <charPipeline/tc/TCPalTable.h>
76 #include <charPipeline/tc/TCCommon.h>
77
78 #include "TCLayerInternal.h"
79 #include "TCMem.h"
80 #include "TCGXDefs.h"
81
82 /*>*******************************(*)*******************************<*/
83 static void TCSetLayerType ( TCLayer* ly, u32 type );
84 static void TCSetLayerDimensions( TCLayer* ly, u32 width, u32 height );
85 static void TCCopyLayer ( TCLayer* src, TCLayer* dst );
86
87 /*>*******************************(*)*******************************<*/
TCCreateLayer(void)88 TCLayer* TCCreateLayer ( void )
89 {
90 TCLayer* newLayer;
91
92 newLayer = (TCLayer*)TCCalloc( 1, sizeof(TCLayer));
93
94 return newLayer;
95 }
96
97 /*>*******************************(*)*******************************<*/
TCSetLayerAttributes(TCLayer * ly,u32 type,u32 width,u32 height)98 void TCSetLayerAttributes ( TCLayer* ly, u32 type, u32 width, u32 height )
99 {
100 TCAssertMsg( (ly != NULL), "TCSetLayerAttributes: NULL layer ptr\n" );
101 TCAssertMsg( (width <= 1024), "TCSetLayerAttributes: layer width exceeds 1024 texels\n" );
102 TCAssertMsg( (height <= 1024), "TCSetLayerAttributes: layer width exceeds 1024 texels\n" );
103
104 switch( type )
105 {
106 case LY_IMAGE_COLOR_RGB24: // fall through
107 case LY_IMAGE_COLOR_CI16:
108 case LY_IMAGE_ALPHA_A8:
109 case LY_IMAGE_COLOR_CMP:
110
111 TCSetLayerType( ly, type );
112 TCSetLayerDimensions(ly, width, height);
113 break;
114
115 default:
116 TCErrorMsg( "TCSetLayerAttributes: invalid layer type\n" );
117 break;
118 }
119 }
120
121 /*>*******************************(*)*******************************<*/
122 // note: format and dimensions must already be set
123 /*>*******************************(*)*******************************<*/
TCSetLayerBuffer(TCLayer * ly)124 u8* TCSetLayerBuffer ( TCLayer* ly )
125 {
126 u32 size;
127
128
129 TCAssertMsg( (ly != NULL), "TCSetLayerBuffer: NULL layer ptr\n" );
130 TCAssertMsg( (ly->width ), "TCSetLayerBuffer: layer width is not set\n" );
131 TCAssertMsg( (ly->height), "TCSetLayerBuffer: layer height is not set\n" );
132
133 // free buffer if previously allocated
134 TCFree( (void**)(&ly->data) ) ;
135
136 // compute total memory size of base image
137 // and any mipmaps included in this layer
138 size = 0;
139 switch(ly->type)
140 {
141 case LY_IMAGE_COLOR_RGB24:
142 size = ( ly->width * ly->height * 3 );
143 break;
144
145 case LY_IMAGE_COLOR_CI16:
146 size = ( ly->width * ly->height * 2 );
147 break;
148
149 case LY_IMAGE_ALPHA_A8:
150 size = ( ly->width * ly->height );
151 break;
152
153 case LY_IMAGE_COLOR_CMP:
154 // 4 bits per texel
155 // 4x4 texel block minimum
156
157 // ( width x height x 4 bpp / 8bits per byte
158 size = ( ( ly->width * ly->height * 4 ) >> 3 );
159 if( size < 8 )
160 {
161 size = 8;
162 }
163 break;
164
165 default: // in case ly->type wasn't set
166 TCErrorMsg( "TCSetLayerBuffer: unknown layer type\n" );
167 return 0;
168 break;
169 }
170
171 ly->data = (u8*)TCCalloc( 1, size );
172
173 return ly->data;
174 }
175
176 /*>*******************************(*)*******************************<*/
177 // set an individual pixel value based on an x,y location
178 // actual internal data representation depends on the buffer format:
179 // rgb color is stored as rgb triples -> u8[3] = { R, G, B }
180 //
181 // 'ria' is an unsigned short to accomodate 14-bit color index indices
182 //
183 // NOTE: assume (x,y) coordinates start at (0,0)
184 /*>*******************************(*)*******************************<*/
TCSetLayerValue(TCLayer * ly,u32 x,u32 y,u16 ria,u8 g,u8 b)185 void TCSetLayerValue ( TCLayer* ly, u32 x, u32 y, u16 ria, u8 g, u8 b )
186 {
187 u32 offset;
188 u8* basePtr;
189
190
191 TCAssertMsg( (ly != NULL), "TCSetLayerValue: NULL layer ptr\n" );
192 TCAssertMsg( (ly->width ), "TCSetLayerValue: layer width is not set\n" );
193 TCAssertMsg( (ly->data != NULL), "TCSetLayerValue: layer data ptr is not set\n" );
194
195 basePtr = (u8*)(ly->data);
196
197 switch(ly->type)
198 {
199 case LY_IMAGE_COLOR_RGB24:
200
201 offset = ( (y * ly->width) + x ) * 3;
202
203 *( basePtr + offset ) = (u8)ria;
204 *( basePtr + offset + 1 ) = g;
205 *( basePtr + offset + 2 ) = b;
206 break;
207
208 case LY_IMAGE_COLOR_CI16: // this is the only 16-bit format
209
210 offset = ((y * ly->width) + x) * 2; // offset in bytes
211 *(u16*)(basePtr + offset) = ria;
212 break;
213
214 case LY_IMAGE_ALPHA_A8:
215
216 offset = (y * ly->width) + x;
217 *(basePtr + offset) = (u8)ria;
218 break;
219
220 case LY_IMAGE_COLOR_CMP: // cant return a value from compressed texture yet
221 TCErrorMsg( "TCsetLayerValue: can't 'set' a texel value from a CMPR layer\n" );
222 return;
223 break;
224
225 default: // in case format was not set
226 TCErrorMsg( "TCSetLayerValue: unknown layer type\n" );
227 return;
228 break;
229 } // end switch
230
231 }
232
233 /*>*******************************(*)*******************************<*/
234 // retrieve color information from the given layer depending on its
235 // format
236 /*>*******************************(*)*******************************<*/
TCGetLayerValue(TCLayer * ly,u32 x,u32 y,u16 * riaPtr,u8 * gPtr,u8 * bPtr)237 void TCGetLayerValue ( TCLayer* ly, u32 x, u32 y, u16* riaPtr, u8* gPtr, u8* bPtr )
238 {
239 u32 offset;
240 u8* basePtr;
241
242
243 TCAssertMsg( (ly != NULL), "TCGetLayerValue: NULL layer ptr\n" );
244 TCAssertMsg( (ly->width ), "TCGetLayerValue: layer width is not set\n" );
245 TCAssertMsg( (ly->data != NULL), "TCGetLayerValue: layer data ptr is not set\n" );
246 TCAssertMsg( (riaPtr != NULL), "TCGetLayerValue: NULL riaPtr\n" );
247
248 basePtr = (u8*)(ly->data);
249
250 switch(ly->type)
251 {
252 case LY_IMAGE_COLOR_RGB24:
253
254 offset = ( (y * ly->width) + x ) * 3;
255 *riaPtr = (u16)( *( basePtr + offset ) );
256
257 if( gPtr != NULL )
258 {
259 *gPtr = *( basePtr + offset + 1 );
260 }
261 if( bPtr != NULL )
262 {
263 *bPtr = *( basePtr + offset + 2 );
264 }
265 break;
266
267 case LY_IMAGE_COLOR_CI16: // this is the only 16-bit format
268
269 offset = ((y * ly->width) + x) * 2; // offset in bytes
270 *riaPtr = *((u16*)(basePtr + offset));
271 break;
272
273 case LY_IMAGE_ALPHA_A8:
274
275 offset = (y * ly->width) + x;
276 *riaPtr = (u16)(*(basePtr + offset));
277 break;
278
279 case LY_IMAGE_COLOR_CMP: // cant set a compressed pixel yet
280
281 TCErrorMsg( "TCSetLayerValue: can't 'set' a CMPR texel value\n" );
282 return;
283 break;
284
285 default: // in case type wasn't set
286 TCErrorMsg( "TCSetLayerValue: unknown layer type- can't set value\n" );
287 return;
288 break;
289 }
290
291 }
292
293 /*>*******************************(*)*******************************<*/
TCMakeImColorLayer(TCFile * dfPtr,TCLayer * newLy)294 void TCMakeImColorLayer ( TCFile* dfPtr, TCLayer* newLy )
295 {
296 u32 row, col;
297 u16 r;
298 u8 g, b;
299
300
301 TCAssertMsg( (dfPtr != NULL), "TCMakeImColorLayer: NULL TCFile ptr\n" );
302 TCAssertMsg( (newLy != NULL), "TCMakeImColorLayer: NULL layer ptr\n" );
303
304 // copy the layer attributes, but set an independent buffer
305 newLy->type = dfPtr->lyColor->type;
306 newLy->width = dfPtr->lyColor->width;
307 newLy->height = dfPtr->lyColor->height;
308 newLy->data = NULL;
309
310 TCSetLayerBuffer( newLy );
311
312 // copy over the data
313 for( row = 0; row< newLy->height; row++ )
314 {
315 for( col = 0; col < newLy->width; col++ )
316 {
317 TCGetLayerValue(dfPtr->lyColor, col, row, &r, &g, &b);
318 TCSetLayerValue(newLy, col, row, r, g, b);
319 }
320 }
321 }
322
323 /*>*******************************(*)*******************************<*/
TCMakeImAlphaLayer(TCFile * dfPtr,TCLayer * newLy)324 void TCMakeImAlphaLayer( TCFile* dfPtr, TCLayer* newLy )
325 {
326 u32 row, col;
327 u16 a;
328
329
330 TCAssertMsg( (dfPtr != NULL), "TCMakeImAlphaLayer: NULL TCFile ptr\n" );
331 TCAssertMsg( (newLy != NULL), "TCMakeImAlphaLayer: NULL layer ptr\n" );
332
333 // copy the layer attributes, but set an independent buffer
334 newLy->type = dfPtr->lyAlpha->type;
335 newLy->width = dfPtr->lyAlpha->width;
336 newLy->height = dfPtr->lyAlpha->height;
337 newLy->data = NULL;
338
339 TCSetLayerBuffer( newLy );
340
341 // copy over the data
342 for( row = 0; row< newLy->height; row++ )
343 {
344 for( col = 0; col < newLy->width; col++ )
345 {
346 TCGetLayerValue(dfPtr->lyAlpha, col, row, &a, NULL, NULL);
347 TCSetLayerValue(newLy, col, row, a, NULL, NULL);
348 }
349 }
350 }
351
352 /*>*******************************(*)*******************************<*/
353 // convert an image CI layer to an rgb24 layer
354 // leave the image alpha layer as is.
355 /*>*******************************(*)*******************************<*/
TCConvertCI_To_RGB(TCFile * dfPtr,TCImage * imPtr)356 void TCConvertCI_To_RGB ( TCFile* dfPtr, TCImage* imPtr )
357 {
358 TCLayer lyColor;
359 u16 index;
360 u32 row, col;
361 u8 r, g, b;
362
363
364 TCAssertMsg( (dfPtr->palPtr != NULL), "TCConvertCI_To_RGB: TCFile %s has no palette\n", dfPtr->name );
365
366 if( imPtr->lyColor.type != LY_IMAGE_COLOR_CI16 )
367 {
368 TCErrorMsg( "TCConvertCI_To_RGB: image %d color layer type is not color-index\n", imPtr->index );
369 }
370
371 TCSetLayerAttributes( &lyColor, LY_IMAGE_COLOR_RGB24, imPtr->lyColor.width, imPtr->lyColor.height );
372 lyColor.data = NULL;
373 TCSetLayerBuffer( &lyColor );
374
375 // perform color-table lookups
376 for( row = 0; row < imPtr->lyColor.height; row++ )
377 {
378 for( col = 0; col < imPtr->lyColor.width; col++ )
379 {
380 // fetch the index, perform the color look-up, convert to rgb
381 TCGetLayerValue( &imPtr->lyColor, col, row, &index, NULL, NULL );
382
383 // ignore 'a' value; leave image alpha layer as is.
384 TCGetPalTableValue( dfPtr->palPtr, index, &r, &g, &b, NULL );
385
386 TCSetLayerValue( &lyColor, col, row, (u16)r, g, b );
387 }
388 }
389
390 // free the original CI buffer, copy over the new color layer
391 TCFree( (void**)( &imPtr->lyColor.data ) );
392 TCCopyLayer( &lyColor, &imPtr->lyColor );
393
394 }
395
396 /*>*******************************(*)*******************************<*/
TCSetLayerType(TCLayer * ly,u32 type)397 static void TCSetLayerType( TCLayer* ly, u32 type )
398 {
399
400 TCAssertMsg( (ly != NULL), "TCSetLayerType, Null TCLayer ptr\n" );
401
402 switch( type )
403 {
404 case LY_IMAGE_COLOR_RGB24:
405 case LY_IMAGE_COLOR_CI16:
406 case LY_IMAGE_ALPHA_A8:
407 case LY_IMAGE_COLOR_CMP:
408
409 ly->type = type;
410 break;
411 default:
412 TCErrorMsg( "TCSetLayerType: unknown layer type\n" );
413 return;
414 break;
415 }
416 }
417
418 /*>*******************************(*)*******************************<*/
TCSetLayerDimensions(TCLayer * ly,u32 width,u32 height)419 static void TCSetLayerDimensions( TCLayer* ly, u32 width, u32 height )
420 {
421
422 TCAssertMsg( (ly != NULL), "TCSetLayerDimensions: NULL TCLayer ptr\n" );
423
424 if( (width == 0) || (width > 1024) )
425 TCErrorMsg( "TCSetLayerDimensions: layer width is out of range\n" );
426
427 if( (height == 0) || (height > 1024) )
428 TCErrorMsg( "TCSetLayerDimensions: layer height is out of range\n" );
429
430 ly->width = width;
431 ly->height = height;
432 }
433
434 /*>*******************************(*)*******************************<*/
435 // copy the contents of a layer including the data pointer
436 /*>*******************************(*)*******************************<*/
TCCopyLayer(TCLayer * src,TCLayer * dst)437 static void TCCopyLayer( TCLayer* src, TCLayer* dst )
438 {
439 if( (src == NULL) || (dst == NULL ) )
440 {
441 return;
442 }
443
444 dst->type = src->type;
445 dst->width = src->width;
446 dst->height = src->height;
447 dst->data = src->data;
448 }
449
450 /*>*******************************(*)*******************************<*/
451