Axiom.Media.DDSCodec.Decode C# (CSharp) Method

Decode() public method

Codes the data from the input chunk into the output chunk.
public Decode ( Stream input, Stream output ) : object
input Stream Input stream (encoded data).
output Stream Output stream (decoded data).
return object
        public override object Decode( Stream input, Stream output, params object[] args )
        {
        	int filePos = 0;

			// Read 4 character code
        	{
        		byte[] filetype = new byte[sizeof(uint)];
        		filePos += input.Read( filetype, filePos, sizeof ( uint ) );
        		uint fileType = 0;
        		IntPtr ptr = Memory.PinObject( fileType );
				FlipEndian( ptr, sizeof(uint), 1);
				Memory.UnpinObject( fileType );
		
				if (new FourCC('D', 'D', 'S', ' ') != fileType)
				{
					throw new AxiomException("This is not a DDS file!");
				}
        	}
		
/*			// Read header in full
			DDSHeader header;
			stream->read(&header, sizeof(DDSHeader));

			// Endian flip if required, all 32-bit values
			flipEndian(&header, 4, sizeof(DDSHeader) / 4);

			// Check some sizes
			if (header.size != DDS_HEADER_SIZE)
			{
				OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, 
					"DDS header size mismatch!", "DDSCodec::decode");
			}
			if (header.pixelFormat.size != DDS_PIXELFORMAT_SIZE)
			{
				OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, 
					"DDS header size mismatch!", "DDSCodec::decode");
			}

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

			imgData->depth = 1; // (deal with volume later)
			imgData->width = header.width;
			imgData->height = header.height;
			size_t numFaces = 1; // assume one face until we know otherwise

			if (header.caps.caps1 & DDSCAPS_MIPMAP)
			{
				imgData->num_mipmaps = static_cast<ushort>(header.mipMapCount - 1);
			}
			else
			{
				imgData->num_mipmaps = 0;
			}
			imgData->flags = 0;

			bool decompressDXT = false;
			// Figure out basic image type
			if (header.caps.caps2 & DDSCAPS2_CUBEMAP)
			{
				imgData->flags |= IF_CUBEMAP;
				numFaces = 6;
			}
			else if (header.caps.caps2 & DDSCAPS2_VOLUME)
			{
				imgData->flags |= IF_3D_TEXTURE;
				imgData->depth = header.depth;
			}
			// Pixel format
			PixelFormat sourceFormat = PF_UNKNOWN;

			if (header.pixelFormat.flags & DDPF_FOURCC)
			{
				sourceFormat = convertFourCCFormat(header.pixelFormat.fourCC);
			}
			else
			{
				sourceFormat = convertPixelFormat(header.pixelFormat.rgbBits, 
					header.pixelFormat.redMask, header.pixelFormat.greenMask, 
					header.pixelFormat.blueMask, 
					header.pixelFormat.flags & DDPF_ALPHAPIXELS ? 
					header.pixelFormat.alphaMask : 0);
			}

			if (PixelUtil::isCompressed(sourceFormat))
			{
				if (!Root::getSingleton().getRenderSystem()->getCapabilities()
					->hasCapability(RSC_TEXTURE_COMPRESSION_DXT))
				{
					// We'll need to decompress
					decompressDXT = true;
					// Convert format
					switch (sourceFormat)
					{
					case PF_DXT1:
						// source can be either 565 or 5551 depending on whether alpha present
						// unfortunately you have to read a block to figure out which
						// Note that we upgrade to 32-bit pixel formats here, even 
						// though the source is 16-bit; this is because the interpolated
						// values will benefit from the 32-bit results, and the source
						// from which the 16-bit samples are calculated may have been
						// 32-bit so can benefit from this.
						DXTColourBlock block;
						stream->read(&block, sizeof(DXTColourBlock));
						flipEndian(&(block.colour_0), sizeof(uint16), 1);
						flipEndian(&(block.colour_1), sizeof(uint16), 1);
						// skip back since we'll need to read this again
						stream->skip(0 - sizeof(DXTColourBlock));
						// colour_0 <= colour_1 means transparency in DXT1
						if (block.colour_0 <= block.colour_1)
						{
							imgData->format = PF_BYTE_RGBA;
						}
						else
						{
							imgData->format = PF_BYTE_RGB;
						}
						break;
					case PF_DXT2:
					case PF_DXT3:
					case PF_DXT4:
					case PF_DXT5:
						// full alpha present, formats vary only in encoding 
						imgData->format = PF_BYTE_RGBA;
						break;
					default:
						// all other cases need no special format handling
						break;
					}
				}
				else
				{
					// Use original format
					imgData->format = sourceFormat;
					// Keep DXT data compressed
					imgData->flags |= IF_COMPRESSED;
				}
			}
			else // not compressed
			{
				// Don't test against DDPF_RGB since greyscale DDS doesn't set this
				// just derive any other kind of format
				imgData->format = sourceFormat;
			}

			// 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();

			// all mips for a face, then each face
			for(size_t i = 0; i < numFaces; ++i)
			{   
				size_t width = imgData->width;
				size_t height = imgData->height;
				size_t depth = imgData->depth;

				for(size_t mip = 0; mip <= imgData->num_mipmaps; ++mip)
				{
					size_t dstPitch = width * PixelUtil::getNumElemBytes(imgData->format);

					if (PixelUtil::isCompressed(sourceFormat))
					{
						// Compressed data
						if (decompressDXT)
						{
							DXTColourBlock col;
							DXTInterpolatedAlphaBlock iAlpha;
							DXTExplicitAlphaBlock eAlpha;
							// 4x4 block of decompressed colour
							ColourValue tempColours[16];
							size_t destBpp = PixelUtil::getNumElemBytes(imgData->format);
							size_t sx = std::min(width, (size_t)4);
							size_t sy = std::min(height, (size_t)4);
							size_t destPitchMinus4 = dstPitch - destBpp * sx;
							// slices are done individually
							for(size_t z = 0; z < depth; ++z)
							{
								// 4x4 blocks in x/y
								for (size_t y = 0; y < height; y += 4)
								{
									for (size_t x = 0; x < width; x += 4)
									{
										if (sourceFormat == PF_DXT2 || 
											sourceFormat == PF_DXT3)
										{
											// explicit alpha
											stream->read(&eAlpha, sizeof(DXTExplicitAlphaBlock));
											flipEndian(eAlpha.alphaRow, sizeof(uint16), 4);
											unpackDXTAlpha(eAlpha, tempColours) ;
										}
										else if (sourceFormat == PF_DXT4 || 
											sourceFormat == PF_DXT5)
										{
											// interpolated alpha
											stream->read(&iAlpha, sizeof(DXTInterpolatedAlphaBlock));
											flipEndian(&(iAlpha.alpha_0), sizeof(uint16), 1);
											flipEndian(&(iAlpha.alpha_1), sizeof(uint16), 1);
											unpackDXTAlpha(iAlpha, tempColours) ;
										}
										// always read colour
										stream->read(&col, sizeof(DXTColourBlock));
										flipEndian(&(col.colour_0), sizeof(uint16), 1);
										flipEndian(&(col.colour_1), sizeof(uint16), 1);
										unpackDXTColour(sourceFormat, col, tempColours);

										// write 4x4 block to uncompressed version
										for (size_t by = 0; by < sy; ++by)
										{
											for (size_t bx = 0; bx < sx; ++bx)
											{
												PixelUtil::packColour(tempColours[by*4+bx],
													imgData->format, destPtr);
												destPtr = static_cast<void*>(
													static_cast<uchar*>(destPtr) + destBpp);
											}
											// advance to next row
											destPtr = static_cast<void*>(
												static_cast<uchar*>(destPtr) + destPitchMinus4);
										}
										// next block. Our dest pointer is 4 lines down
										// from where it started
										if (x + 4 >= width)
										{
											// Jump back to the start of the line
											destPtr = static_cast<void*>(
												static_cast<uchar*>(destPtr) - destPitchMinus4);
										}
										else
										{
											// Jump back up 4 rows and 4 pixels to the
											// right to be at the next block to the right
											destPtr = static_cast<void*>(
												static_cast<uchar*>(destPtr) - dstPitch * sy + destBpp * sx);

										}

									}

								}
							}

						}
						else
						{
							// load directly
							// DDS format lies! sizeOrPitch is not always set for DXT!!
							size_t dxtSize = PixelUtil::getMemorySize(width, height, depth, imgData->format);
							stream->read(destPtr, dxtSize);
							destPtr = static_cast<void*>(static_cast<uchar*>(destPtr) + dxtSize);
						}

					}
					else
					{
						// Final data - trim incoming pitch
						size_t srcPitch;
						if (header.flags & DDSD_PITCH)
						{
							srcPitch = header.sizeOrPitch / 
								std::max((size_t)1, mip * 2);
						}
						else
						{
							// assume same as final pitch
							srcPitch = dstPitch;
						}
						assert (dstPitch <= srcPitch);
						long srcAdvance = static_cast<long>(srcPitch) - static_cast<long>(dstPitch);

						for (size_t z = 0; z < imgData->depth; ++z)
						{
							for (size_t y = 0; y < imgData->height; ++y)
							{
								stream->read(destPtr, dstPitch);
								if (srcAdvance > 0)
									stream->skip(srcAdvance);

								destPtr = static_cast<void*>(static_cast<uchar*>(destPtr) + dstPitch);
							}
						}

					}

					
					/// 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;*/

        	return null;
		
        }