Use the new tinyexr API for memory load/save instead of manual additions

This commit is contained in:
baldurk
2016-04-07 00:55:30 +02:00
parent 432423d84a
commit 1ed69916c9
2 changed files with 143 additions and 23 deletions
+78 -14
View File
@@ -200,23 +200,30 @@ ReplayCreateStatus IMG_CreateReplayDevice(const char *logfile, IReplayDriver **d
// make sure the file is a type we recognise before going further
if(is_exr_file(f))
{
FileIO::fseek64(f, 0, SEEK_SET);
const char *err = NULL;
float *data = NULL;
int dummy;
FileIO::fseek64(f, 0, SEEK_END);
uint64_t size = FileIO::ftell64(f);
FileIO::fseek64(f, 0, SEEK_SET);
int ret = LoadEXRFP(&data, &dummy, &dummy, f, &err);
std::vector<byte> buffer;
buffer.resize((size_t)size);
if(data) free(data);
FileIO::fread(&buffer[0], 1, buffer.size(), f);
EXRImage exrImage;
InitEXRImage(&exrImage);
int ret = ParseMultiChannelEXRHeaderFromMemory(&exrImage, &buffer[0], &err);
FreeEXRImage(&exrImage);
// could be an unsupported form of EXR, like deep image or other
if(ret != 0)
{
FileIO::fclose(f);
RDCERR("EXR file detected, but couldn't load with LoadEXR %d: '%s'", ret, err);
RDCERR("EXR file detected, but couldn't load with ParseMultiChannelEXRHeaderFromMemory %d: '%s'", ret, err);
return eReplayCreate_APIUnsupported;
}
}
@@ -355,20 +362,77 @@ void ImageViewer::RefreshFile()
if(is_exr_file(f))
{
texDetails.format = rgba32_float;
FileIO::fseek64(f, 0, SEEK_END);
uint64_t size = FileIO::ftell64(f);
FileIO::fseek64(f, 0, SEEK_SET);
std::vector<byte> buffer;
buffer.resize((size_t)size);
FileIO::fread(&buffer[0], 1, buffer.size(), f);
FileIO::fclose(f);
EXRImage exrImage;
InitEXRImage(&exrImage);
const char *err = NULL;
int ret = LoadEXRFP((float **)&data, (int *)&texDetails.width, (int *)&texDetails.height, f, &err);
datasize = texDetails.width*texDetails.height*4*sizeof(float);
int ret = ParseMultiChannelEXRHeaderFromMemory(&exrImage, &buffer[0], &err);
// could be an unsupported form of EXR, like deep image or other
if(ret != 0)
{
if(data) free(data);
RDCERR("EXR file detected, but couldn't load with LoadEXR %d: '%s'", ret, err);
FileIO::fclose(f);
RDCERR("EXR file detected, but couldn't load with ParseMultiChannelEXRHeaderFromMemory %d: '%s'", ret, err);
return;
}
texDetails.width = exrImage.width;
texDetails.height = exrImage.height;
datasize = texDetails.width*texDetails.height*4*sizeof(float);
data = (byte *)malloc(datasize);
for(int i=0; i < exrImage.num_channels; i++)
exrImage.requested_pixel_types[i] = TINYEXR_PIXELTYPE_FLOAT;
ret = LoadMultiChannelEXRFromMemory(&exrImage, &buffer[0], &err);
int channels[4] = { -1, -1, -1, -1 };
for(int i=0; i < exrImage.num_channels; i++)
{
switch(exrImage.channel_names[i][0])
{
case 'R': channels[0] = i; break;
case 'G': channels[1] = i; break;
case 'B': channels[2] = i; break;
case 'A': channels[3] = i; break;
}
}
float *rgba = (float *)data;
float **src = (float **)exrImage.images;
for(uint32_t i=0; i < texDetails.width*texDetails.height; i++)
{
for(int c=0; c < 4; c++)
{
if(channels[c] >= 0)
rgba[i*4 + c] = src[ channels[c] ][i];
else if(c < 3) // RGB channels default to 0
rgba[i*4 + c] = 0.0f;
else // alpha defaults to 1
rgba[i*4 + c] = 1.0f;
}
}
FreeEXRImage(&exrImage);
// shouldn't get here but let's be safe
if(ret != 0)
{
free(data);
RDCERR("EXR file detected, but couldn't load with LoadEXRFromMemory %d: '%s'", ret, err);
return;
}
}
+65 -9
View File
@@ -1045,7 +1045,20 @@ bool ReplayRenderer::SaveTexture(const TextureSave &saveData, const char *path)
}
else if(sd.destType == eFileType_HDR || sd.destType == eFileType_EXR)
{
float *fldata = new float[td.width*td.height*4];
float *fldata = NULL;
float *bgra[4] = { NULL, NULL, NULL, NULL };
if(sd.destType == eFileType_HDR)
{
fldata = new float[td.width*td.height*4];
}
else
{
bgra[0] = new float[td.width*td.height];
bgra[1] = new float[td.width*td.height];
bgra[2] = new float[td.width*td.height];
bgra[3] = new float[td.width*td.height];
}
byte *srcData = subdata[0];
@@ -1124,10 +1137,20 @@ bool ReplayRenderer::SaveTexture(const TextureSave &saveData, const char *path)
r = g = b = a; a = 1.0f;
}
fldata[(y*td.width + x) * 4 + 0] = r;
fldata[(y*td.width + x) * 4 + 1] = g;
fldata[(y*td.width + x) * 4 + 2] = b;
fldata[(y*td.width + x) * 4 + 3] = a;
if(fldata)
{
fldata[(y*td.width + x) * 4 + 0] = r;
fldata[(y*td.width + x) * 4 + 1] = g;
fldata[(y*td.width + x) * 4 + 2] = b;
fldata[(y*td.width + x) * 4 + 3] = a;
}
else
{
bgra[0][(y*td.width + x)] = b;
bgra[1][(y*td.width + x)] = g;
bgra[2][(y*td.width + x)] = r;
bgra[3][(y*td.width + x)] = a;
}
}
}
@@ -1139,13 +1162,46 @@ bool ReplayRenderer::SaveTexture(const TextureSave &saveData, const char *path)
else if(sd.destType == eFileType_EXR)
{
const char *err = NULL;
int ret = SaveEXRFP(fldata, (int)td.width, (int)td.height, f, &err);
success = (ret == 0);
if(!success)
EXRImage exrImage;
InitEXRImage(&exrImage);
int pixTypes[4] = { TINYEXR_PIXELTYPE_FLOAT, TINYEXR_PIXELTYPE_FLOAT, TINYEXR_PIXELTYPE_FLOAT, TINYEXR_PIXELTYPE_FLOAT };
int reqTypes[4] = { TINYEXR_PIXELTYPE_HALF, TINYEXR_PIXELTYPE_HALF, TINYEXR_PIXELTYPE_HALF, TINYEXR_PIXELTYPE_HALF };
const char *bgraNames[4] = { "B", "G", "R", "A" };
exrImage.num_channels = 4;
exrImage.channel_names = bgraNames;
exrImage.images = (unsigned char**)bgra;
exrImage.width = td.width;
exrImage.height = td.height;
exrImage.pixel_types = pixTypes;
exrImage.requested_pixel_types = reqTypes;
unsigned char *mem = NULL;
size_t ret = SaveMultiChannelEXRToMemory(&exrImage, &mem, &err);
success = (ret > 0);
if(success)
FileIO::fwrite(mem, 1, ret, f);
else
RDCERR("Error saving EXR file %d: '%s'", ret, err);
free(mem);
}
delete[] fldata;
if(fldata)
{
delete[] fldata;
}
else
{
delete[] bgra[0];
delete[] bgra[1];
delete[] bgra[2];
delete[] bgra[3];
}
}
FileIO::fclose(f);