5 #include "filesystem.h"
6 #include "interlacemodes.h"
9 #include <ImfChannelList.h>
10 #include <ImfChromaticities.h>
11 #include <ImfCompression.h>
13 #include <ImfInputFile.h>
14 #include <ImfOutputFile.h>
15 #include <ImfPixelType.h>
16 #include <ImfRgbaFile.h>
17 #include <ImfRgbaYca.h>
18 #include <ImfVersion.h>
19 #include "mwindow.inc"
23 class EXRIStream : public Imf::IStream
26 EXRIStream(char *data, int size);
29 bool read (char c[], int n);
31 void seekg (Imf::Int64 pos);
40 class EXROStream : public Imf::OStream
43 EXROStream(VFrame *data);
46 virtual void write(const char c[], int n);
47 virtual Imf::Int64 tellp();
48 virtual void seekp(Imf::Int64 pos);
57 EXRIStream::EXRIStream(char *data, int size)
58 : Imf::IStream("mypath")
65 EXRIStream::~EXRIStream()
69 bool EXRIStream::read(char c[], int n)
72 if(position + fragment > size)
74 fragment = size - position;
76 memcpy(c, data + position, fragment);
81 throw Iex::InputExc ("EXRIStream::read: Unexpected end of file.");
83 return position >= size;
86 Imf::Int64 EXRIStream::tellg ()
91 void EXRIStream::seekg(Imf::Int64 pos)
96 void EXRIStream::clear()
110 EXROStream::EXROStream(VFrame *data)
111 : Imf::OStream("mypath")
116 EXROStream::~EXROStream()
120 void EXROStream::write(const char c[], int n)
122 if(position + n > data->get_compressed_allocated())
123 data->allocate_compressed_data(MAX(position + n, data->get_compressed_allocated() * 2));
125 memcpy(data->get_data() + position, c, n);
127 data->set_compressed_size(MAX(position, data->get_compressed_size()));
130 Imf::Int64 EXROStream::tellp()
135 void EXROStream::seekp(Imf::Int64 pos)
150 FileEXR::FileEXR(Asset *asset, File *file)
151 : FileList(asset, file, "EXRLIST", ".exr", FILE_EXR, FILE_EXR_LIST)
153 native_cmodel = BC_RGB_FLOAT;
162 if(temp_y) delete [] temp_y;
163 if(temp_u) delete [] temp_u;
164 if(temp_v) delete [] temp_v;
167 char* FileEXR::compression_to_str(int compression)
171 case FileEXR::NONE: return "None"; break;
172 case FileEXR::PIZ: return "PIZ"; break;
173 case FileEXR::ZIP: return "ZIP"; break;
174 case FileEXR::ZIPS: return "ZIPS"; break;
175 case FileEXR::RLE: return "RLE"; break;
176 case FileEXR::PXR24: return "PXR24"; break;
181 int FileEXR::compression_to_exr(int compression)
185 case FileEXR::NONE: return (int)Imf::NO_COMPRESSION; break;
186 case FileEXR::PIZ: return (int)Imf::PIZ_COMPRESSION; break;
187 case FileEXR::ZIP: return (int)Imf::ZIP_COMPRESSION; break;
188 case FileEXR::ZIPS: return (int)Imf::ZIPS_COMPRESSION; break;
189 case FileEXR::RLE: return (int)Imf::RLE_COMPRESSION; break;
190 case FileEXR::PXR24: return (int)Imf::PXR24_COMPRESSION; break;
192 return Imf::NO_COMPRESSION;
195 int FileEXR::str_to_compression(char *string)
197 if(!strcmp(compression_to_str(FileEXR::NONE), string))
198 return FileEXR::NONE;
199 if(!strcmp(compression_to_str(FileEXR::PIZ), string))
201 if(!strcmp(compression_to_str(FileEXR::ZIP), string))
203 if(!strcmp(compression_to_str(FileEXR::ZIPS), string))
204 return FileEXR::ZIPS;
205 if(!strcmp(compression_to_str(FileEXR::RLE), string))
207 if(!strcmp(compression_to_str(FileEXR::PXR24), string))
209 return FileEXR::NONE;
212 int FileEXR::check_sig(Asset *asset, char *test)
214 if(Imf::isImfMagic(test)) return 1;
215 if(test[0] == 'E' && test[1] == 'X' && test[2] == 'R' &&
216 test[3] == 'L' && test[4] == 'I' && test[5] == 'S' && test[6] == 'T')
224 void FileEXR::get_parameters(BC_WindowBase *parent_window,
226 BC_WindowBase* &format_window,
232 EXRConfigVideo *window = new EXRConfigVideo(parent_window, asset);
233 format_window = window;
234 window->create_objects();
235 window->run_window();
240 int FileEXR::colormodel_supported(int colormodel)
242 return native_cmodel;
245 int FileEXR::get_best_colormodel(Asset *asset, int driver)
247 if(asset->exr_use_alpha)
248 return BC_RGBA_FLOAT;
253 int64_t FileEXR::get_memory_usage()
255 int64_t result = FileList::get_memory_usage();
256 if(temp_y) result += (int64_t)asset->width * asset->height * 3 / 2;
261 int FileEXR::read_frame_header(char *path)
265 // This may have been used by VFS
268 // if(!(stream = fopen(path, "rb")))
270 // perror("FileEXR::read_frame_header");
273 // int size = FileSystem::get_size(path);
274 // char *buffer = new char[size];
275 // fread(buffer, size, 1, stream);
278 // EXRIStream exr_stream(buffer, size);
279 // Imf::InputFile file(exr_stream);
282 Imf::InputFile file(path);
284 Imath::Box2i dw = file.header().dataWindow();
286 asset->width = dw.max.x - dw.min.x + 1;
287 asset->height = dw.max.y - dw.min.y + 1;
288 asset->interlace_mode = BC_ILACE_MODE_NOTINTERLACED;
290 const Imf::ChannelList &channels = file.header().channels();
292 if(channels.findChannel("A"))
293 native_cmodel = BC_RGBA_FLOAT;
295 native_cmodel = BC_RGB_FLOAT;
297 if(channels.findChannel("Y"))
299 // for (Imf::ChannelList::ConstIterator i = channels.begin(); i != channels.end(); ++i)
301 // printf("%s\n", i.name());
308 int FileEXR::read_frame(VFrame *frame, VFrame *data)
310 EXRIStream exr_stream((char*)data->get_data(), data->get_compressed_size());
311 Imf::InputFile file(exr_stream);
312 Imath::Box2i dw = file.header().dataWindow();
315 Imf::FrameBuffer framebuffer;
316 float **rows = (float**)frame->get_rows();
317 int components = cmodel_components(frame->get_color_model());
321 if(!temp_y) temp_y = new float[asset->width * asset->height];
322 if(!temp_u) temp_u = new float[asset->width * asset->height / 4];
323 if(!temp_v) temp_v = new float[asset->width * asset->height / 4];
324 framebuffer.insert("Y", Imf::Slice(Imf::FLOAT,
325 (char*)(temp_y - dy * asset->width - dx),
327 sizeof(float) * frame->get_w()));
328 framebuffer.insert("BY", Imf::Slice(Imf::FLOAT,
329 (char*)(temp_u - dy * asset->width / 4 - dx / 2),
331 sizeof(float) * frame->get_w() / 2,
334 framebuffer.insert("RY", Imf::Slice(Imf::FLOAT,
335 (char*)(temp_v - dy * asset->width / 4 - dx / 2),
337 sizeof(float) * frame->get_w() / 2,
343 framebuffer.insert("R", Imf::Slice(Imf::FLOAT,
344 (char*)(&rows[-dy][-dx * components]),
345 sizeof(float) * components,
346 sizeof(float) * components * frame->get_w()));
347 framebuffer.insert("G", Imf::Slice(Imf::FLOAT,
348 (char*)(&rows[-dy][-dx * components + 1]),
349 sizeof(float) * components,
350 sizeof(float) * components * frame->get_w()));
351 framebuffer.insert("B", Imf::Slice(Imf::FLOAT,
352 (char*)(&rows[-dy][-dx * components + 2]),
353 sizeof(float) * components,
354 sizeof(float) * components * frame->get_w()));
357 // Alpha always goes directly to the output frame
360 framebuffer.insert("A", Imf::Slice(Imf::FLOAT,
361 (char*)(&rows[-dy][-dx * components + 3]),
362 sizeof(float) * components,
363 sizeof(float) * components * frame->get_w()));
366 file.setFrameBuffer(framebuffer);
367 file.readPixels (dw.min.y, dw.max.y);
373 // Convert to RGB using crazy ILM equations
375 Imf::Chromaticities cr;
376 yw = Imf::RgbaYca::computeYw(cr);
378 for(int i = 0; i < asset->height - 1; i += 2)
380 float *y_row1 = temp_y + i * asset->width;
381 float *y_row2 = temp_y + (i + 1) * asset->width;
382 float *u_row = temp_u + (i * asset->width / 4);
383 float *v_row = temp_v + (i * asset->width / 4);
384 float *out_row1 = rows[i];
385 float *out_row2 = rows[i + 1];
386 for(int j = 0; j < asset->width - 1; j += 2)
396 g = (y - r * yw.x - b * yw.z) / yw.y;
400 if(components == 4) out_row1++;
405 g = (y - r * yw.x - b * yw.z) / yw.y;
409 if(components == 4) out_row1++;
414 g = (y - r * yw.x - b * yw.z) / yw.y;
418 if(components == 4) out_row1++;
423 g = (y - r * yw.x - b * yw.z) / yw.y;
427 if(components == 4) out_row1++;
437 int FileEXR::write_frame(VFrame *frame, VFrame *data, FrameWriterUnit *unit)
439 EXRUnit *exr_unit = (EXRUnit*)unit;
442 VFrame *output_frame;
443 data->set_compressed_size(0);
446 int native_cmodel = asset->exr_use_alpha ? BC_RGBA_FLOAT : BC_RGB_FLOAT;
447 int components = cmodel_components(native_cmodel);
449 if(frame->get_color_model() != native_cmodel)
451 if(!exr_unit->temp_frame) exr_unit->temp_frame = new VFrame(0,
455 cmodel_transfer(exr_unit->temp_frame->get_rows(), /* Leave NULL if non existent */
457 exr_unit->temp_frame->get_y(), /* Leave NULL if non existent */
458 exr_unit->temp_frame->get_u(),
459 exr_unit->temp_frame->get_v(),
460 frame->get_y(), /* Leave NULL if non existent */
463 0, /* Dimensions to capture from input frame */
467 0, /* Dimensions to project on output frame */
471 frame->get_color_model(),
473 0, /* When transfering BC_RGBA8888 to non-alpha this is the background color in 0xRRGGBB hex */
474 asset->width, /* For planar use the luma rowspan */
476 output_frame = exr_unit->temp_frame;
479 output_frame = frame;
481 Imf::Header header(output_frame->get_w(), output_frame->get_h());
482 header.compression() = (Imf::Compression)compression_to_exr(
483 asset->exr_compression);
484 header.channels().insert("R", Imf::Channel(Imf::FLOAT));
485 header.channels().insert("G", Imf::Channel(Imf::FLOAT));
486 header.channels().insert("B", Imf::Channel(Imf::FLOAT));
487 if(asset->exr_use_alpha) header.channels().insert("A", Imf::Channel(Imf::FLOAT));
489 EXROStream exr_stream(data);
490 Imf::OutputFile file(exr_stream, header);
491 Imf::FrameBuffer framebuffer;
492 float **rows = (float**)output_frame->get_rows();
493 framebuffer.insert("R",
494 Imf::Slice(Imf::FLOAT,
496 sizeof(float) * components,
497 sizeof(float) * components * output_frame->get_w()));
498 framebuffer.insert("G",
499 Imf::Slice(Imf::FLOAT,
500 (char*)(rows[0] + 1),
501 sizeof(float) * components,
502 sizeof(float) * components * output_frame->get_w()));
503 framebuffer.insert("B",
504 Imf::Slice(Imf::FLOAT,
505 (char*)(rows[0] + 2),
506 sizeof(float) * components,
507 sizeof(float) * components * output_frame->get_w()));
508 if(asset->exr_use_alpha)
509 framebuffer.insert("A",
510 Imf::Slice(Imf::FLOAT,
511 (char*)(rows[0] + 3),
512 sizeof(float) * components,
513 sizeof(float) * components * output_frame->get_w()));
514 file.setFrameBuffer(framebuffer);
515 file.writePixels(asset->height);
519 FrameWriterUnit* FileEXR::new_writer_unit(FrameWriter *writer)
521 return new EXRUnit(this, writer);
535 EXRUnit::EXRUnit(FileEXR *file, FrameWriter *writer)
536 : FrameWriterUnit(writer)
544 if(temp_frame) delete temp_frame;
557 EXRConfigVideo::EXRConfigVideo(BC_WindowBase *parent_window, Asset *asset)
558 : BC_Window(PROGRAM_NAME ": Video Compression",
559 parent_window->get_abs_cursor_x(1),
560 parent_window->get_abs_cursor_y(1),
562 BC_OKButton::calculate_h() + 100)
564 this->parent_window = parent_window;
568 EXRConfigVideo::~EXRConfigVideo()
572 int EXRConfigVideo::create_objects()
575 add_subwindow(new EXRUseAlpha(this, x, y));
577 EXRCompression *menu;
578 add_subwindow(new BC_Title(x, y, "Compression:"));
580 add_subwindow(menu = new EXRCompression(this, x, y, 100));
581 menu->create_objects();
582 add_subwindow(new BC_OKButton(this));
586 int EXRConfigVideo::close_event()
593 EXRUseAlpha::EXRUseAlpha(EXRConfigVideo *gui, int x, int y)
594 : BC_CheckBox(x, y, gui->asset->exr_use_alpha, _("Use alpha"))
599 int EXRUseAlpha::handle_event()
601 gui->asset->exr_use_alpha = get_value();
607 EXRCompression::EXRCompression(EXRConfigVideo *gui, int x, int y, int w)
611 FileEXR::compression_to_str(gui->asset->exr_compression))
615 void EXRCompression::create_objects()
617 add_item(new EXRCompressionItem(gui, FileEXR::NONE));
618 add_item(new EXRCompressionItem(gui, FileEXR::PIZ));
619 add_item(new EXRCompressionItem(gui, FileEXR::ZIP));
620 add_item(new EXRCompressionItem(gui, FileEXR::ZIPS));
621 add_item(new EXRCompressionItem(gui, FileEXR::RLE));
622 add_item(new EXRCompressionItem(gui, FileEXR::PXR24));
625 int EXRCompression::handle_event()
630 EXRCompressionItem::EXRCompressionItem(EXRConfigVideo *gui, int value)
631 : BC_MenuItem(FileEXR::compression_to_str(value))
637 int EXRCompressionItem::handle_event()
639 gui->asset->exr_compression = value;