void mem_read(Stream & mem, DDSHeader & header) {
	mem_read(mem, header.fourcc);
	mem_read(mem, header.size);
	mem_read(mem, header.flags);
	mem_read(mem, header.height);
	mem_read(mem, header.width);
	mem_read(mem, header.pitch);
	mem_read(mem, header.depth);
	mem_read(mem, header.mipmapcount);
	for (uint i = 0; i < 11; i++) mem_read(mem, header.reserved[i]);
	mem_read(mem, header.pf);
	mem_read(mem, header.caps);
	mem_read(mem, header.notused);
	
	if (header.hasDX10Header()) {
		mem_read(mem, header.header10);
	}
}
Exemple #2
0
bool Compressor::Private::outputHeader(nvtt::TextureType textureType, int w, int h, int d, int mipmapCount, bool isNormalMap, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) const
{
    if (w <= 0 || h <= 0 || d <= 0 || mipmapCount <= 0)
    {
        outputOptions.error(Error_InvalidInput);
        return false;
    }

    if (!outputOptions.outputHeader)
    {
        return true;
    }

    // Output DDS header.
    if (outputOptions.container == Container_DDS || outputOptions.container == Container_DDS10)
    {
        DDSHeader header;

        header.setUserVersion(outputOptions.version);

        if (textureType == TextureType_2D) {
            header.setTexture2D();
        }
        else if (textureType == TextureType_Cube) {
            header.setTextureCube();
        }
        else if (textureType == TextureType_3D) {
            header.setTexture3D();
            header.setDepth(d);
        }

        header.setWidth(w);
        header.setHeight(h);
        header.setMipmapCount(mipmapCount);

        bool supported = true;

        if (outputOptions.container == Container_DDS10)
        {
            if (compressionOptions.format == Format_RGBA)
            {
                const uint bitcount = compressionOptions.getBitCount();

                if (bitcount == 16)
                {
                    if (compressionOptions.rsize == 16)
                    {
                        header.setDX10Format(56); // R16_UNORM
                    }
                    else
                    {
                        // B5G6R5_UNORM
                        // B5G5R5A1_UNORM
                        supported = false;
                    }
                }
                else if (bitcount == 32)
                {
                    // B8G8R8A8_UNORM
                    // B8G8R8X8_UNORM
                    // R8G8B8A8_UNORM
                    // R10G10B10A2_UNORM
                    supported = false;
                }
                else {
                    supported = false;
                }
            }
            else
            {
                if (compressionOptions.format == Format_DXT1 || compressionOptions.format == Format_DXT1a || compressionOptions.format == Format_DXT1n) {
                    header.setDX10Format(outputOptions.srgb ? DXGI_FORMAT_BC1_UNORM_SRGB : DXGI_FORMAT_BC1_UNORM);
                    if (compressionOptions.format == Format_DXT1a) header.setHasAlphaFlag(true);
                    if (isNormalMap) header.setNormalFlag(true);
                }
                else if (compressionOptions.format == Format_DXT3) {
                    header.setDX10Format(outputOptions.srgb ? DXGI_FORMAT_BC2_UNORM_SRGB : DXGI_FORMAT_BC2_UNORM);
                }
                else if (compressionOptions.format == Format_DXT5 || compressionOptions.format == Format_BC3_RGBM) {
                    header.setDX10Format(outputOptions.srgb ? DXGI_FORMAT_BC3_UNORM_SRGB : DXGI_FORMAT_BC3_UNORM);
                }
                else if (compressionOptions.format == Format_DXT5n) {
                    header.setDX10Format(DXGI_FORMAT_BC3_UNORM);
                    if (isNormalMap) header.setNormalFlag(true);
                }
                else if (compressionOptions.format == Format_BC4) {
                    header.setDX10Format(DXGI_FORMAT_BC4_UNORM); // DXGI_FORMAT_BC4_SNORM ?
                }
                else if (compressionOptions.format == Format_BC5 || compressionOptions.format == Format_BC5_Luma) {
                    header.setDX10Format(DXGI_FORMAT_BC5_UNORM); // DXGI_FORMAT_BC5_SNORM ?
                    if (isNormalMap) header.setNormalFlag(true);
                }
                else if (compressionOptions.format == Format_BC6) {
                    if (compressionOptions.pixelType == PixelType_Float) header.setDX10Format(DXGI_FORMAT_BC6H_SF16);
                    /*if (compressionOptions.pixelType == PixelType_UnsignedFloat)*/ header.setDX10Format(DXGI_FORMAT_BC6H_UF16); // By default we assume unsigned.
                }
                else if (compressionOptions.format == Format_BC7) {
                    header.setDX10Format(outputOptions.srgb ? DXGI_FORMAT_BC7_UNORM_SRGB : DXGI_FORMAT_BC7_UNORM);
                    if (isNormalMap) header.setNormalFlag(true);
                }
                else if (compressionOptions.format == Format_CTX1) {
                    supported = false;
                }
                else {
                    supported = false;
                }
            }
        }
        else
        {
            if (compressionOptions.format == Format_RGBA)
            {
                // Get output bit count.
                header.setPitch(computeBytePitch(w, compressionOptions.getBitCount(), compressionOptions.pitchAlignment));

                if (compressionOptions.pixelType == PixelType_Float)
                {
                    if (compressionOptions.rsize == 16 && compressionOptions.gsize == 0 && compressionOptions.bsize == 0 && compressionOptions.asize == 0)
                    {
                        header.setFormatCode(111); // D3DFMT_R16F
                    }
                    else if (compressionOptions.rsize == 16 && compressionOptions.gsize == 16 && compressionOptions.bsize == 0 && compressionOptions.asize == 0)
                    {
                        header.setFormatCode(112); // D3DFMT_G16R16F
                    }
                    else if (compressionOptions.rsize == 16 && compressionOptions.gsize == 16 && compressionOptions.bsize == 16 && compressionOptions.asize == 16)
                    {
                        header.setFormatCode(113); // D3DFMT_A16B16G16R16F
                    }
                    else if (compressionOptions.rsize == 32 && compressionOptions.gsize == 0 && compressionOptions.bsize == 0 && compressionOptions.asize == 0)
                    {
                        header.setFormatCode(114); // D3DFMT_R32F
                    }
                    else if (compressionOptions.rsize == 32 && compressionOptions.gsize == 32 && compressionOptions.bsize == 0 && compressionOptions.asize == 0)
                    {
                        header.setFormatCode(115); // D3DFMT_G32R32F
                    }
                    else if (compressionOptions.rsize == 32 && compressionOptions.gsize == 32 && compressionOptions.bsize == 32 && compressionOptions.asize == 32)
                    {
                        header.setFormatCode(116); // D3DFMT_A32B32G32R32F
                    }
                    else
                    {
                        supported = false;
                    }
                }
                else // Fixed point
                {
                    const uint bitcount = compressionOptions.getBitCount();

                    if (compressionOptions.bitcount != 0)
                    {
                        // Masks already computed.
                        header.setPixelFormat(compressionOptions.bitcount, compressionOptions.rmask, compressionOptions.gmask, compressionOptions.bmask, compressionOptions.amask);
                    }
                    else if (bitcount <= 32)
                    {
                        // Compute pixel format masks.
                        const uint ashift = 0;
                        const uint bshift = ashift + compressionOptions.asize;
                        const uint gshift = bshift + compressionOptions.bsize;
                        const uint rshift = gshift + compressionOptions.gsize;

                        const uint rmask = ((1 << compressionOptions.rsize) - 1) << rshift;
                        const uint gmask = ((1 << compressionOptions.gsize) - 1) << gshift;
                        const uint bmask = ((1 << compressionOptions.bsize) - 1) << bshift;
                        const uint amask = ((1 << compressionOptions.asize) - 1) << ashift;

                        header.setPixelFormat(bitcount, rmask, gmask, bmask, amask);
                    }
                    else
                    {
                        supported = false;
                    }
                }
            }
            else
            {
                header.setLinearSize(computeImageSize(w, h, d, compressionOptions.bitcount, compressionOptions.pitchAlignment, compressionOptions.format));

                if (compressionOptions.format == Format_DXT1 || compressionOptions.format == Format_DXT1a || compressionOptions.format == Format_DXT1n) {
                    header.setFourCC('D', 'X', 'T', '1');
                    if (isNormalMap) header.setNormalFlag(true);
                }
                else if (compressionOptions.format == Format_DXT3) {
                    header.setFourCC('D', 'X', 'T', '3');
                }
                else if (compressionOptions.format == Format_DXT5 || compressionOptions.format == Format_BC3_RGBM) {
                    header.setFourCC('D', 'X', 'T', '5');
                }
                else if (compressionOptions.format == Format_DXT5n) {
                    header.setFourCC('D', 'X', 'T', '5');
                    if (isNormalMap) {
                        header.setNormalFlag(true);
                        header.setSwizzleCode('A', '2', 'D', '5');
                        //header.setSwizzleCode('x', 'G', 'x', 'R');
                    }
                }
                else if (compressionOptions.format == Format_BC4) {
                    header.setFourCC('A', 'T', 'I', '1');
                }
                else if (compressionOptions.format == Format_BC5 || compressionOptions.format == Format_BC5_Luma) {
                    header.setFourCC('A', 'T', 'I', '2');
                    if (isNormalMap) {
                        header.setNormalFlag(true);
                        header.setSwizzleCode('A', '2', 'X', 'Y');
                    }
                }
                else if (compressionOptions.format == Format_BC6) {
                    header.setFourCC('Z', 'O', 'H', ' ');               // This is not supported by D3DX. Always use DX10 header with BC6-7 formats.
                    supported = false;
                }
                else if (compressionOptions.format == Format_BC7) {
                    header.setFourCC('Z', 'O', 'L', 'A');               // This is not supported by D3DX. Always use DX10 header with BC6-7 formats.
                    if (isNormalMap) header.setNormalFlag(true);
                    supported = false;
                }
                else if (compressionOptions.format == Format_CTX1) {
                    header.setFourCC('C', 'T', 'X', '1');
                    if (isNormalMap) header.setNormalFlag(true);
                }
                else {
                    supported = false;
                }
            }

            if (outputOptions.srgb) header.setSrgbFlag(true);
        }

        if (!supported)
        {
            // This container does not support the requested format.
            outputOptions.error(Error_UnsupportedOutputFormat);
            return false;
        }

        uint headerSize = 128;
        if (header.hasDX10Header())
        {
            nvStaticCheck(sizeof(DDSHeader) == 128 + 20);
            headerSize = 128 + 20;
        }

        // Swap bytes if necessary.
        header.swapBytes();

        bool writeSucceed = outputOptions.writeData(&header, headerSize);
        if (!writeSucceed)
        {
            outputOptions.error(Error_FileWrite);
        }

        return writeSucceed;
    }

    return true;
}
unsigned int Decompressor::Private::getHeader(void* buffer, const unsigned int bufferSize, const InputOptions::Private & inputOptions, const CompressionOptions::Private & compressionOptions)
{
	if( bufferSize < DECOMPRESSOR_MIN_HEADER_SIZE )
	{
		return 0;
	}

	DDSHeader header;

	inputOptions.computeTargetExtents();

	header.setWidth(inputOptions.targetWidth);
	header.setHeight(inputOptions.targetHeight);

	int mipmapCount = inputOptions.realMipmapCount();
	nvDebugCheck(mipmapCount > 0);

	header.setMipmapCount(mipmapCount);

	if (inputOptions.textureType == TextureType_2D) {
		header.setTexture2D();
	}
	else if (inputOptions.textureType == TextureType_Cube) {
		header.setTextureCube();
	}		

	uint p = inputOptions.targetWidth * ((compressionOptions.bitcount + 7) / 8);
		// Align to 32 bits.
	uint pitch = ((p + 3) / 4) * 4;

	if (compressionOptions.format == Format_RGBA)
	{
		
		header.setPitch(pitch);
		header.setPixelFormat(compressionOptions.bitcount, compressionOptions.rmask, compressionOptions.gmask, compressionOptions.bmask, compressionOptions.amask);
	}
	else
	{
		
		uint lineralSize = 0;
		if (compressionOptions.format == Format_RGBA)
		{
			lineralSize = inputOptions.targetDepth * inputOptions.targetHeight * pitch;
		}
		else 
		{
			uint blockSize = 0;
			if (compressionOptions.format == Format_DXT1 || compressionOptions.format == Format_DXT1a || compressionOptions.format == Format_BC4) 
			{
				blockSize = 8;
			}
			else 
			{
				blockSize = 16;
			}
			

			lineralSize = ((inputOptions.targetWidth + 3) / 4) * ((inputOptions.targetHeight + 3) / 4) * blockSize;
		}

		header.setLinearSize(lineralSize);

		if (compressionOptions.format == Format_DXT1 || compressionOptions.format == Format_DXT1a) {
			header.setFourCC('D', 'X', 'T', '1');
			if (inputOptions.isNormalMap) header.setNormalFlag(true);
		}
		else if (compressionOptions.format == Format_DXT3) {
			header.setFourCC('D', 'X', 'T', '3');
		}
		else if (compressionOptions.format == Format_DXT5) {
			header.setFourCC('D', 'X', 'T', '5');
		}
		else if (compressionOptions.format == Format_DXT5n) {
			header.setFourCC('D', 'X', 'T', '5');
			if (inputOptions.isNormalMap) header.setNormalFlag(true);
		}
		else if (compressionOptions.format == Format_BC4) {
			header.setFourCC('A', 'T', 'I', '1');
		}
		else if (compressionOptions.format == Format_BC5) {
			header.setFourCC('A', 'T', 'I', '2');
			if (inputOptions.isNormalMap) header.setNormalFlag(true);
		}
		else if (compressionOptions.format == Format_ATC_RGB) {
			header.setFourCC('A', 'T', 'C', ' ');
		}
		else if (compressionOptions.format == Format_ATC_RGBA_EXPLICIT_ALPHA) {
			header.setFourCC('A', 'T', 'C', 'I');
		}
		else if (compressionOptions.format == Format_ATC_RGBA_INTERPOLATED_ALPHA) {
			header.setFourCC('A', 'T', 'C', 'A');
		}
	}

	// Swap bytes if necessary.
	header.swapBytes();

	uint headerSize = 128;
	if (header.hasDX10Header())
	{
		nvStaticCheck(sizeof(DDSHeader) == 128 + 20);
		headerSize = 128 + 20;
	}

	
	memcpy( buffer, &header, headerSize);
	return headerSize;
}
Exemple #4
0
// Output DDS header.
bool Compressor::Private::outputHeader(const InputOptions::Private & inputOptions, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) const
{
	// Output DDS header.
	if (outputOptions.outputHandler == NULL || !outputOptions.outputHeader)
	{
		return true;
	}

	DDSHeader header;

	header.setWidth(inputOptions.targetWidth);
	header.setHeight(inputOptions.targetHeight);

	int mipmapCount = inputOptions.realMipmapCount();
	nvDebugCheck(mipmapCount > 0);

	header.setMipmapCount(mipmapCount);

	if (inputOptions.textureType == TextureType_2D) {
		header.setTexture2D();
	}
	else if (inputOptions.textureType == TextureType_Cube) {
		header.setTextureCube();
	}		
	/*else if (inputOptions.textureType == TextureType_3D) {
	header.setTexture3D();
	header.setDepth(inputOptions.targetDepth);
	}*/

	if (compressionOptions.format == Format_RGBA)
	{
		header.setPitch(computePitch(inputOptions.targetWidth, compressionOptions.bitcount));
		header.setPixelFormat(compressionOptions.bitcount, compressionOptions.rmask, compressionOptions.gmask, compressionOptions.bmask, compressionOptions.amask);
	}
	else
	{
		header.setLinearSize(computeImageSize(inputOptions.targetWidth, inputOptions.targetHeight, inputOptions.targetDepth, compressionOptions.bitcount, compressionOptions.format));

		if (compressionOptions.format == Format_DXT1 || compressionOptions.format == Format_DXT1a) {
			header.setFourCC('D', 'X', 'T', '1');
			if (inputOptions.isNormalMap) header.setNormalFlag(true);
		}
		else if (compressionOptions.format == Format_DXT3) {
			header.setFourCC('D', 'X', 'T', '3');
		}
		else if (compressionOptions.format == Format_DXT5) {
			header.setFourCC('D', 'X', 'T', '5');
		}
		else if (compressionOptions.format == Format_DXT5n) {
			header.setFourCC('D', 'X', 'T', '5');
			if (inputOptions.isNormalMap) header.setNormalFlag(true);
		}
		else if (compressionOptions.format == Format_BC4) {
			header.setFourCC('A', 'T', 'I', '1');
		}
		else if (compressionOptions.format == Format_BC5) {
			header.setFourCC('A', 'T', 'I', '2');
			if (inputOptions.isNormalMap) header.setNormalFlag(true);
		}
	}

	// Swap bytes if necessary.
	header.swapBytes();

	uint headerSize = 128;
	if (header.hasDX10Header())
	{
		nvStaticCheck(sizeof(DDSHeader) == 128 + 20);
		headerSize = 128 + 20;
	}

	bool writeSucceed = outputOptions.outputHandler->writeData(&header, headerSize);
	if (!writeSucceed && outputOptions.errorHandler != NULL)
	{
		outputOptions.errorHandler->error(Error_FileWrite);
	}

	return writeSucceed;
}