in imagetool/commands/genlut.cpp [34:205]
int GenLUTCommand::run(const char** args, unsigned int numArgs)
{
if( numArgs < 3 ) {
fprintf(stderr, "Usage: ImageTool genlut [1d|3d] <input> <output>\n");
fprintf(stderr, "\te.g. ImageTool genlut 3d input.png output.cube\n");
return IMAGECORE_INVALID_USAGE;
}
FILE* outputFile = fopen(args[2], "wb");
if( strcmp(args[0], "3d") == 0 || strcmp(args[0], "1d") == 0 ) {
const char* inputFilePath = args[1];
ImageReader::Storage* source = ImageReader::FileStorage::open(inputFilePath);
if( source == NULL ) {
fprintf(stderr, "error: unable to open input file for '%s'\n", inputFilePath);
return IMAGECORE_READ_ERROR;
}
ImageReader* imageReader = ImageReader::create(source);
if( imageReader == NULL ) {
fprintf(stderr, "error: unknown or corrupt image format for '%s'\n", inputFilePath);
return IMAGECORE_INVALID_FORMAT;
}
ImageRGBA* inputImage = ImageRGBA::create(imageReader->getWidth(), imageReader->getHeight());
SECURE_ASSERT(inputImage != NULL);
imageReader->readImage(inputImage);
const uint8_t* buffer = inputImage->getBytes();
unsigned int inHeight = inputImage->getHeight();
unsigned int inPitch = inputImage->getPitch();
if( strcmp(args[0], "3d") == 0 ) {
unsigned int lutSize = inputImage->getWidth();
SECURE_ASSERT(inputImage->getHeight() == lutSize * lutSize);
fprintf(outputFile, "#Created by: Twitter ImageTool\n");
fprintf(outputFile, "LUT_3D_SIZE %i\n", lutSize);
fprintf(outputFile, "DOMAIN_MIN 0.0 0.0 0.0\n");
fprintf(outputFile, "DOMAIN_MAX 1.0 1.0 1.0\n");
for( unsigned int b = 0; b < lutSize; b++ ) {
unsigned int baseY = b * lutSize;
for( unsigned int g = 0; g < lutSize; g++ ) {
for( unsigned int r = 0; r < lutSize; r++ ) {
int inX = r;
int inY = g + baseY;
int inOffset = (inY * inPitch) + inX * 4;
unsigned int sampr = buffer[inOffset + 0];
unsigned int sampg = buffer[inOffset + 1];
unsigned int sampb = buffer[inOffset + 2];
float rf = (float)sampr / 255.0f;
float gf = (float)sampg / 255.0f;
float bf = (float)sampb / 255.0f;
fprintf(outputFile, "%f %f %f\n", rf, gf, bf);
}
}
}
} else if( strcmp(args[0], "1d") == 0 ) {
fprintf(outputFile, "#Created by: Twitter ImageTool\n");
fprintf(outputFile, "LUT_3D_SIZE 17\n");
fprintf(outputFile, "DOMAIN_MIN 0.0 0.0 0.0\n");
fprintf(outputFile, "DOMAIN_MAX 1.0 1.0 1.0\n");
unsigned int lutSize = 17;
for( unsigned int b = 0; b < lutSize; b++ ) {
for( unsigned int g = 0; g < lutSize; g++ ) {
for( unsigned int r = 0; r < lutSize; r++ ) {
float rl = (float)r / ((float)lutSize - 1.0f);
float gl = (float)g / ((float)lutSize - 1.0f);
float bl = (float)b / ((float)lutSize - 1.0f);
unsigned int rs = clamp(0, inHeight - 1, rl * (float)inHeight);
unsigned int gs = clamp(0, inHeight - 1, gl * (float)inHeight);
unsigned int bs = clamp(0, inHeight - 1, bl * (float)inHeight);
unsigned int sampr = buffer[rs * inPitch + 0];
unsigned int sampg = buffer[gs * inPitch + 1];
unsigned int sampb = buffer[bs * inPitch + 2];
float rf = (float)sampr / 255.0f;
float gf = (float)sampg / 255.0f;
float bf = (float)sampb / 255.0f;
fprintf(outputFile, "%f %f %f\n", rf, gf, bf);
}
}
}
}
} else if( strcmp(args[0], "identity") == 0 ) {
int lutSize = atoi(args[1]);
int padding = 0;
if( numArgs > 3 ) {
padding = atoi(args[3]);
}
ImageRGBA* outputImage = ImageRGBA::create((lutSize + (padding * 2)), (lutSize + (padding * 2)) * lutSize);
SECURE_ASSERT(outputImage != NULL);
unsigned int outPitch = 0;
uint8_t* outputBuffer = outputImage->lockRect(outputImage->getWidth(), outputImage->getHeight(), outPitch);
for( int b = 0; b < lutSize; b++ ) {
unsigned int baseY = b * (lutSize + (padding * 2));
for( int g = -padding; g < lutSize + padding; g++ ) {
for( int r = -padding; r < lutSize + padding; r++ ) {
int clampedG = clamp(0, lutSize - 1, g);
int clampedR = clamp(0, lutSize - 1, r);
float rValue = (float)clampedR / ((float)lutSize - 1.0f);
float gValue = (float)clampedG / ((float)lutSize - 1.0f);
float bValue = (float)b / ((float)lutSize - 1.0f);
int outY = g + padding + baseY;
int outX = r + padding;
int outOffset = (outY * outPitch) + outX * 4;
outputBuffer[outOffset + 0] = clamp(0, 255, rValue * 255.0f);
outputBuffer[outOffset + 1] = clamp(0, 255, gValue * 255.0f);
outputBuffer[outOffset + 2] = clamp(0, 255, bValue * 255.0f);
outputBuffer[outOffset + 3] = 255;
}
}
}
ImageWriter::FileStorage outputStorage(outputFile);
ImageWriter* writer = ImageWriter::createWithFormat(kImageFormat_PNG, &outputStorage);
writer->writeImage(outputImage);
} else if( strcmp(args[0], "depad") == 0 ) {
const char* inputFilePath = args[1];
ImageReader::Storage* source = ImageReader::FileStorage::open(inputFilePath);
if( source == NULL ) {
fprintf(stderr, "error: unable to open input file for '%s'\n", inputFilePath);
return IMAGECORE_READ_ERROR;
}
ImageReader* imageReader = ImageReader::create(source);
if( imageReader == NULL ) {
fprintf(stderr, "error: unknown or corrupt image format for '%s'\n", inputFilePath);
return IMAGECORE_INVALID_FORMAT;
}
ImageRGBA* inputImage = ImageRGBA::create(imageReader->getWidth(), imageReader->getHeight());
SECURE_ASSERT(inputImage != NULL);
imageReader->readImage(inputImage);
const uint8_t* buffer = inputImage->getBytes();
int padding = atoi(args[3]);
int lutSize = inputImage->getWidth() - padding * 2;
SECURE_ASSERT(lutSize * (lutSize + padding * 2) == (int)inputImage->getHeight());
unsigned int inPitch = inputImage->getWidth();
ImageRGBA* outputImage = ImageRGBA::create(lutSize, lutSize*lutSize);
SECURE_ASSERT(inputImage != NULL);
unsigned int outPitch = 0;
uint8_t* outputBuffer = outputImage->lockRect(outputImage->getWidth(), outputImage->getHeight(), outPitch);
for( int b = 0; b < lutSize; b++ ) {
unsigned int inBaseY = b * (lutSize + padding * 2);
unsigned int outBaseY = b * lutSize;
for( int g = 0; g < lutSize; g++ ) {
for( int r = 0; r < lutSize; r++ ) {
int inY = g + padding + inBaseY;
int inX = r + padding;
int inputOffset = (inY * inPitch) + inX * 4;
int outY = g + outBaseY;
int outX = r;
int outputOffset = (outY * outPitch) + outX * 4;
outputBuffer[outputOffset + 0] = buffer[inputOffset + 0];
outputBuffer[outputOffset + 1] = buffer[inputOffset + 1];
outputBuffer[outputOffset + 2] = buffer[inputOffset + 2];
outputBuffer[outputOffset + 3] = 255;
}
}
}
ImageWriter::FileStorage outputStorage(outputFile);
ImageWriter* writer = ImageWriter::createWithFormat(kImageFormat_PNG, &outputStorage);
writer->writeImage(outputImage);
}
fclose(outputFile);
return IMAGECORE_SUCCESS;
}