diff --git a/Source/Main.cpp b/Source/Main.cpp index c548684..7e0a646 100644 --- a/Source/Main.cpp +++ b/Source/Main.cpp @@ -41,20 +41,20 @@ const std::map> formats = {"BC7_SRGB", {"8 bit RGBA - Good general purpose. 16 bytes per block.", 16, vk::Format::eBc7SrgbBlock}} }; -const std::string usage = "[cube|array] [input2, input3...] [fast|normal|slow|veryslow] [explicitmips]"; +const std::string usage = "[cube|array] [input2, input3...] [fast|normal|slow|veryslow]"; int main(int argc, char ** argv) { ISPCInit(); if (argc < 4) { - std::cerr << "Usage: " << argv[0] << " " << usage << std::endl; - std::cerr << "Formats:" << std::endl; + std::cout << "Usage: " << argv[0] << " " << usage << std::endl; + std::cout << "Formats:" << std::endl; for (auto & formatName : formatOrder) { auto format = formats.at(formatName); - std::cerr << " " << formatName << " - " << std::get<0>(format) << std::endl; + std::cout << " " << formatName << " - " << std::get<0>(format) << std::endl; } - return -1; + return 1; } int numInputs = argc - 3; @@ -72,20 +72,10 @@ int main(int argc, char ** argv) std::string speedString(argv[argc - 1]); std::string formatString; int speed = 2; - bool explicitmips = false; - - int formatPosition = -1; - - if (speedString == "explicitmips") { - speedString = std::string(argv[argc - 2]); - numInputs -= 1; - formatPosition -= 1; - explicitmips = true; - } if (speedString == "fast" || speedString == "normal" || speedString == "slow" || speedString == "veryslow") { + formatString = std::string(argv[argc - 2]); numInputs -= 1; - formatPosition -= 1; if (speedString == "slow") { speed = 1; @@ -96,41 +86,29 @@ int main(int argc, char ** argv) } else { speed = 2; } + } else { + formatString = std::string(argv[argc - 1]); } - formatString = std::string(argv[argc + formatPosition]); - if (numInputs < 1) { - std::cerr << "Usage: " << argv[0] << usage << " " << std::endl; - return -1; + std::cout << "Usage: " << argv[0] << usage << " " << std::endl; + return 1; } - if (explicitmips) { - if (option == "cube" && numInputs % 6 != 0) { - std::cerr << "Cube maps must have a multiple of 6 inputs." << std::endl; - return -1; - } - } else { - if (option == "cube" && numInputs != 6) { - std::cerr << "Cube maps must have 6 inputs." << std::endl; - return -1; - } + if (option == "cube" && numInputs != 6) { + std::cout << "Cube maps must have 6 inputs." << std::endl; + return 1; } if (option == "array" && numInputs < 2) { - std::cerr << "Array maps must have at least 2 inputs." << std::endl; - return -1; - } - - if (option == "array" && explicitmips) { - std::cerr << "Explicit mips are not supported for arrays." << std::endl; - return -1; + std::cout << "Array maps must have at least 2 inputs." << std::endl; + return 1; } if (formats.find(formatString) == formats.end()) { - std::cerr << "Invalid format: " << formatString << std::endl; - std::cerr << usage << std::endl; - std::cerr << "Formats:" << std::endl; + std::cout << "Invalid format: " << formatString << std::endl; + std::cout << usage << std::endl; + std::cout << "Formats:" << std::endl; for (auto & formatName : formatOrder) { auto format = formats.at(formatName); std::cout << " " << formatName << " - " << std::get<0>(format) << std::endl; @@ -210,142 +188,94 @@ int main(int argc, char ** argv) ldrLevelBlocks.resize(numInputs); } - unsigned int levelCount; - int numFaces = 1; + uint32_t levelCount; - int topLevelWidth, topLevelHeight; + for (int input = 0; input < numInputs; input++) { + int level = 0; - if (option == "cube") { - numFaces = 6; - } + std::cout << "Loading/scaling " << input << ": " << inputs[input] << std::endl; - if (explicitmips) { - levelCount = numInputs / numFaces; - - for (int face = 0; face < numFaces; face++) { - int levelWidth = 0, levelHeight = 0; - - for (unsigned int level = 0; level < levelCount; level++) { - std::cout << "Loading/scaling face " << face << ", level " << level << ", " << inputs[face * levelCount + level] << std::endl; - - if (hdr) { - hdrBufferA = stbi_loadf(inputs[face * levelCount + level].c_str(), &width, &height, &channels, forcedChannels); - } else { - ldrBufferA = stbi_load(inputs[face * levelCount + level].c_str(), &width, &height, &channels, forcedChannels); - } - - if (level == 0) { - levelWidth = width; - levelHeight = height; - topLevelWidth = width; - topLevelHeight = height; - } else { - if (width != levelWidth || height != levelHeight) { - std::cout << "Input " << inputs[face * levelCount + level] << " for face " << face << ", level " << level << "dimensions " << width << "x" << height << " do not match expected " << levelWidth << "x" << levelHeight << std::endl; - return -1; - } - } - - if (hdr) { - hdrLevels[face].push_back(std::vector(hdrBufferA, hdrBufferA + width * height * forcedChannels)); - stbi_image_free(hdrBufferA); - } else { - ldrLevels[face].push_back(std::vector(ldrBufferA, ldrBufferA + width * height * forcedChannels)); - stbi_image_free(ldrBufferA); - } - - levelWidth = std::max(1, (int)floorf((float)levelWidth / 2)); - levelHeight = std::max(1, (int)floorf((float)levelHeight / 2)); + if (hdr) { + hdrBufferA = stbi_loadf(inputs[input].c_str(), &width, &height, &channels, forcedChannels); + if (hdrBufferA == nullptr) { + std::cout << "Failed to load image: " << inputs[input] << std::endl; + return 1; } + + hdrBufferB = new float[width * height * forcedChannels]; + hdrBufferMain = hdrBufferA; + hdrBufferOther = hdrBufferB; + } else { + ldrBufferA = stbi_load(inputs[input].c_str(), &width, &height, &channels, forcedChannels); + if (ldrBufferA == nullptr) { + std::cout << "Failed to load image: " << inputs[input] << std::endl; + return 1; + } + + ldrBufferB = new unsigned char[width * height * forcedChannels]; + ldrBufferMain = ldrBufferA; + ldrBufferOther = ldrBufferB; } - width = topLevelWidth; - height = topLevelHeight; - } else { - for (int input = 0; input < numInputs; input++) { - int level = 0; + int oldWidth = width; + int oldHeight = height; - std::cout << "Loading/scaling " << input << ": " << inputs[input] << std::endl; + levelCount = 1; + { + int levelWidth = width; + int levelHeight = height; + while (levelWidth > 1 || levelHeight > 1) { + levelWidth = std::max(1, (int)floorf((float)levelWidth / 2)); + levelHeight = std::max(1, (int)floorf((float)levelHeight / 2)); + levelCount++; + } + } + + while(1) { + if (hdr) { + hdrLevels[input].push_back(std::vector(hdrBufferMain, hdrBufferMain + oldWidth * oldHeight * forcedChannels)); + } else { + ldrLevels[input].push_back(std::vector(ldrBufferMain, ldrBufferMain + oldWidth * oldHeight * forcedChannels)); + } + + if (oldWidth == 1 && oldHeight == 1) { + break; + } + + int newWidth = std::max(1, (int)floorf((float)oldWidth / 2)); + int newHeight = std::max(1, (int)floorf((float)oldHeight / 2)); + + stbir_colorspace colorspace = srgb ? STBIR_COLORSPACE_SRGB : STBIR_COLORSPACE_LINEAR; + int alphaChannel = channels == 4 ? 3 : STBIR_ALPHA_CHANNEL_NONE; if (hdr) { - hdrBufferA = stbi_loadf(inputs[input].c_str(), &width, &height, &channels, forcedChannels); - if (hdrBufferA == nullptr) { - std::cout << "Failed to load image: " << inputs[input] << std::endl; - return 1; + int rv = stbir_resize_float_generic(hdrBufferMain, oldWidth, oldHeight, 0, hdrBufferOther, newWidth, newHeight, 0, forcedChannels, alphaChannel, 0, STBIR_EDGE_CLAMP, STBIR_FILTER_MITCHELL, colorspace, nullptr); + if (rv != 1) { + std::cerr << "Error resizing" << std::endl; } - - hdrBufferB = new float[width * height * forcedChannels]; - hdrBufferMain = hdrBufferA; - hdrBufferOther = hdrBufferB; + std::swap(hdrBufferMain, hdrBufferOther); } else { - ldrBufferA = stbi_load(inputs[input].c_str(), &width, &height, &channels, forcedChannels); - if (ldrBufferA == nullptr) { - std::cout << "Failed to load image: " << inputs[input] << std::endl; - return 1; + int rv = stbir_resize_uint8_generic(ldrBufferMain, oldWidth, oldHeight, 0, ldrBufferOther, newWidth, newHeight, 0, forcedChannels, alphaChannel, 0, STBIR_EDGE_CLAMP, STBIR_FILTER_MITCHELL, colorspace, nullptr); + if (rv != 1) { + std::cerr << "Error resizing" << std::endl; } - - ldrBufferB = new unsigned char[width * height * forcedChannels]; - ldrBufferMain = ldrBufferA; - ldrBufferOther = ldrBufferB; + std::swap(ldrBufferMain, ldrBufferOther); } - int oldWidth = width; - int oldHeight = height; + oldWidth = newWidth; + oldHeight = newHeight; + level++; + } - levelCount = 1; - { - int levelWidth = width; - int levelHeight = height; - while (levelWidth > 1 || levelHeight > 1) { - levelWidth = std::max(1, (int)floorf((float)levelWidth / 2)); - levelHeight = std::max(1, (int)floorf((float)levelHeight / 2)); - levelCount++; - } - } - - while(1) { - if (hdr) { - hdrLevels[input].push_back(std::vector(hdrBufferMain, hdrBufferMain + oldWidth * oldHeight * forcedChannels)); - } else { - ldrLevels[input].push_back(std::vector(ldrBufferMain, ldrBufferMain + oldWidth * oldHeight * forcedChannels)); - } - - if (oldWidth == 1 && oldHeight == 1) { - break; - } - - int newWidth = std::max(1, (int)floorf((float)oldWidth / 2)); - int newHeight = std::max(1, (int)floorf((float)oldHeight / 2)); - - stbir_colorspace colorspace = srgb ? STBIR_COLORSPACE_SRGB : STBIR_COLORSPACE_LINEAR; - int alphaChannel = channels == 4 ? 3 : STBIR_ALPHA_CHANNEL_NONE; - - if (hdr) { - int rv = stbir_resize_float_generic(hdrBufferMain, oldWidth, oldHeight, 0, hdrBufferOther, newWidth, newHeight, 0, forcedChannels, alphaChannel, 0, STBIR_EDGE_CLAMP, STBIR_FILTER_MITCHELL, colorspace, nullptr); - if (rv != 1) { - std::cerr << "Error resizing" << std::endl; - } - std::swap(hdrBufferMain, hdrBufferOther); - } else { - int rv = stbir_resize_uint8_generic(ldrBufferMain, oldWidth, oldHeight, 0, ldrBufferOther, newWidth, newHeight, 0, forcedChannels, alphaChannel, 0, STBIR_EDGE_CLAMP, STBIR_FILTER_MITCHELL, colorspace, nullptr); - if (rv != 1) { - std::cerr << "Error resizing" << std::endl; - } - std::swap(ldrBufferMain, ldrBufferOther); - } - - oldWidth = newWidth; - oldHeight = newHeight; - level++; - } - - if (hdr) { - free(hdrBufferA); - delete[] hdrBufferB; - } else { - free(ldrBufferA); - delete[] ldrBufferB; - } + oldWidth = width; + oldHeight = height; + level = 0; + if (hdr) { + free(hdrBufferA); + delete[] hdrBufferB; + } else { + free(ldrBufferA); + delete[] ldrBufferB; } } @@ -386,19 +316,19 @@ int main(int argc, char ** argv) std::tuple format = formats.find(formatString)->second; size_t blockSize = std::get<1>(format); - for (int face = 0; face < numFaces; face++) { + for (int input = 0; input < numInputs; input++) { if (numInputs > 1) { if (option == "cube") { - std::cout << "Face " << face << std::endl; + std::cout << "Face " << input << std::endl; } else { - std::cout << "Layer " << face << std::endl; + std::cout << "Layer " << input << std::endl; } } if (hdr) { - hdrLevelBlocks[face].resize(levelCount); + hdrLevelBlocks[input].resize(levelCount); } else { - ldrLevelBlocks[face].resize(levelCount); + ldrLevelBlocks[input].resize(levelCount); } int level = 0; @@ -410,7 +340,7 @@ int main(int argc, char ** argv) unsigned int blocksHeight = (oldHeight + 3) / 4; if (hdr) { - hdrLevelBlocks[face][level].resize(blocksWidth * blocksHeight); + hdrLevelBlocks[input][level].resize(blocksWidth * blocksHeight); for (unsigned int y = 0; y < blocksHeight; y++) { for (unsigned int x = 0; x < blocksWidth; x++) { @@ -422,7 +352,7 @@ int main(int argc, char ** argv) unsigned int clampedX = std::min(pixelX, (unsigned int)oldWidth - 1); for (int channel = 0; channel < copyChannels; channel++) { - float value = hdrLevels[face][level][(clampedY * oldWidth + clampedX) * forcedChannels + channel]; + float value = hdrLevels[input][level][(clampedY * oldWidth + clampedX) * forcedChannels + channel]; if (value < 0.0f) { value = 0.0f; } @@ -436,11 +366,11 @@ int main(int argc, char ** argv) } } - hdrLevelBlocks[face][level][blocksWidth * y + x] = block; + hdrLevelBlocks[input][level][blocksWidth * y + x] = block; } } } else { - ldrLevelBlocks[face][level].resize(blocksWidth * blocksHeight); + ldrLevelBlocks[input][level].resize(blocksWidth * blocksHeight); for (unsigned int y = 0; y < blocksHeight; y++) { for (unsigned int x = 0; x < blocksWidth; x++) { @@ -452,12 +382,12 @@ int main(int argc, char ** argv) unsigned int clampedX = std::min(pixelX, (unsigned int)oldWidth - 1); for (int channel = 0; channel < copyChannels; channel++) { - block[((pixelY % 4) * 4 + (pixelX % 4)) * copyChannels + channel] = ldrLevels[face][level][(clampedY * oldWidth + clampedX) * forcedChannels + channel]; + block[((pixelY % 4) * 4 + (pixelX % 4)) * copyChannels + channel] = ldrLevels[input][level][(clampedY * oldWidth + clampedX) * forcedChannels + channel]; } } } - ldrLevelBlocks[face][level][blocksWidth * y + x] = block; + ldrLevelBlocks[input][level][blocksWidth * y + x] = block; } } } @@ -469,19 +399,16 @@ int main(int argc, char ** argv) oldWidth = std::max(1, (int)floorf((float)oldWidth / 2)); oldHeight = std::max(1, (int)floorf((float)oldHeight / 2)); level++; - - if (level >= levelCount) { - break; - } } + /* Compress */ - levelBlocksCompressed[face].resize(levelCount); + levelBlocksCompressed[input].resize(levelCount); for (unsigned int l = 0; l < levelCount; l++) { if (hdr) { - levelBlocksCompressed[face][l].resize(hdrLevelBlocks[face][l].size() * blockSize); + levelBlocksCompressed[input][l].resize(hdrLevelBlocks[input][l].size() * blockSize); } else { - levelBlocksCompressed[face][l].resize(ldrLevelBlocks[face][l].size() * blockSize); + levelBlocksCompressed[input][l].resize(ldrLevelBlocks[input][l].size() * blockSize); } } @@ -496,49 +423,49 @@ int main(int argc, char ** argv) for (unsigned int l = 0; l < levelCount; l++) { unsigned int blocksPerThread; if (hdr) { - blocksPerThread = hdrLevelBlocks[face][l].size() / numThreads; + blocksPerThread = hdrLevelBlocks[input][l].size() / numThreads; } else { - blocksPerThread = ldrLevelBlocks[face][l].size() / numThreads; + blocksPerThread = ldrLevelBlocks[input][l].size() / numThreads; } unsigned int startBlock = t * blocksPerThread; unsigned int endBlock = startBlock + blocksPerThread; if (hdr) { if (t == numThreads - 1) { - endBlock = hdrLevelBlocks[face][l].size(); + endBlock = hdrLevelBlocks[input][l].size(); } } else { if (t == numThreads - 1) { - endBlock = ldrLevelBlocks[face][l].size(); + endBlock = ldrLevelBlocks[input][l].size(); } } for (unsigned int b = startBlock; b < endBlock; b++) { if (formatString == "BC6H") { rgba_surface surface; - surface.ptr = (uint8_t *)hdrLevelBlocks[face][l][b].data(); + surface.ptr = (uint8_t *)hdrLevelBlocks[input][l][b].data(); surface.width = 4; surface.height = 4; surface.stride = copyChannels * 4 * 2; - CompressBlocksBC6H(&surface, &levelBlocksCompressed[face][l][b * blockSize], &bc6henc); + CompressBlocksBC6H(&surface, &levelBlocksCompressed[input][l][b * blockSize], &bc6henc); } else { rgba_surface surface; - surface.ptr = ldrLevelBlocks[face][l][b].data(); + surface.ptr = ldrLevelBlocks[input][l][b].data(); surface.width = 4; surface.height = 4; surface.stride = copyChannels * 4; if (formatString == "BC1" || formatString == "BC1_SRGB") { - CompressBlocksBC1(&surface, &levelBlocksCompressed[face][l][b * blockSize]); + CompressBlocksBC1(&surface, &levelBlocksCompressed[input][l][b * blockSize]); } else if (formatString == "BC3" || formatString == "BC3_SRGB") { - CompressBlocksBC3(&surface, &levelBlocksCompressed[face][l][b * blockSize]); + CompressBlocksBC3(&surface, &levelBlocksCompressed[input][l][b * blockSize]); } else if (formatString == "BC4") { - CompressBlocksBC4(&surface, &levelBlocksCompressed[face][l][b * blockSize]); + CompressBlocksBC4(&surface, &levelBlocksCompressed[input][l][b * blockSize]); } else if (formatString == "BC5") { - CompressBlocksBC5(&surface, &levelBlocksCompressed[face][l][b * blockSize]); + CompressBlocksBC5(&surface, &levelBlocksCompressed[input][l][b * blockSize]); } else if (formatString == "BC7" || formatString == "BC7_SRGB") { - CompressBlocksBC7(&surface, &levelBlocksCompressed[face][l][b * blockSize], &bc7enc); + CompressBlocksBC7(&surface, &levelBlocksCompressed[input][l][b * blockSize], &bc7enc); } } @@ -549,9 +476,9 @@ int main(int argc, char ** argv) if (l == maxLevel) { float progress; if (hdr) { - progress = (float)completedBlocks[l] / hdrLevelBlocks[face][l].size(); + progress = (float)completedBlocks[l] / hdrLevelBlocks[input][l].size(); } else { - progress = (float)completedBlocks[l] / ldrLevelBlocks[face][l].size(); + progress = (float)completedBlocks[l] / ldrLevelBlocks[input][l].size(); } int barWidth = 70; @@ -576,9 +503,9 @@ int main(int argc, char ** argv) } if (hdr) { - hdrLevelBlocks[face].clear(); + hdrLevelBlocks[input].clear(); } else { - ldrLevelBlocks[face].clear(); + ldrLevelBlocks[input].clear(); } int barWidth = 70; @@ -685,13 +612,13 @@ int main(int argc, char ** argv) fh.seekp(levelOffsetBytePosition + (std::ofstream::pos_type)(level * 24)); uint64_t byteOffset = levelBytePosition; fh.write((char *)&byteOffset, sizeof(byteOffset)); - uint64_t byteLength = levelBlocksCompressed[0][level].size() * faceCount; + uint64_t byteLength = levelBlocksCompressed[0][level].size() * numInputs; fh.write((char *)&byteLength, sizeof(byteLength)); fh.write((char *)&byteLength, sizeof(byteLength)); fh.seekp(levelBytePosition); - for (int face = 0; face < faceCount; face++) { - fh.write((char *)levelBlocksCompressed[face][level].data(), levelBlocksCompressed[face][level].size()); + for (int input = 0; input < numInputs; input++) { + fh.write((char *)levelBlocksCompressed[input][level].data(), levelBlocksCompressed[input][level].size()); } }