示例#1
0
文件: QutTexture.c 项目: refnum/quesa
TQ3TextureObject
QutTexture_CreateTextureObjectFromPixmap(PixMapHandle		thePixMap,
									TQ3PixelType	pixelType,
									TQ3Boolean		wantMipMaps)
{	TQ3Uns32				x, y, theWidth, theHeight, rowBytes, pixelBytes;
	TQ3TextureObject		qd3dTextureObject = NULL;
	TQ3StorageObject		qd3dMemoryStorage;
	TQ3StoragePixmap		qd3dPixMap;
	TQ3Mipmap				qd3dMipMap;
	UInt16					*pixelPtr;
	UInt8					*baseAddr;
	OSType					pixelFormat;
	TQ3Endian				byteOrder;


	// Get the details we need from the PixMap
	NoPurgePixels(thePixMap);
	LockPixels(thePixMap);

	theWidth   = (*thePixMap)->bounds.right  - (*thePixMap)->bounds.left;
	theHeight  = (*thePixMap)->bounds.bottom - (*thePixMap)->bounds.top;
	rowBytes   = (*thePixMap)->rowBytes & 0x7FFF;
	pixelBytes = (*thePixMap)->pixelSize / 8;
	baseAddr   = (UInt8 *) GetPixBaseAddr(thePixMap);
#if OLDPIXMAPSTRUCT
	pixelFormat = 0;
#else
	pixelFormat = (*thePixMap)->pixelFormat;
#endif


	// If this is a 16 bit alpha channel texture, set the alpha bits.
	// We assume that black is transparent.
	if (pixelType == kQ3PixelTypeARGB16)
		{
		for (y = 0; y < theHeight; y++)
			{
			for (x = 0; x < theWidth; x++)
				{
				pixelPtr = (UInt16 *) (baseAddr + (y * rowBytes) + (x * 2));
				if (*pixelPtr != 0x0000)
					*pixelPtr |= (1 << 15);
				}
			}
		}


	// Set the byte order
	if ( (pixelFormat == k32BGRAPixelFormat) ||
		(pixelFormat == k16LE555PixelFormat) )
	{
		byteOrder = kQ3EndianLittle;
	}
	else
	{
		byteOrder = kQ3EndianBig;
	}


	// Create a storage object based on the GWorld
	qd3dMemoryStorage = Q3MemoryStorage_New(baseAddr, theHeight * rowBytes);
	if (qd3dMemoryStorage != NULL)
		{
		// Create the appropriate type of texture. Note that if mip-maps are
		// required, we create a QD3D PixMap. This might seem back to front,
		// but QD3D automatically creates mip-maps for PixMaps.
		//
		// If mip-maps are not required, we create a QD3D MipMap by hand and
		// signal that we don't want any other mip-maps to be created.
		//
		// We need to work around a bug in Q3MipmapTexture_New: if the rowByte
		// for the pixel exactly matches the size of each row, the texture is
		// distorted - we can fix this by using Q3PixmapTexture_New instead. 
		if (wantMipMaps || (rowBytes == theWidth * pixelBytes))
			{
			// Create a PixMap from the GWorld data
			qd3dPixMap.image        = qd3dMemoryStorage;
			qd3dPixMap.width		= theWidth;
			qd3dPixMap.height		= theHeight;
			qd3dPixMap.rowBytes		= rowBytes;
			qd3dPixMap.pixelSize	= (pixelType == kQ3PixelTypeARGB32 || pixelType == kQ3PixelTypeRGB32) ? 32 : 16;
			qd3dPixMap.pixelType	= pixelType;
			qd3dPixMap.bitOrder		= byteOrder;
			qd3dPixMap.byteOrder	= byteOrder;

			qd3dTextureObject = Q3PixmapTexture_New(&qd3dPixMap);
			}
	
		else
			{
			// Create a MipMap from the GWorld data
			qd3dMipMap.image         = qd3dMemoryStorage;
			qd3dMipMap.useMipmapping = kQ3False;
			qd3dMipMap.pixelType	 = pixelType;
			qd3dMipMap.bitOrder		 = byteOrder;
			qd3dMipMap.byteOrder	 = byteOrder;
			qd3dMipMap.reserved		 = 0;

			qd3dMipMap.mipmaps[0].width    = theWidth;
			qd3dMipMap.mipmaps[0].height   = theHeight;
			qd3dMipMap.mipmaps[0].rowBytes = rowBytes;
			qd3dMipMap.mipmaps[0].offset   = 0;
		
			qd3dTextureObject = Q3MipmapTexture_New(&qd3dMipMap);
			}
		Q3Object_Dispose(qd3dMemoryStorage);
		
		}



	// Clean up and return
	UnlockPixels(thePixMap);
	return(qd3dTextureObject);
}
示例#2
0
short LoadMapPICT(
	PicHandle 			pict,
	unsigned long 		mapID,
	unsigned long 		mapSizeX,
	unsigned long 		mapSizeY,
	TQ3StoragePixmap 	*bMap)
{
	unsigned long 			*textureMap;
	unsigned long			*textureMapAddr;
	unsigned long 			*pictMap;
	unsigned long			pictMapAddr;
	register unsigned long 	row;
	register unsigned long 	col;
	Rect 					rectGW;
	GWorldPtr 				pGWorld;
	PixMapHandle 			hPixMap;
	unsigned long 			pictRowBytes;
	QDErr					err;
	GDHandle				oldGD;
	GWorldPtr				oldGW;
	short					success;
	
	mapID;		/* unused argument */
	
	/* save current port */
	GetGWorld(&oldGW, &oldGD);

	/* create the GWorld */
	SetRect(&rectGW, 0, 0, (unsigned short)mapSizeX, (unsigned short)mapSizeY);

	err = NewGWorld(&pGWorld, 32, &rectGW, 0, 0, useTempMem);
	if (err != noErr)
		return 0;

	success = 1;
	
	hPixMap = GetGWorldPixMap(pGWorld);
	pictMapAddr = (unsigned long)GetPixBaseAddr (hPixMap);
	pictRowBytes = (unsigned long)(**hPixMap).rowBytes & 0x3fff;
	
	/* put the PICT into the window */
	SetGWorld(pGWorld, nil);
	
	LockPixels(hPixMap);
	EraseRect(&rectGW);
	DrawPicture(pict, &rectGW);
		
	/* allocate an area of memory for the texture */
	textureMap = (unsigned long *)malloc(mapSizeX * mapSizeY * sizeof(unsigned long));
	if (textureMap == NULL) {
		success = 0;
		goto bail;
	}
	/* bMap->image = (char *)textureMap; */

	/* copy the PICT into the texture */
	textureMapAddr = textureMap;
	for (row = 0L; row < mapSizeY; row++) {
		pictMap = (unsigned long *)(pictMapAddr + (pictRowBytes * row));
		for (col = 0L; col < mapSizeX; col++) {
			*textureMap++ = (*pictMap++ | 0xff000000L);
		}
	}
		
	bMap->image = Q3MemoryStorage_New((const unsigned char *)textureMapAddr, 
								  mapSizeX * mapSizeY * sizeof(unsigned long));
								  
	if (bMap->image == NULL) {
		/* error */
		success = 0;
		goto bail;
	}

	UnlockPixels(hPixMap);
	
	bMap->width 	= mapSizeX;
	bMap->height	= mapSizeY;
	bMap->rowBytes 	= bMap->width * 4;
	bMap->pixelSize = 32;
	bMap->pixelType	= kQ3PixelTypeRGB32;
	bMap->bitOrder	= kQ3EndianBig;
	bMap->byteOrder	= kQ3EndianBig;
	
	/* Free junk */
bail:

	SetGWorld(oldGW, oldGD);
	
	DisposeGWorld(pGWorld);
	if (textureMapAddr != NULL)
		free(textureMapAddr);
	
	return success;
}
示例#3
0
文件: QutTexture.c 项目: refnum/quesa
//-----------------------------------------------------------------------------
//		QutTexture_CreateTextureObjectFromTGAFile : Create texture object from a TGA file.
//-----------------------------------------------------------------------------
TQ3TextureObject
QutTexture_CreateTextureObjectFromTGAFile( const char* inFilePath )
{
	TQ3TextureObject	theTexture = NULL;
	FILE*				theFile = NULL;
	TGAHeader			theHeader;
	int					numPixels, bytesPerPixel, n, i, j;
	int					oppositeRow, packetHeader, chunkSize, rowBytes;
	TQ3Object			memStorage = NULL;
	unsigned char		p[5];
	unsigned char*		theBuffer;
	TQ3Uns32			bufferSize;
	TQ3StoragePixmap	thePixMap;
	TQ3PixelType		pixelType;
	
	theFile = fopen( inFilePath, "rb" );
	if (theFile != NULL)
	{
		// Read the file header.
		theHeader.IDLength = fgetc( theFile );
		theHeader.colorMapType = fgetc( theFile );
		theHeader.dataTypeCode = fgetc( theFile );
		theHeader.colorMapOrigin = qutTexture_read_littleendian_short( theFile );
		theHeader.colorMapLength = qutTexture_read_littleendian_short( theFile );
		theHeader.colorMapDepth = fgetc( theFile );
		theHeader.x_origin = qutTexture_read_littleendian_short( theFile );
		theHeader.y_origin = qutTexture_read_littleendian_short( theFile );
		theHeader.width = qutTexture_read_littleendian_short( theFile );
		theHeader.height = qutTexture_read_littleendian_short( theFile );
		theHeader.bitsPerPixel = fgetc( theFile );
		theHeader.imageDescriptor = fgetc( theFile );
		
		// Check that the image format is one we can handle.
		if (
			(
				(theHeader.dataTypeCode == kTGATypeColor) ||
				(theHeader.dataTypeCode == kTGATypeColorRLE)
			) &&
			(
				(theHeader.bitsPerPixel == 16) ||
				(theHeader.bitsPerPixel == 24) ||
				(theHeader.bitsPerPixel == 32)
			) &&
			(
				(theHeader.colorMapType == 0) ||
				(theHeader.colorMapType == 1)
			) &&
			! (feof(theFile) || ferror(theFile))
		)
		{
			// Skip identification field, if any.
			fseek( theFile, theHeader.IDLength, SEEK_CUR );
			// Skip color map, if any.
			fseek( theFile, theHeader.colorMapType * theHeader.colorMapLength, SEEK_CUR );
			
			// Make a storage object to hold the pixels.
			bytesPerPixel = theHeader.bitsPerPixel / 8;
			numPixels = theHeader.width * theHeader.height;
			bufferSize = numPixels * bytesPerPixel;
			theBuffer = (unsigned char*) malloc( bufferSize );
			if (theBuffer != NULL)
			{
				// Read the image.
				n = 0;
				while ( (n < numPixels) && (!feof(theFile)) && (!ferror(theFile)) )
				{
					if (theHeader.dataTypeCode == kTGATypeColor)	// uncompressed
					{
						fread( theBuffer + n * bytesPerPixel, bytesPerPixel, 1, theFile );
						++n;
					}
					else	// RLE compressed
					{
						packetHeader = fgetc( theFile );
						chunkSize = (packetHeader & 0x7F) + 1;
						
						if (packetHeader & 0x80)	// RLE chunk
						{
							fread( p, bytesPerPixel, 1, theFile );
							
							for (i=0; i < chunkSize; ++i)
							{
								memcpy( theBuffer + n * bytesPerPixel, p, bytesPerPixel );
								++n;
							}
						}
						else	// uncompressed chunk
						{
							fread( theBuffer + n * bytesPerPixel, bytesPerPixel, chunkSize, theFile );
							n += chunkSize;
						}
					}
				}
				
				// We may need to flip the image into the usual top to bottom row order.
				rowBytes = theHeader.width * bytesPerPixel;
				if ( (theHeader.imageDescriptor & kTGADescTopToBottom) == 0)
				{
					for (i = 0; i < theHeader.height / 2; ++i)
					{
						oppositeRow = theHeader.height - i - 1;
						for (j = 0; j < rowBytes; ++j)
						{
							unsigned char temp = theBuffer[ i * rowBytes + j ];
							theBuffer[ i * rowBytes + j ] = theBuffer[ oppositeRow * rowBytes + j ];
							theBuffer[ oppositeRow * rowBytes + j ] = temp;
						}
					}
				}
				
				// Set the pixel type
				switch (bytesPerPixel)
				{
					case 2:
						pixelType = kQ3PixelTypeRGB16;
						break;
						
					case 3:
						pixelType = kQ3PixelTypeRGB24;
						break;
					
					default:	// quiet an uninitialized-variable warning
					case 4:
						pixelType = kQ3PixelTypeARGB32;
						// Typically TGA format uses non-premultiplied alpha,
						// whereas Quesa usually expects premultiplied alpha, so
						// we multiply here.
						for (i = 0; i < theHeader.width * theHeader.height; ++i)
						{
							unsigned short a = theBuffer[i*4+3];

							theBuffer[i*4] = (theBuffer[i*4]*a) / 255;
							theBuffer[i*4+1] = (theBuffer[i*4+1]*a) / 255;
							theBuffer[i*4+2] = (theBuffer[i*4+2]*a) / 255;							
						}
						break;
				}
				
			#if TARGET_API_MAC_OS8
				// QD3D on Mac does not support kQ3PixelTypeRGB24, and also appears to
				// ignore the byte order, so we must convert to kQ3PixelTypeRGB32 in
				// big-endian order.
				if (pixelType == kQ3PixelTypeRGB24)
				{
					unsigned char*	bigBuffer = malloc( numPixels * 4 );
					if (bigBuffer != NULL)
					{
						pixelType = kQ3PixelTypeRGB32;
						
						for (i = 0; i < numPixels; ++i)
						{
							bigBuffer[4*i + 3] = theBuffer[3*i];
							bigBuffer[4*i + 2] = theBuffer[3*i + 1];
							bigBuffer[4*i + 1] = theBuffer[3*i + 2];
						}
						
						bytesPerPixel = 4;
						rowBytes = theHeader.width * bytesPerPixel;
						bufferSize = numPixels * bytesPerPixel;
						free( theBuffer );
						theBuffer = bigBuffer;
					}
				}
			#endif
				
				// Create a memory storage object holding a copy of the buffer
				memStorage = Q3MemoryStorage_New( theBuffer, bufferSize );
				
				if (memStorage != NULL)
				{
					// Create the texture object
					thePixMap.image = memStorage;
					thePixMap.width = theHeader.width;
					thePixMap.height = theHeader.height;
					thePixMap.rowBytes = rowBytes;
					thePixMap.pixelSize = bytesPerPixel * 8;
					thePixMap.bitOrder = kQ3EndianLittle;
					thePixMap.byteOrder = kQ3EndianLittle;
					thePixMap.pixelType = pixelType;
					
					theTexture = Q3PixmapTexture_New( &thePixMap );
					
					Q3Object_Dispose( memStorage );
				}
				free( theBuffer );
			}
		}
		
		fclose( theFile );
	}
	
	return theTexture;
}
示例#4
0
文件: E3Texture.c 项目: refnum/quesa
TQ3Status
E3CompressedPixmapTexture_CompressImage(TQ3CompressedPixmap *	compressedPixmap, 
										PixMapHandle 			sourcePixMap, 
										CodecType				codecType, 
										CodecComponent			codecComponent, 
										TQ3Int16				codedDepth, 
										CodecQ					codecQuality)
{


	// If we support QuickTime, compress the image
	ImageDescriptionHandle	imageDescH 			= NULL;
	long					maxCompressedSize	= 0;
	Handle					compressedDataH		= NULL;
	Ptr						compressedDataP		= NULL;
	OSErr					theErr				= noErr;
	Rect 					bounds				= (**sourcePixMap).bounds;
	TQ3StorageObject		compressedImage		= NULL;
	TQ3StorageObject		imageDesc			= NULL;



	// Make sure QuickTime is present
	if ((TQ3Uns32) EnterMovies == (TQ3Uns32) kUnresolvedCFragSymbolAddress)
		return(kQ3Failure);



	theErr = GetMaxCompressionSize(	sourcePixMap,
									&bounds, 
									codedDepth,
									codecQuality,
									codecType,
									(CompressorComponent)codecComponent,
									&maxCompressedSize);
									
	if ( theErr != noErr ) 
	{
		// paramErr or noCodecErr
		E3ErrorManager_PostError( kQ3ErrorInvalidParameter, kQ3False ) ;
		
		// failure
		return(kQ3Failure);
	}
	
	// allocate memory - we need to use Mac OS Handles for QuickTime
	imageDescH		= (ImageDescriptionHandle) NewHandle( 4 );
	compressedDataH = NewHandle( maxCompressedSize );
	
	if ( compressedDataH != NULL && imageDescH != NULL )
	{
		HLock(compressedDataH);
		compressedDataP = *compressedDataH;
	
		theErr = FCompressImage(sourcePixMap,
								&bounds,
								codedDepth,
								codecQuality,
								codecType,
								(CompressorComponent) codecComponent,
								NULL,
								0,
								0,
								NULL,
								NULL,
								imageDescH,
								compressedDataP);
		
		if ( theErr != noErr )
		{
			// post error
			if (MemError() !=  noErr)
				E3ErrorManager_PostError( kQ3ErrorOutOfMemory , kQ3False ) ;
			else
				E3ErrorManager_PostError( kQ3ErrorInvalidParameter , kQ3False ) ;

			//deallocate  handle storage
			DisposeHandle( (Handle)imageDescH);
			DisposeHandle( compressedDataH);
			
			// failure
			return(kQ3Failure) ;			
		}
		
	}
	// otherwise we have a memory error
	else
	{
		// deallocate handle storage
		if (imageDescH) 
			DisposeHandle( (Handle)imageDescH);
		if (compressedDataH) 
			DisposeHandle( compressedDataH);
		
		// post error
		E3ErrorManager_PostError( kQ3ErrorOutOfMemory , kQ3False ) ;
		
		//failure
		return( kQ3Failure) ;
		
	}
	
	
	if (imageDescH) 
		DisposeHandle( (Handle)imageDescH);
	if (compressedDataH) 
		DisposeHandle( compressedDataH);
	
	// lock the image desc handle
	HLock( (Handle) imageDescH ) ;
		
	// store the data in storage objects
	compressedImage = Q3MemoryStorage_New(	(unsigned char *) compressedDataP, 
											(TQ3Uns32)        (**imageDescH).dataSize ) ;
	imageDesc		= Q3MemoryStorage_New( 	(unsigned char *) imageDescH, 
											(TQ3Uns32)        (**imageDescH).idSize ) ;
	
		
	// make sure memory was allocated
	if( compressedImage == NULL && imageDesc == NULL )
	{
		if( compressedImage != NULL )
			Q3Object_Dispose( compressedImage ) ;
		if( imageDesc != NULL )
			Q3Object_Dispose( imageDesc ) ;
				
		// deallocate handle storage
		DisposeHandle( (Handle) imageDescH ) ;
		DisposeHandle( compressedDataH ) ;
		
		// we don't need to post a memory error because it
		// has already been done, return failure
		return(kQ3Failure);
	}
	
	
	// store the data in the compressed pixmap structure
	E3Shared_Acquire(&compressedPixmap->compressedImage, compressedImage);
	E3Shared_Acquire(&compressedPixmap->imageDesc,       imageDesc);
	
	// NOTE: we do not fill out the other fields of the data structure,
	// since this is the defined QD3D behaviour
	
	// deallocate handle storage
	DisposeHandle( (Handle) imageDescH ) ;
	DisposeHandle( compressedDataH ) ;
	
	return(kQ3Success) ;
}