Exemplo n.º 1
0
    //---------------------------------------------------------------------    
	Codec::DecodeResult PVRTCCodec::decodeV2(DataStreamPtr& stream) const
	{
		PVRTCTexHeaderV2 header;
        uint32 flags = 0, formatFlags = 0;
        size_t numFaces = 1; // Assume one face until we know otherwise

        ImageData *imgData = OGRE_NEW ImageData();
		MemoryDataStreamPtr output;

        // Read the PVRTC header
        stream->read(&header, sizeof(PVRTCTexHeaderV2));

        // Get format flags
        flags = header.flags;
        flipEndian(reinterpret_cast<void*>(flags), sizeof(uint32));
        formatFlags = flags & PVR_TEXTURE_FLAG_TYPE_MASK;

        uint32 bitmaskAlpha = header.bitmaskAlpha;
        flipEndian(reinterpret_cast<void*>(bitmaskAlpha), sizeof(uint32));

        if (formatFlags == kPVRTextureFlagTypePVRTC_4 || formatFlags == kPVRTextureFlagTypePVRTC_2)
        {
            if (formatFlags == kPVRTextureFlagTypePVRTC_4)
            {
                imgData->format = bitmaskAlpha ? PF_PVRTC_RGBA4 : PF_PVRTC_RGB4;
            }
            else if (formatFlags == kPVRTextureFlagTypePVRTC_2)
            {
                imgData->format = bitmaskAlpha ? PF_PVRTC_RGBA2 : PF_PVRTC_RGB2;
            }

            imgData->depth = 1;
            imgData->width = header.width;
            imgData->height = header.height;
            imgData->num_mipmaps = static_cast<ushort>(header.numMipmaps);

            // PVRTC is a compressed format
            imgData->flags |= IF_COMPRESSED;
        }

        // Calculate total size from number of mipmaps, faces and size
		imgData->size = Image::calculateSize(imgData->num_mipmaps, numFaces, 
                                             imgData->width, imgData->height, imgData->depth, imgData->format);

		// Bind output buffer
		output.bind(OGRE_NEW MemoryDataStream(imgData->size));

		// Now deal with the data
		void *destPtr = output->getPtr();
        stream->read(destPtr, imgData->size);
        destPtr = static_cast<void*>(static_cast<uchar*>(destPtr));

		DecodeResult ret;
		ret.first = output;
		ret.second = CodecDataPtr(imgData);

		return ret;
	}
Exemplo n.º 2
0
    //---------------------------------------------------------------------
    Codec::DecodeResult FreeImageCodec::decode(DataStreamPtr& input) const
    {
		// Set error handler
		FreeImage_SetOutputMessage(FreeImageLoadErrorHandler);

		// Buffer stream into memory (TODO: override IO functions instead?)
		MemoryDataStream memStream(input, true);

		FIMEMORY* fiMem = 
			FreeImage_OpenMemory(memStream.getPtr(), static_cast<DWORD>(memStream.size()));

		FIBITMAP* fiBitmap = FreeImage_LoadFromMemory(
			(FREE_IMAGE_FORMAT)mFreeImageType, fiMem);
		if (!fiBitmap)
		{
			OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, 
				"Error decoding image", 
				"FreeImageCodec::decode");
		}


		ImageData* imgData = OGRE_NEW ImageData();
		MemoryDataStreamPtr output;

		imgData->depth = 1; // only 2D formats handled by this codec
		imgData->width = FreeImage_GetWidth(fiBitmap);
		imgData->height = FreeImage_GetHeight(fiBitmap);
        imgData->num_mipmaps = 0; // no mipmaps in non-DDS 
        imgData->flags = 0;

		// Must derive format first, this may perform conversions
		
		FREE_IMAGE_TYPE imageType = FreeImage_GetImageType(fiBitmap);
		FREE_IMAGE_COLOR_TYPE colourType = FreeImage_GetColorType(fiBitmap);
		unsigned bpp = FreeImage_GetBPP(fiBitmap);

		switch(imageType)
		{
		case FIT_UNKNOWN:
		case FIT_COMPLEX:
		case FIT_UINT32:
		case FIT_INT32:
		case FIT_DOUBLE:
        default:
			OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, 
				"Unknown or unsupported image format", 
				"FreeImageCodec::decode");
				
			break;
		case FIT_BITMAP:
			// Standard image type
			// Perform any colour conversions for greyscale
			if (colourType == FIC_MINISWHITE || colourType == FIC_MINISBLACK)
			{
				FIBITMAP* newBitmap = FreeImage_ConvertToGreyscale(fiBitmap);
				// free old bitmap and replace
				FreeImage_Unload(fiBitmap);
				fiBitmap = newBitmap;
				// get new formats
				bpp = FreeImage_GetBPP(fiBitmap);
				colourType = FreeImage_GetColorType(fiBitmap);
			}
			// Perform any colour conversions for RGB
			else if (bpp < 8 || colourType == FIC_PALETTE || colourType == FIC_CMYK)
			{
				FIBITMAP* newBitmap =  NULL;	
				if (FreeImage_IsTransparent(fiBitmap))
				{
					// convert to 32 bit to preserve the transparency 
					// (the alpha byte will be 0 if pixel is transparent)
					newBitmap = FreeImage_ConvertTo32Bits(fiBitmap);
				}
				else
				{
					// no transparency - only 3 bytes are needed
					newBitmap = FreeImage_ConvertTo24Bits(fiBitmap);
				}

				// free old bitmap and replace
				FreeImage_Unload(fiBitmap);
				fiBitmap = newBitmap;
				// get new formats
				bpp = FreeImage_GetBPP(fiBitmap);
				colourType = FreeImage_GetColorType(fiBitmap);
			}

			// by this stage, 8-bit is greyscale, 16/24/32 bit are RGB[A]
			switch(bpp)
			{
			case 8:
				imgData->format = PF_L8;
				break;
			case 16:
				// Determine 555 or 565 from green mask
				// cannot be 16-bit greyscale since that's FIT_UINT16
				if(FreeImage_GetGreenMask(fiBitmap) == FI16_565_GREEN_MASK)
				{
					imgData->format = PF_R5G6B5;
				}
				else
				{
					// FreeImage doesn't support 4444 format so must be 1555
					imgData->format = PF_A1R5G5B5;
				}
				break;
			case 24:
				// FreeImage differs per platform
				//     PF_BYTE_BGR[A] for little endian (== PF_ARGB native)
				//     PF_BYTE_RGB[A] for big endian (== PF_RGBA native)
#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB
				imgData->format = PF_BYTE_RGB;
#else
				imgData->format = PF_BYTE_BGR;
#endif
				break;
			case 32:
#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB
				imgData->format = PF_BYTE_RGBA;
#else
				imgData->format = PF_BYTE_BGRA;
#endif
				break;
				
				
			};
			break;
		case FIT_UINT16:
		case FIT_INT16:
			// 16-bit greyscale
			imgData->format = PF_L16;
			break;
		case FIT_FLOAT:
			// Single-component floating point data
			imgData->format = PF_FLOAT32_R;
			break;
		case FIT_RGB16:
			imgData->format = PF_SHORT_RGB;
			break;
		case FIT_RGBA16:
			imgData->format = PF_SHORT_RGBA;
			break;
		case FIT_RGBF:
			imgData->format = PF_FLOAT32_RGB;
			break;
		case FIT_RGBAF:
			imgData->format = PF_FLOAT32_RGBA;
			break;
			
			
		};

		unsigned char* srcData = FreeImage_GetBits(fiBitmap);
		unsigned srcPitch = FreeImage_GetPitch(fiBitmap);

		// Final data - invert image and trim pitch at the same time
		size_t dstPitch = imgData->width * PixelUtil::getNumElemBytes(imgData->format);
		imgData->size = dstPitch * imgData->height;
        // Bind output buffer
        output.bind(OGRE_NEW MemoryDataStream(imgData->size));

		uchar* pSrc;
		uchar* pDst = output->getPtr();
		for (size_t y = 0; y < imgData->height; ++y)
		{
			pSrc = srcData + (imgData->height - y - 1) * srcPitch;
			memcpy(pDst, pSrc, dstPitch);
			pDst += dstPitch;
		}

		
		FreeImage_Unload(fiBitmap);
		FreeImage_CloseMemory(fiMem);


        DecodeResult ret;
        ret.first = output;
        ret.second = CodecDataPtr(imgData);
		return ret;

    }
Exemplo n.º 3
0
    //---------------------------------------------------------------------
	bool ETCCodec::decodeKTX(DataStreamPtr& stream, DecodeResult& result) const
	{
        KTXHeader header;
        // Read the ETC1 header
        stream->read(&header, sizeof(KTXHeader));

		const uint8 KTXFileIdentifier[12] = { 0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A };
		if (memcmp(KTXFileIdentifier, &header.identifier, sizeof(KTXFileIdentifier)) != 0 )
			return false;

		if (header.endianness == KTX_ENDIAN_REF_REV)
			flipEndian(&header.glType, sizeof(uint32), 1);

        ImageData *imgData = OGRE_NEW ImageData();
        imgData->depth = 1;
        imgData->width = header.pixelWidth;
        imgData->height = header.pixelHeight;
		imgData->num_mipmaps = static_cast<ushort>(header.numberOfMipmapLevels - 1);

		switch(header.glInternalFormat)
		{
		case 37492: // GL_COMPRESSED_RGB8_ETC2
            imgData->format = PF_ETC2_RGB8;
			break;
        case 37496:// GL_COMPRESSED_RGBA8_ETC2_EAC
			imgData->format = PF_ETC2_RGBA8;
            break;
		case 37494: // GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
            imgData->format = PF_ETC2_RGB8A1;
			break;
		case 35986: // ATC_RGB
			imgData->format = PF_ATC_RGB;
			break;
		case 35987: // ATC_RGB_Explicit
			imgData->format = PF_ATC_RGBA_EXPLICIT_ALPHA;
			break;
		case 34798: // ATC_RGB_Interpolated
			imgData->format = PF_ATC_RGBA_INTERPOLATED_ALPHA;
			break;
		case 33777: // DXT 1
	        imgData->format = PF_DXT1;
			break;
		case 33778: // DXT 3
	        imgData->format = PF_DXT3;
			break;
		case 33779: // DXT 5
	        imgData->format = PF_DXT5;
			break;
		default:		
	        imgData->format = PF_ETC1_RGB8;
			break;
		}
		
		imgData->flags = 0;
		if (header.glType == 0 || header.glFormat == 0)
	        imgData->flags |= IF_COMPRESSED;

		size_t numFaces = 1; // Assume one face until we know otherwise
                             // Calculate total size from number of mipmaps, faces and size
		imgData->size = Image::calculateSize(imgData->num_mipmaps, numFaces,
                                             imgData->width, imgData->height, imgData->depth, imgData->format);

		stream->skip(header.bytesOfKeyValueData);

		// Bind output buffer
		MemoryDataStreamPtr output;
		output.bind(OGRE_NEW MemoryDataStream(imgData->size));

		// Now deal with the data
		uchar* destPtr = output->getPtr();
		for (uint32 level = 0; level < header.numberOfMipmapLevels; ++level)
		{
			uint32 imageSize = 0;
			stream->read(&imageSize, sizeof(uint32));
			stream->read(destPtr, imageSize);
			destPtr += imageSize;
		}

		result.first = output;
		result.second = CodecDataPtr(imgData);
        
		return true;
	}
Exemplo n.º 4
0
    //---------------------------------------------------------------------
	bool ETCCodec::decodePKM(DataStreamPtr& stream, DecodeResult& result) const
	{
        PKMHeader header;

        // Read the ETC header
        stream->read(&header, sizeof(PKMHeader));

        if (PKM_MAGIC != FOURCC(header.name[0], header.name[1], header.name[2], header.name[3]) ) // "PKM 10"
            return false;

        uint16 width = (header.iWidthMSB << 8) | header.iWidthLSB;
        uint16 height = (header.iHeightMSB << 8) | header.iHeightLSB;
        uint16 paddedWidth = (header.iPaddedWidthMSB << 8) | header.iPaddedWidthLSB;
        uint16 paddedHeight = (header.iPaddedHeightMSB << 8) | header.iPaddedHeightLSB;
        uint16 type = (header.iTextureTypeMSB << 8) | header.iTextureTypeLSB;

        ImageData *imgData = OGRE_NEW ImageData();
        imgData->depth = 1;
        imgData->width = width;
        imgData->height = height;

        // File version 2.0 supports ETC2 in addition to ETC1
        if(header.version[0] == '2' && header.version[1] == '0')
        {
            switch (type) {
                case 0:
                    imgData->format = PF_ETC1_RGB8;
                    break;

                    // GL_COMPRESSED_RGB8_ETC2
                case 1:
                    imgData->format = PF_ETC2_RGB8;
                    break;

                    // GL_COMPRESSED_RGBA8_ETC2_EAC
                case 3:
                    imgData->format = PF_ETC2_RGBA8;
                    break;

                    // GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
                case 4:
                    imgData->format = PF_ETC2_RGB8A1;
                    break;

                    // Default case is ETC1
                default:
                    imgData->format = PF_ETC1_RGB8;
                    break;
            }
        }
        else
            imgData->format = PF_ETC1_RGB8;

        // ETC has no support for mipmaps - malideveloper.com has a example
        // where the load mipmap levels from different external files
        imgData->num_mipmaps = 0;

        // ETC is a compressed format
        imgData->flags |= IF_COMPRESSED;

        // Calculate total size from number of mipmaps, faces and size
		imgData->size = (paddedWidth * paddedHeight) >> 1;

		// Bind output buffer
		MemoryDataStreamPtr output;
		output.bind(OGRE_NEW MemoryDataStream(imgData->size));

		// Now deal with the data
		void *destPtr = output->getPtr();
        stream->read(destPtr, imgData->size);
        destPtr = static_cast<void*>(static_cast<uchar*>(destPtr));
        
		DecodeResult ret;
		ret.first = output;
		ret.second = CodecDataPtr(imgData);

        return true;
    }
Exemplo n.º 5
0
Codec::DecodeResult EXRCodec::decode(DataStreamPtr& input) const
{
    ImageData * imgData = new ImageData;
    MemoryDataStreamPtr output;

    try {
        // Make a mutable clone of input to be able to change file pointer
        MemoryDataStream myIn(input);
    
        // Now we can simulate an OpenEXR file with that
        O_IStream str(myIn, "SomeChunk.exr");
        InputFile file(str);
    
        Box2i dw = file.header().dataWindow();
        int width  = dw.max.x - dw.min.x + 1;
        int height = dw.max.y - dw.min.y + 1;
        int components = 3;
    
        // Alpha channel present?
        const ChannelList &channels = file.header().channels();
        if(channels.findChannel("A"))
            components = 4;
        
        // Allocate memory
        output.bind(new MemoryDataStream(width*height*components*4));
    
        // Construct frame buffer
        uchar *pixels = output->getPtr();
        FrameBuffer frameBuffer;
        frameBuffer.insert("R",             // name
                    Slice (FLOAT,       // type
                       ((char *) pixels)+0, // base
                       4 * components,      // xStride
                    4 * components * width));    // yStride
        frameBuffer.insert("G",             // name
                    Slice (FLOAT,       // type
                       ((char *) pixels)+4, // base
                       4 * components,      // xStride
                    4 * components * width));    // yStride
        frameBuffer.insert("B",             // name
                    Slice (FLOAT,       // type
                       ((char *) pixels)+8, // base
                       4 * components,      // xStride
                    4 * components * width));    // yStride
        if(components==4) {
            frameBuffer.insert("A",                 // name
                        Slice (FLOAT,           // type
                           ((char *) pixels)+12,        // base
                           4 * components,      // xStride
                        4 * components * width));    // yStride
        }
      
        file.setFrameBuffer (frameBuffer);
        file.readPixels (dw.min.y, dw.max.y);
    
        imgData->format = components==3 ? PF_FLOAT32_RGB : PF_FLOAT32_RGBA;
        imgData->width = width;
        imgData->height = height;
        imgData->depth = 1;
        imgData->size = width*height*components*4;
        imgData->num_mipmaps = 0;
        imgData->flags = 0;
    } catch (const std::exception &exc) {
        delete imgData;
        throw(Exception(Exception::ERR_INTERNAL_ERROR,
            "OpenEXR Error",
            exc.what()));
    }
    
    DecodeResult ret;
    ret.first = output; 
    ret.second = CodecDataPtr(imgData);
    return ret;
}
Exemplo n.º 6
0
	//---------------------------------------------------------------------    
	Codec::DecodeResult PVRTCCodec::decodeV3(DataStreamPtr& stream) const
	{
		PVRTCTexHeaderV3 header;
        PVRTCMetadata metadata;
        uint32 flags = 0;
        size_t numFaces = 1; // Assume one face until we know otherwise

        ImageData *imgData = OGRE_NEW ImageData();
		MemoryDataStreamPtr output;

        // Read the PVRTC header
        stream->read(&header, sizeof(PVRTCTexHeaderV3));

        // Read the PVRTC metadata
        if(header.metaDataSize)
        {
            stream->read(&metadata, sizeof(PVRTCMetadata));
        }

        // Identify the pixel format
        switch (header.pixelFormat)
        {
            case kPVRTC1_PF_2BPP_RGB:
                imgData->format = PF_PVRTC_RGB2;
                break;
            case kPVRTC1_PF_2BPP_RGBA:
                imgData->format = PF_PVRTC_RGBA2;
                break;
            case kPVRTC1_PF_4BPP_RGB:
                imgData->format = PF_PVRTC_RGB4;
                break;
            case kPVRTC1_PF_4BPP_RGBA:
                imgData->format = PF_PVRTC_RGBA4;
                break;
            case kPVRTC2_PF_2BPP:
                imgData->format = PF_PVRTC2_2BPP;
                break;
            case kPVRTC2_PF_4BPP:
                imgData->format = PF_PVRTC2_4BPP;
                break;
        }

        // Get format flags
        flags = header.flags;
        flipEndian(reinterpret_cast<void*>(flags), sizeof(uint32));

        imgData->depth = header.depth;
        imgData->width = header.width;
        imgData->height = header.height;
        imgData->num_mipmaps = static_cast<ushort>(header.mipMapCount);

        // PVRTC is a compressed format
        imgData->flags |= IF_COMPRESSED;

        if(header.numFaces == 6)
            imgData->flags |= IF_CUBEMAP;

        if(header.depth > 1)
            imgData->flags |= IF_3D_TEXTURE;

        // Calculate total size from number of mipmaps, faces and size
		imgData->size = Image::calculateSize(imgData->num_mipmaps, numFaces, 
                                             imgData->width, imgData->height, imgData->depth, imgData->format);

		// Bind output buffer
		output.bind(OGRE_NEW MemoryDataStream(imgData->size));

		// Now deal with the data
		void *destPtr = output->getPtr();
        
        uint width = imgData->width;
        uint height = imgData->height;
        uint depth = imgData->depth;

        // All mips for a surface, then each face
        for(size_t mip = 0; mip <= imgData->num_mipmaps; ++mip)
		{
            for(size_t surface = 0; surface < header.numSurfaces; ++surface)
            {
                for(size_t i = 0; i < numFaces; ++i)
                {
                    // Load directly
                    size_t pvrSize = PixelUtil::getMemorySize(width, height, depth, imgData->format);
                    stream->read(destPtr, pvrSize);
                    destPtr = static_cast<void*>(static_cast<uchar*>(destPtr) + pvrSize);
                }
            }

            // Next mip
            if(width!=1) width /= 2;
            if(height!=1) height /= 2;
            if(depth!=1) depth /= 2;
		}

        DecodeResult ret;
		ret.first = output;
		ret.second = CodecDataPtr(imgData);

		return ret;
	}
Exemplo n.º 7
0
    //---------------------------------------------------------------------
    Codec::DecodeResult ILImageCodec::decode(DataStreamPtr& input) const
    {

        // DevIL variables
        ILuint ImageName;

        ILint ImageFormat, BytesPerPixel, ImageType;
        ImageData* imgData = new ImageData();
        MemoryDataStreamPtr output;

        // Load the image
        ilGenImages( 1, &ImageName );
        ilBindImage( ImageName );

        // Put it right side up
        ilEnable(IL_ORIGIN_SET);
        ilSetInteger(IL_ORIGIN_MODE, IL_ORIGIN_UPPER_LEFT);

        // Keep DXTC(compressed) data if present
        ilSetInteger(IL_KEEP_DXTC_DATA, IL_TRUE);

        // Load image from stream, cache into memory
        MemoryDataStream memInput(input);
        ilLoadL( 
            mIlType, 
            memInput.getPtr(), 
            static_cast< ILuint >(memInput.size()));

        // Check if everything was ok
        ILenum PossibleError = ilGetError() ;
        if( PossibleError != IL_NO_ERROR ) {
            OGRE_EXCEPT( Exception::ERR_NOT_IMPLEMENTED,
                "IL Error",
                iluErrorString(PossibleError) ) ;
        }

        ImageFormat = ilGetInteger( IL_IMAGE_FORMAT );
        ImageType = ilGetInteger( IL_IMAGE_TYPE );

        // Convert image if ImageType is incompatible with us (double or long)
        if(ImageType != IL_BYTE && ImageType != IL_UNSIGNED_BYTE && 
			ImageType != IL_FLOAT &&
			ImageType != IL_UNSIGNED_SHORT && ImageType != IL_SHORT) {
            ilConvertImage(ImageFormat, IL_FLOAT);
			ImageType = IL_FLOAT;
        }
		// Converted paletted images
		if(ImageFormat == IL_COLOUR_INDEX)
		{
			ilConvertImage(IL_BGRA, IL_UNSIGNED_BYTE);
			ImageFormat = IL_BGRA;
			ImageType = IL_UNSIGNED_BYTE;
		}

        // Now sets some variables
        BytesPerPixel = ilGetInteger( IL_IMAGE_BYTES_PER_PIXEL ); 

        imgData->format = ILUtil::ilFormat2OgreFormat( ImageFormat, ImageType );
        imgData->width = ilGetInteger( IL_IMAGE_WIDTH );
        imgData->height = ilGetInteger( IL_IMAGE_HEIGHT );
        imgData->depth = ilGetInteger( IL_IMAGE_DEPTH );
        imgData->num_mipmaps = ilGetInteger ( IL_NUM_MIPMAPS );
        imgData->flags = 0;
		
		if(imgData->format == PF_UNKNOWN)
		{
			std::stringstream err;
			err << "Unsupported devil format ImageFormat=" << std::hex << ImageFormat << 
				" ImageType="<< ImageType << std::dec;
			ilDeleteImages( 1, &ImageName );
			
			OGRE_EXCEPT( Exception::ERR_NOT_IMPLEMENTED,
                err.str(),
                "ILImageCodec::decode" ) ;
		}

        // Check for cubemap
        //ILuint cubeflags = ilGetInteger ( IL_IMAGE_CUBEFLAGS );
		size_t numFaces = ilGetInteger ( IL_NUM_IMAGES ) + 1;
        if(numFaces == 6) 
			imgData->flags |= IF_CUBEMAP;
        else
            numFaces = 1; // Support only 1 or 6 face images for now
  
        // Keep DXT data (if present at all and the GPU supports it)
        ILuint dxtFormat = ilGetInteger( IL_DXTC_DATA_FORMAT );
        if(dxtFormat != IL_DXT_NO_COMP && Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability( RSC_TEXTURE_COMPRESSION_DXT ))
        {
			imgData->format = ILUtil::ilFormat2OgreFormat( dxtFormat, ImageType );
            imgData->flags |= IF_COMPRESSED;
            
            // Validate that this devil version saves DXT mipmaps
            if(imgData->num_mipmaps>0)
            {
                ilBindImage(ImageName);
                ilActiveMipmap(1);
                if((size_t)ilGetInteger( IL_DXTC_DATA_FORMAT ) != dxtFormat)
                {
                    imgData->num_mipmaps=0;
                    LogManager::getSingleton().logMessage(
                    "Warning: Custom mipmaps for compressed image "+input->getName()+" were ignored because they are not loaded by this DevIL version");
                }
            }
        }
        
        // Calculate total size from number of mipmaps, faces and size
        imgData->size = Image::calculateSize(imgData->num_mipmaps, numFaces, 
            imgData->width, imgData->height, imgData->depth, imgData->format);

        // Bind output buffer
        output.bind(new MemoryDataStream(imgData->size));
        size_t offset = 0;
        
        // Dimensions of current mipmap
        size_t width = imgData->width;
        size_t height = imgData->height;
        size_t depth = imgData->depth;
        
        // Transfer data
        for(size_t mip=0; mip<=imgData->num_mipmaps; ++mip)
        {   
            for(size_t i = 0; i < numFaces; ++i)
            {
                ilBindImage(ImageName);
                if(numFaces > 1)
                    ilActiveImage(i);
                if(imgData->num_mipmaps > 0)
                    ilActiveMipmap(mip);
                /// Size of this face
                size_t imageSize = PixelUtil::getMemorySize(
                        width, height, depth, imgData->format);
                if(imgData->flags & IF_COMPRESSED)
                {

                    // Compare DXT size returned by DevIL with our idea of the compressed size
                    if(imageSize == ilGetDXTCData(NULL, 0, dxtFormat))
                    {
                        // Retrieve data from DevIL
                        ilGetDXTCData((unsigned char*)output->getPtr()+offset, imageSize, dxtFormat);
                    } else
                    {
                        LogManager::getSingleton().logMessage(
                            "Warning: compressed image "+input->getName()+" size mismatch, devilsize="+StringConverter::toString(ilGetDXTCData(NULL, 0, dxtFormat))+" oursize="+
                            StringConverter::toString(imageSize));
                    }
                }
                else
                {
                    /// Retrieve data from DevIL
                    PixelBox dst(width, height, depth, imgData->format, (unsigned char*)output->getPtr()+offset);
                    ILUtil::toOgre(dst);
                }
                offset += imageSize;
            }
            /// Next mip
            if(width!=1) width /= 2;
            if(height!=1) height /= 2;
            if(depth!=1) depth /= 2;
        }

        // Restore IL state
        ilDisable(IL_ORIGIN_SET);
        ilDisable(IL_FORMAT_SET);

        ilDeleteImages( 1, &ImageName );

        DecodeResult ret;
        ret.first = output;
        ret.second = CodecDataPtr(imgData);


        return ret;
    }
Exemplo n.º 8
0
Ogre::Codec::DecodeResult MTGACodec::decode(Ogre::DataStreamPtr& stream) const
{
	// Read 4 character code
	mtga_header_s hdr;
	//uint32 fileType;
	stream->read(&hdr, sizeof(hdr));
	if (LodResource_Bitmap != hdr.magic)
	{
		OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, 
			"This is not a MTGA file!", "MTGACodec::decode");
	}
	
	mtga_pal_s pal[256];
	assert(stream->size() == sizeof(hdr)+hdr.uncompressedSize + sizeof(pal));

	stream->seek(sizeof(mtga_header_s)+hdr.uncompressedSize);
	stream->read(pal,sizeof(pal));

	bool isTransparent = false;
	mtga_pal_s& clr = pal[0];
	if( (clr.r == 0 && clr.g >250 && clr.b > 250) || (clr.r > 250 && clr.g ==0 && clr.b > 250))
		isTransparent = true;


	Ogre::ImageCodec::ImageData* imgData = OGRE_NEW Ogre::ImageCodec::ImageData();
	imgData->format = PF_BYTE_BGRA;
	imgData->width = hdr.width;
	imgData->height = hdr.height;
	imgData->num_mipmaps = 3;
	imgData->depth = 1;

	imgData->size = Image::calculateSize(imgData->num_mipmaps, 1, 
			imgData->width, imgData->height, imgData->depth, imgData->format);
	
	Ogre::MemoryDataStreamPtr pixelData;
	
	pixelData.bind(OGRE_NEW MemoryDataStream(imgData->size));

	// Now deal with the data
	unsigned char* destPtr = pixelData->getPtr();
	stream->seek(sizeof(mtga_header_s));
	size_t width = hdr.width;
	size_t height = hdr.height;
	for(size_t mip = 0; mip <= imgData->num_mipmaps; ++mip)
	{
			for (size_t y = 0; y < height; y ++)
			{
				for (size_t x = 0; x < width; x ++)
				{
					unsigned char idx;
					stream->read(&idx,1);
					mtga_pal_s& clr = pal[idx];
					assert(destPtr-pixelData->getPtr() < imgData->size);
					
					*destPtr++ = clr.b;
					*destPtr++ = clr.g;
					*destPtr++ = clr.r;
					*destPtr++ = (idx == 0 && isTransparent)?0:255;
				}
			}
			width /=2;
			height /=2;

	}
	


	DecodeResult ret;
	ret.first = pixelData;
	ret.second = CodecDataPtr(imgData);
	return ret;
}