//! Compresses data to a DXT format using nVidia's Texture Tools library. // The data must be in unsigned byte RGBA format. The alpha channel will be ignored if DxtType is IL_DXT1. // DxtSize is used to return the size in bytes of the DXTC data returned. ILAPI ILubyte* ILAPIENTRY ilNVidiaCompressDXT(ILubyte *Data, ILuint Width, ILuint Height, ILuint Depth, ILenum DxtFormat, ILuint *DxtSize) { if (Data == NULL) { // We cannot operate on a null pointer. ilSetError(IL_INVALID_PARAM); return NULL; } // The nVidia Texture Tools library does not support volume textures yet. if (Depth != 1) { ilSetError(IL_INVALID_PARAM); return NULL; } InputOptions inputOptions; inputOptions.setTextureLayout(TextureType_2D, Width, Height); inputOptions.setMipmapData(Data, Width, Height); inputOptions.setMipmapGeneration(false, -1); //@TODO: Use this in certain cases. OutputOptions outputOptions; ilOutputHandlerMem outputHandler(Width, Height, DxtFormat); outputOptions.setOutputHeader(false); outputOptions.setOutputHandler(&outputHandler); if (outputHandler.NewData == NULL) return NULL; CompressionOptions compressionOptions; switch (DxtFormat) { case IL_DXT1: compressionOptions.setFormat(Format_DXT1); break; case IL_DXT1A: compressionOptions.setFormat(Format_DXT1a); break; case IL_DXT3: compressionOptions.setFormat(Format_DXT1); break; case IL_DXT5: compressionOptions.setFormat(Format_DXT5); break; default: // Does not support DXT2 or DXT4. ilSetError(IL_INVALID_PARAM); break; } Compressor compressor; compressor.process(inputOptions, compressionOptions, outputOptions); *DxtSize = outputHandler.Size; return outputHandler.NewData; }
bool LibDxtHelper::DecompressImageToRGBA(const Image & image, Vector<Image*> &imageSet, bool forseSoftwareConvertation) { if(!(image.format >= FORMAT_DXT1 && image.format <= FORMAT_DXT5NM) ) { Logger::Error("[LibDxtHelper::DecompressImageToRGBA] Wrong copression format (%d).", image.format); return false; } nvtt::Format innerComprFormat = NvttHelper::GetNVTTFormatByPixelFormat(image.format); if(nvtt::Format_BC5 == innerComprFormat) { //bc5 is unsupported, used to determinate fail in search Logger::Error("[LibDxtHelper::DecompressImageToRGBA] Can't work with nvtt::Format_BC5."); return false; } InputOptions inputOptions; inputOptions.setTextureLayout(TextureType_2D, image.width, image.height); inputOptions.setMipmapGeneration(false); CompressionOptions compressionOptions; compressionOptions.setFormat(innerComprFormat); if(FORMAT_DXT1NM == image.format) { compressionOptions.setColorWeights(1, 1, 0); } else if (FORMAT_DXT5NM == image.format) { inputOptions.setNormalMap(true); } uint32 headerSize = DX10HEADER_SIZE; uint8* imageHeaderBuffer = new uint8[headerSize]; uint32 realHeaderSize = nvtt::Decompressor::getHeader(imageHeaderBuffer, headerSize, inputOptions, compressionOptions); nvtt::Decompressor dec; uint8* compressedImageBuffer = new uint8[realHeaderSize + image.dataSize]; memcpy(compressedImageBuffer, imageHeaderBuffer, realHeaderSize); memcpy(compressedImageBuffer + realHeaderSize, image.data, image.dataSize); SafeDeleteArray(imageHeaderBuffer); bool retValue = NvttHelper::InitDecompressor(dec, compressedImageBuffer, realHeaderSize + image.dataSize); if(retValue) { retValue = NvttHelper::ReadDxtFile(dec, imageSet, forseSoftwareConvertation); } SafeDeleteArray(compressedImageBuffer); return retValue; }
//! Compresses data to a DXT format using nVidia's Texture Tools library. // This version is supposed to be completely internal to DevIL. // The data must be in unsigned byte RGBA format. The alpha channel will be ignored if DxtType is IL_DXT1. ILuint ilNVidiaCompressDXTFile(ILubyte *Data, ILuint Width, ILuint Height, ILuint Depth, ILenum DxtFormat) { ILuint FilePos = itellw(); // The nVidia Texture Tools library does not support volume textures yet. if (Depth != 1) { ilSetError(IL_INVALID_PARAM); return 0; } InputOptions inputOptions; inputOptions.setTextureLayout(TextureType_2D, Width, Height); inputOptions.setMipmapData(Data, Width, Height); inputOptions.setMipmapGeneration(false, -1); //@TODO: Use this in certain cases. OutputOptions outputOptions; ilOutputHandlerFile outputHandler(Width, Height, DxtFormat); outputOptions.setOutputHeader(false); outputOptions.setOutputHandler(&outputHandler); CompressionOptions compressionOptions; switch (DxtFormat) { case IL_DXT1: compressionOptions.setFormat(Format_DXT1); break; case IL_DXT1A: compressionOptions.setFormat(Format_DXT1a); break; case IL_DXT3: compressionOptions.setFormat(Format_DXT1); break; case IL_DXT5: compressionOptions.setFormat(Format_DXT5); break; default: // Does not support DXT2 or DXT4. ilSetError(IL_INVALID_PARAM); break; } Compressor compressor; compressor.process(inputOptions, compressionOptions, outputOptions); return itellw() - FilePos; // Return the number of characters written. }
bool LibArchiveInterface::addFiles(const QStringList& files, const CompressionOptions& options) { const bool creatingNewFile = !QFileInfo(filename()).exists(); const QString tempFilename = filename() + QLatin1String( ".arkWriting" ); const QString globalWorkDir = options.value(QLatin1String( "GlobalWorkDir" )).toString(); if (!globalWorkDir.isEmpty()) { kDebug() << "GlobalWorkDir is set, changing dir to " << globalWorkDir; m_workDir.setPath(globalWorkDir); QDir::setCurrent(globalWorkDir); } m_writtenFiles.clear(); ArchiveRead arch_reader; if (!creatingNewFile) { arch_reader.reset(archive_read_new()); if (!(arch_reader.data())) { emit error(i18n("The archive reader could not be initialized.")); return false; } if (archive_read_support_compression_all(arch_reader.data()) != ARCHIVE_OK) { return false; } if (archive_read_support_format_all(arch_reader.data()) != ARCHIVE_OK) { return false; } if (archive_read_open_filename(arch_reader.data(), QFile::encodeName(filename()), 10240) != ARCHIVE_OK) { emit error(i18n("The source file could not be read.")); return false; } } ArchiveWrite arch_writer(archive_write_new()); if (!(arch_writer.data())) { emit error(i18n("The archive writer could not be initialized.")); return false; } //pax_restricted is the libarchive default, let's go with that. archive_write_set_format_pax_restricted(arch_writer.data()); int ret; if (creatingNewFile) { if (filename().right(2).toUpper() == QLatin1String( "GZ" )) { kDebug() << "Detected gzip compression for new file"; ret = archive_write_set_compression_gzip(arch_writer.data()); } else if (filename().right(3).toUpper() == QLatin1String( "BZ2" )) { kDebug() << "Detected bzip2 compression for new file"; ret = archive_write_set_compression_bzip2(arch_writer.data()); #ifdef HAVE_LIBARCHIVE_XZ_SUPPORT } else if (filename().right(2).toUpper() == QLatin1String( "XZ" )) { kDebug() << "Detected xz compression for new file"; ret = archive_write_set_compression_xz(arch_writer.data()); #endif #ifdef HAVE_LIBARCHIVE_LZMA_SUPPORT } else if (filename().right(4).toUpper() == QLatin1String( "LZMA" )) { kDebug() << "Detected lzma compression for new file"; ret = archive_write_set_compression_lzma(arch_writer.data()); #endif } else if (filename().right(3).toUpper() == QLatin1String( "TAR" )) { kDebug() << "Detected no compression for new file (pure tar)"; ret = archive_write_set_compression_none(arch_writer.data()); } else { kDebug() << "Falling back to gzip"; ret = archive_write_set_compression_gzip(arch_writer.data()); } if (ret != ARCHIVE_OK) { emit error(i18nc("@info", "Setting the compression method failed with the following error: <message>%1</message>", QLatin1String(archive_error_string(arch_writer.data())))); return false; } } else { switch (archive_compression(arch_reader.data())) { case ARCHIVE_COMPRESSION_GZIP: ret = archive_write_set_compression_gzip(arch_writer.data()); break; case ARCHIVE_COMPRESSION_BZIP2: ret = archive_write_set_compression_bzip2(arch_writer.data()); break; #ifdef HAVE_LIBARCHIVE_XZ_SUPPORT case ARCHIVE_COMPRESSION_XZ: ret = archive_write_set_compression_xz(arch_writer.data()); break; #endif #ifdef HAVE_LIBARCHIVE_LZMA_SUPPORT case ARCHIVE_COMPRESSION_LZMA: ret = archive_write_set_compression_lzma(arch_writer.data()); break; #endif case ARCHIVE_COMPRESSION_NONE: ret = archive_write_set_compression_none(arch_writer.data()); break; default: emit error(i18n("The compression type '%1' is not supported by Ark.", QLatin1String(archive_compression_name(arch_reader.data())))); return false; } if (ret != ARCHIVE_OK) { emit error(i18nc("@info", "Setting the compression method failed with the following error: <message>%1</message>", QLatin1String(archive_error_string(arch_writer.data())))); return false; } } ret = archive_write_open_filename(arch_writer.data(), QFile::encodeName(tempFilename)); if (ret != ARCHIVE_OK) { emit error(i18nc("@info", "Opening the archive for writing failed with the following error: <message>%1</message>", QLatin1String(archive_error_string(arch_writer.data())))); return false; } //**************** first write the new files foreach(const QString& selectedFile, files) { bool success; success = writeFile(selectedFile, arch_writer.data()); if (!success) { QFile::remove(tempFilename); return false; } if (QFileInfo(selectedFile).isDir()) { QDirIterator it(selectedFile, QDir::AllEntries | QDir::Readable | QDir::Hidden | QDir::NoDotAndDotDot, QDirIterator::Subdirectories); while (it.hasNext()) { const QString path = it.next(); if ((it.fileName() == QLatin1String("..")) || (it.fileName() == QLatin1String("."))) { continue; } const bool isRealDir = it.fileInfo().isDir() && !it.fileInfo().isSymLink(); success = writeFile(path + (isRealDir ? QLatin1String( "/" ) : QLatin1String( "" )), arch_writer.data()); if (!success) { QFile::remove(tempFilename); return false; } } } }
bool LibDxtHelper::WriteDxtFile(const String & fileNameOriginal, int32 width, int32 height, uint8 * data, PixelFormat compressionFormat, bool generateMipmaps) { if(!( (compressionFormat >= FORMAT_DXT1 && compressionFormat <= FORMAT_DXT5NM)|| (compressionFormat == FORMAT_RGBA8888)) ) { Logger::Error("[LibDxtHelper::WriteDxtFile] Wrong copression format (%d).", compressionFormat); return false; } //creating tmp dds file, nvtt accept only filename.dds as input, because of this the last letter befor "." should be changed to "_". String extension = FileSystem::Instance()->GetExtension(fileNameOriginal); if(0 != CompareCaseInsensitive(extension, ".dds")) { Logger::Error("[LibDxtHelper::WriteDxtFile] Wrong input file name (%s).", fileNameOriginal.c_str()); return false; } nvtt::Format innerComprFormat = NvttHelper::GetNVTTFormatByPixelFormat(compressionFormat); if(nvtt::Format_BC5 == innerComprFormat) { //bc5 is unsupported, used to determinate fail in search Logger::Error("[LibDxtHelper::WriteDxtFile] Can't work with nvtt::Format_BC5."); return false; } uint32 imgDataSize = width * height * Texture::GetPixelFormatSizeInBytes(FORMAT_RGBA8888); NvttHelper::SwapBRChannels(data, imgDataSize); InputOptions inputOptions; inputOptions.setTextureLayout(TextureType_2D, width, height); inputOptions.setMipmapGeneration(generateMipmaps); inputOptions.setMipmapData(data, width, height); CompressionOptions compressionOptions; compressionOptions.setFormat(innerComprFormat); if(FORMAT_DXT1NM == compressionFormat) { compressionOptions.setColorWeights(1, 1, 0); } else if (FORMAT_DXT5NM == compressionFormat) { inputOptions.setNormalMap(true); } OutputOptions outputOptions; String fileName = FileSystem::Instance()->ReplaceExtension(fileNameOriginal, "_dds"); outputOptions.setFileName(fileName.c_str()); Compressor compressor; bool ret = compressor.process(inputOptions, compressionOptions, outputOptions); if(ret) { FileSystem::Instance()->DeleteFile(fileNameOriginal); if(!FileSystem::Instance()->MoveFile(fileName, fileNameOriginal, true)) { Logger::Error("[LibDxtHelper::WriteDxtFile] Temporary dds file renamig failed."); ret = false; } } else { Logger::Error("[LibDxtHelper::WriteDxtFile] Error during writing DDS file (%s).", fileName.c_str()); } return ret; }