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