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