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 = cmodel_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; 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; }
void BC_Texture::create_texture(int w, int h, int colormodel) { #ifdef HAVE_GL // Get max texture size from the server. // Maximum size was 4096 on the earliest cards that could do video. int max_texture_size = 0; glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size); // Calculate dimensions of texture int new_w = calculate_texture_size(w, &max_texture_size); int new_h = calculate_texture_size(h, &max_texture_size); int new_components = cmodel_components(colormodel); if(new_w < w || new_h < h) { printf("BC_Texture::create_texture frame size %dx%d bigger than maximum texture %dx%d.\n", w, h, max_texture_size, max_texture_size); } // Delete existing texture if(texture_id >= 0 && (new_h != texture_h || new_w != texture_w || new_components != texture_components || BC_WindowBase::get_synchronous()->current_window->get_id() != window_id)) { // printf("BC_Texture::create_texture released window_id=%d texture_id=%d\n", // BC_WindowBase::get_synchronous()->current_window->get_id(), // texture_id); BC_WindowBase::get_synchronous()->release_texture( window_id, texture_id); texture_id = -1; window_id = -1; } texture_w = new_w; texture_h = new_h; texture_components = new_components; // Get matching texture if(texture_id < 0) { texture_id = BC_WindowBase::get_synchronous()->get_texture( texture_w, texture_h, texture_components); // A new VFrame has no window_id, so it must read it from the matching texture. if(texture_id >= 0) window_id = BC_WindowBase::get_synchronous()->current_window->get_id(); } // No matching texture exists. // Create new texture with the proper dimensions if(texture_id < 0) { glGenTextures(1, (GLuint*)&texture_id); glBindTexture(GL_TEXTURE_2D, (GLuint)texture_id); glEnable(GL_TEXTURE_2D); if(texture_components == 4) glTexImage2D(GL_TEXTURE_2D, 0, 4, texture_w, texture_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); else glTexImage2D(GL_TEXTURE_2D, 0, 3, texture_w, texture_h, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); window_id = BC_WindowBase::get_synchronous()->current_window->get_id(); BC_WindowBase::get_synchronous()->put_texture(texture_id, texture_w, texture_h, texture_components); // printf("VFrame::new_texture created texture_id=%d window_id=%d\n", // *texture_id, // *window_id); } else { glBindTexture(GL_TEXTURE_2D, (GLuint)texture_id); glEnable(GL_TEXTURE_2D); } #endif }