int FileEXR::read_frame(VFrame *frame, VFrame *data) { EXRIStream exr_stream((char*)data->get_data(), data->get_compressed_size()); Imf::InputFile file(exr_stream); Imath::Box2i dw = file.header().dataWindow(); int dx = dw.min.x; int dy = dw.min.y; Imf::FrameBuffer framebuffer; float **rows = (float**)frame->get_rows(); int components = BC_CModels::components(frame->get_color_model()); if(is_yuv) { if(!temp_y) temp_y = new float[asset->width * asset->height]; if(!temp_u) temp_u = new float[asset->width * asset->height / 4]; if(!temp_v) temp_v = new float[asset->width * asset->height / 4]; framebuffer.insert("Y", Imf::Slice(Imf::FLOAT, (char*)(temp_y - dy * asset->width - dx), sizeof(float), sizeof(float) * frame->get_w())); framebuffer.insert("BY", Imf::Slice(Imf::FLOAT, (char*)(temp_u - dy * asset->width / 4 - dx / 2), sizeof(float), sizeof(float) * frame->get_w() / 2, 2, 2)); framebuffer.insert("RY", Imf::Slice(Imf::FLOAT, (char*)(temp_v - dy * asset->width / 4 - dx / 2), sizeof(float), sizeof(float) * frame->get_w() / 2, 2, 2)); } else { framebuffer.insert("R", Imf::Slice(Imf::FLOAT, (char*)(&rows[-dy][-dx * components]), sizeof(float) * components, sizeof(float) * components * frame->get_w())); framebuffer.insert("G", Imf::Slice(Imf::FLOAT, (char*)(&rows[-dy][-dx * components + 1]), sizeof(float) * components, sizeof(float) * components * frame->get_w())); framebuffer.insert("B", Imf::Slice(Imf::FLOAT, (char*)(&rows[-dy][-dx * components + 2]), sizeof(float) * components, sizeof(float) * components * frame->get_w())); } // Alpha always goes directly to the output frame if(components == 4) { framebuffer.insert("A", Imf::Slice(Imf::FLOAT, (char*)(&rows[-dy][-dx * components + 3]), sizeof(float) * components, sizeof(float) * components * frame->get_w())); } file.setFrameBuffer(framebuffer); file.readPixels (dw.min.y, dw.max.y); if(is_yuv) { // Convert to RGB using crazy ILM equations Imath::V3f yw; Imf::Chromaticities cr; yw = Imf::RgbaYca::computeYw(cr); for(int i = 0; i < asset->height - 1; i += 2) { float *y_row1 = temp_y + i * asset->width; float *y_row2 = temp_y + (i + 1) * asset->width; float *u_row = temp_u + (i * asset->width / 4); float *v_row = temp_v + (i * asset->width / 4); float *out_row1 = rows[i]; float *out_row2 = rows[i + 1]; for(int j = 0; j < asset->width - 1; j += 2) { float v = *u_row++; float u = *v_row++; float y; float r, g, b; y = *y_row1++; r = (u + 1) * y; b = (v + 1) * y; g = (y - r * yw.x - b * yw.z) / yw.y; *out_row1++ = r; *out_row1++ = g; *out_row1++ = b; if(components == 4) out_row1++; y = *y_row1++; r = (u + 1) * y; b = (v + 1) * y; g = (y - r * yw.x - b * yw.z) / yw.y; *out_row1++ = r; *out_row1++ = g; *out_row1++ = b; if(components == 4) out_row1++; y = *y_row2++; r = (u + 1) * y; b = (v + 1) * y; g = (y - r * yw.x - b * yw.z) / yw.y; *out_row2++ = r; *out_row2++ = g; *out_row2++ = b; if(components == 4) out_row1++; y = *y_row2++; r = (u + 1) * y; b = (v + 1) * y; g = (y - r * yw.x - b * yw.z) / yw.y; *out_row2++ = r; *out_row2++ = g; *out_row2++ = b; if(components == 4) out_row1++; } } } return 0; }
int FileEXR::write_frame(VFrame *frame, VFrame *data, FrameWriterUnit *unit) { EXRUnit *exr_unit = (EXRUnit*)unit; int result = 0; VFrame *output_frame; data->set_compressed_size(0); int native_cmodel = asset->exr_use_alpha ? BC_RGBA_FLOAT : BC_RGB_FLOAT; int components = BC_CModels::components(native_cmodel); if(frame->get_color_model() != native_cmodel) { if(!exr_unit->temp_frame) exr_unit->temp_frame = new VFrame(0, asset->width, asset->height, native_cmodel); exr_unit->temp_frame->transfer_from(frame); output_frame = exr_unit->temp_frame; } else output_frame = frame; Imf::Header header(output_frame->get_w(), output_frame->get_h()); header.compression() = (Imf::Compression)compression_to_exr( asset->exr_compression); header.channels().insert("R", Imf::Channel(Imf::FLOAT)); header.channels().insert("G", Imf::Channel(Imf::FLOAT)); header.channels().insert("B", Imf::Channel(Imf::FLOAT)); if(asset->exr_use_alpha) header.channels().insert("A", Imf::Channel(Imf::FLOAT)); EXROStream exr_stream(data); Imf::OutputFile file(exr_stream, header); Imf::FrameBuffer framebuffer; float **rows = (float**)output_frame->get_rows(); framebuffer.insert("R", Imf::Slice(Imf::FLOAT, (char*)(rows[0]), sizeof(float) * components, sizeof(float) * components * output_frame->get_w())); framebuffer.insert("G", Imf::Slice(Imf::FLOAT, (char*)(rows[0] + 1), sizeof(float) * components, sizeof(float) * components * output_frame->get_w())); framebuffer.insert("B", Imf::Slice(Imf::FLOAT, (char*)(rows[0] + 2), sizeof(float) * components, sizeof(float) * components * output_frame->get_w())); if(asset->exr_use_alpha) framebuffer.insert("A", Imf::Slice(Imf::FLOAT, (char*)(rows[0] + 3), sizeof(float) * components, sizeof(float) * components * output_frame->get_w())); file.setFrameBuffer(framebuffer); file.writePixels(asset->height); return 0; }
int FileEXR::write_frame(VFrame *frame, VFrame *data, FrameWriterUnit *unit) { EXRUnit *exr_unit = (EXRUnit*)unit; VFrame *output_frame; data->set_compressed_size(0); int native_cmodel = asset->exr_use_alpha ? BC_RGBA_FLOAT : BC_RGB_FLOAT; int components = cmodel_components(native_cmodel); if(frame->get_color_model() != native_cmodel) { if(!exr_unit->temp_frame) exr_unit->temp_frame = new VFrame(0, -1, asset->width, asset->height, native_cmodel, -1); BC_CModels::transfer(exr_unit->temp_frame->get_rows(), /* Leave NULL if non existent */ frame->get_rows(), exr_unit->temp_frame->get_y(), /* Leave NULL if non existent */ exr_unit->temp_frame->get_u(), exr_unit->temp_frame->get_v(), frame->get_y(), /* Leave NULL if non existent */ frame->get_u(), frame->get_v(), 0, /* Dimensions to capture from input frame */ 0, asset->width, asset->height, 0, /* Dimensions to project on output frame */ 0, asset->width, asset->height, frame->get_color_model(), native_cmodel, 0, /* When transfering BC_RGBA8888 to non-alpha this is the background color in 0xRRGGBB hex */ asset->width, /* For planar use the luma rowspan */ asset->height); output_frame = exr_unit->temp_frame; } else output_frame = frame; Imf::Header header(output_frame->get_w(), output_frame->get_h()); header.compression() = (Imf::Compression)compression_to_exr( asset->exr_compression); header.channels().insert("R", Imf::Channel(Imf::FLOAT)); header.channels().insert("G", Imf::Channel(Imf::FLOAT)); header.channels().insert("B", Imf::Channel(Imf::FLOAT)); if(asset->exr_use_alpha) header.channels().insert("A", Imf::Channel(Imf::FLOAT)); EXROStream exr_stream(data); Imf::OutputFile file(exr_stream, header); Imf::FrameBuffer framebuffer; float **rows = (float**)output_frame->get_rows(); framebuffer.insert("R", Imf::Slice(Imf::FLOAT, (char*)(rows[0]), sizeof(float) * components, sizeof(float) * components * output_frame->get_w())); framebuffer.insert("G", Imf::Slice(Imf::FLOAT, (char*)(rows[0] + 1), sizeof(float) * components, sizeof(float) * components * output_frame->get_w())); framebuffer.insert("B", Imf::Slice(Imf::FLOAT, (char*)(rows[0] + 2), sizeof(float) * components, sizeof(float) * components * output_frame->get_w())); if(asset->exr_use_alpha) framebuffer.insert("A", Imf::Slice(Imf::FLOAT, (char*)(rows[0] + 3), sizeof(float) * components, sizeof(float) * components * output_frame->get_w())); file.setFrameBuffer(framebuffer); file.writePixels(asset->height); return 0; }