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 int FileEXR::get_memory_usage()
255 int result = FileBase::get_memory_usage();
256 if(temp_y) result += asset->width * asset->height * 3 / 2;
261 int FileEXR::read_frame_header(char *path)
266 if(!(stream = fopen(path, "rb")))
268 perror("FileEXR::read_frame_header");
271 int size = FileSystem::get_size(path);
272 char *buffer = new char[size];
273 fread(buffer, size, 1, stream);
276 EXRIStream exr_stream(buffer, size);
277 Imf::InputFile file(exr_stream);
278 Imath::Box2i dw = file.header().dataWindow();
280 asset->width = dw.max.x - dw.min.x + 1;
281 asset->height = dw.max.y - dw.min.y + 1;
282 asset->interlace_mode = BC_ILACE_MODE_NOTINTERLACED;
284 const Imf::ChannelList &channels = file.header().channels();
286 if(channels.findChannel("A"))
287 native_cmodel = BC_RGBA_FLOAT;
289 native_cmodel = BC_RGB_FLOAT;
291 if(channels.findChannel("Y"))
293 // for (Imf::ChannelList::ConstIterator i = channels.begin(); i != channels.end(); ++i)
295 // printf("%s\n", i.name());
302 int FileEXR::read_frame(VFrame *frame, VFrame *data)
304 EXRIStream exr_stream((char*)data->get_data(), data->get_compressed_size());
305 Imf::InputFile file(exr_stream);
306 Imath::Box2i dw = file.header().dataWindow();
309 Imf::FrameBuffer framebuffer;
310 float **rows = (float**)frame->get_rows();
311 int components = cmodel_components(frame->get_color_model());
315 if(!temp_y) temp_y = new float[asset->width * asset->height];
316 if(!temp_u) temp_u = new float[asset->width * asset->height / 4];
317 if(!temp_v) temp_v = new float[asset->width * asset->height / 4];
318 framebuffer.insert("Y", Imf::Slice(Imf::FLOAT,
319 (char*)(temp_y - dy * asset->width - dx),
321 sizeof(float) * frame->get_w()));
322 framebuffer.insert("BY", Imf::Slice(Imf::FLOAT,
323 (char*)(temp_u - dy * asset->width / 4 - dx / 2),
325 sizeof(float) * frame->get_w() / 2,
328 framebuffer.insert("RY", Imf::Slice(Imf::FLOAT,
329 (char*)(temp_v - dy * asset->width / 4 - dx / 2),
331 sizeof(float) * frame->get_w() / 2,
337 framebuffer.insert("R", Imf::Slice(Imf::FLOAT,
338 (char*)(&rows[-dy][-dx * components]),
339 sizeof(float) * components,
340 sizeof(float) * components * frame->get_w()));
341 framebuffer.insert("G", Imf::Slice(Imf::FLOAT,
342 (char*)(&rows[-dy][-dx * components + 1]),
343 sizeof(float) * components,
344 sizeof(float) * components * frame->get_w()));
345 framebuffer.insert("B", Imf::Slice(Imf::FLOAT,
346 (char*)(&rows[-dy][-dx * components + 2]),
347 sizeof(float) * components,
348 sizeof(float) * components * frame->get_w()));
351 // Alpha always goes directly to the output frame
354 framebuffer.insert("A", Imf::Slice(Imf::FLOAT,
355 (char*)(&rows[-dy][-dx * components + 3]),
356 sizeof(float) * components,
357 sizeof(float) * components * frame->get_w()));
360 file.setFrameBuffer(framebuffer);
361 file.readPixels (dw.min.y, dw.max.y);
367 // Convert to RGB using crazy ILM equations
369 Imf::Chromaticities cr;
370 yw = Imf::RgbaYca::computeYw(cr);
372 for(int i = 0; i < asset->height - 1; i += 2)
374 float *y_row1 = temp_y + i * asset->width;
375 float *y_row2 = temp_y + (i + 1) * asset->width;
376 float *u_row = temp_u + (i * asset->width / 4);
377 float *v_row = temp_v + (i * asset->width / 4);
378 float *out_row1 = rows[i];
379 float *out_row2 = rows[i + 1];
380 for(int j = 0; j < asset->width - 1; j += 2)
390 g = (y - r * yw.x - b * yw.z) / yw.y;
394 if(components == 4) out_row1++;
399 g = (y - r * yw.x - b * yw.z) / yw.y;
403 if(components == 4) out_row1++;
408 g = (y - r * yw.x - b * yw.z) / yw.y;
412 if(components == 4) out_row1++;
417 g = (y - r * yw.x - b * yw.z) / yw.y;
421 if(components == 4) out_row1++;
430 int FileEXR::write_frame(VFrame *frame, VFrame *data, FrameWriterUnit *unit)
432 //printf("FileEXR::write_frame 1\n");
433 EXRUnit *exr_unit = (EXRUnit*)unit;
436 VFrame *output_frame;
437 data->set_compressed_size(0);
440 int native_cmodel = asset->exr_use_alpha ? BC_RGBA_FLOAT : BC_RGB_FLOAT;
441 int components = cmodel_components(native_cmodel);
443 if(frame->get_color_model() != native_cmodel)
445 if(!exr_unit->temp_frame) exr_unit->temp_frame = new VFrame(0,
449 cmodel_transfer(exr_unit->temp_frame->get_rows(), /* Leave NULL if non existent */
451 exr_unit->temp_frame->get_y(), /* Leave NULL if non existent */
452 exr_unit->temp_frame->get_u(),
453 exr_unit->temp_frame->get_v(),
454 frame->get_y(), /* Leave NULL if non existent */
457 0, /* Dimensions to capture from input frame */
461 0, /* Dimensions to project on output frame */
465 frame->get_color_model(),
467 0, /* When transfering BC_RGBA8888 to non-alpha this is the background color in 0xRRGGBB hex */
468 asset->width, /* For planar use the luma rowspan */
470 output_frame = exr_unit->temp_frame;
473 output_frame = frame;
475 Imf::Header header(output_frame->get_w(), output_frame->get_h());
476 header.compression() = (Imf::Compression)compression_to_exr(
477 asset->exr_compression);
478 header.channels().insert("R", Imf::Channel(Imf::FLOAT));
479 header.channels().insert("G", Imf::Channel(Imf::FLOAT));
480 header.channels().insert("B", Imf::Channel(Imf::FLOAT));
481 if(asset->exr_use_alpha) header.channels().insert("A", Imf::Channel(Imf::FLOAT));
483 EXROStream exr_stream(data);
484 Imf::OutputFile file(exr_stream, header);
485 Imf::FrameBuffer framebuffer;
486 float **rows = (float**)output_frame->get_rows();
487 framebuffer.insert("R",
488 Imf::Slice(Imf::FLOAT,
490 sizeof(float) * components,
491 sizeof(float) * components * output_frame->get_w()));
492 framebuffer.insert("G",
493 Imf::Slice(Imf::FLOAT,
494 (char*)(rows[0] + 1),
495 sizeof(float) * components,
496 sizeof(float) * components * output_frame->get_w()));
497 framebuffer.insert("B",
498 Imf::Slice(Imf::FLOAT,
499 (char*)(rows[0] + 2),
500 sizeof(float) * components,
501 sizeof(float) * components * output_frame->get_w()));
502 if(asset->exr_use_alpha)
503 framebuffer.insert("A",
504 Imf::Slice(Imf::FLOAT,
505 (char*)(rows[0] + 3),
506 sizeof(float) * components,
507 sizeof(float) * components * output_frame->get_w()));
508 file.setFrameBuffer(framebuffer);
509 file.writePixels(asset->height);
510 //printf("FileEXR::write_frame 10\n");
513 FrameWriterUnit* FileEXR::new_writer_unit(FrameWriter *writer)
515 return new EXRUnit(this, writer);
529 EXRUnit::EXRUnit(FileEXR *file, FrameWriter *writer)
530 : FrameWriterUnit(writer)
538 if(temp_frame) delete temp_frame;
551 EXRConfigVideo::EXRConfigVideo(BC_WindowBase *parent_window, Asset *asset)
552 : BC_Window(PROGRAM_NAME ": Video Compression",
553 parent_window->get_abs_cursor_x(1),
554 parent_window->get_abs_cursor_y(1),
558 this->parent_window = parent_window;
562 EXRConfigVideo::~EXRConfigVideo()
566 int EXRConfigVideo::create_objects()
569 add_subwindow(new EXRUseAlpha(this, x, y));
571 EXRCompression *menu;
572 add_subwindow(new BC_Title(x, y, "Compression:"));
574 add_subwindow(menu = new EXRCompression(this, x, y, 100));
575 menu->create_objects();
576 add_subwindow(new BC_OKButton(this));
580 int EXRConfigVideo::close_event()
587 EXRUseAlpha::EXRUseAlpha(EXRConfigVideo *gui, int x, int y)
588 : BC_CheckBox(x, y, gui->asset->exr_use_alpha, _("Use alpha"))
593 int EXRUseAlpha::handle_event()
595 gui->asset->exr_use_alpha = get_value();
601 EXRCompression::EXRCompression(EXRConfigVideo *gui, int x, int y, int w)
605 FileEXR::compression_to_str(gui->asset->exr_compression))
609 void EXRCompression::create_objects()
611 add_item(new EXRCompressionItem(gui, FileEXR::NONE));
612 add_item(new EXRCompressionItem(gui, FileEXR::PIZ));
613 add_item(new EXRCompressionItem(gui, FileEXR::ZIP));
614 add_item(new EXRCompressionItem(gui, FileEXR::ZIPS));
615 add_item(new EXRCompressionItem(gui, FileEXR::RLE));
616 add_item(new EXRCompressionItem(gui, FileEXR::PXR24));
619 int EXRCompression::handle_event()
624 EXRCompressionItem::EXRCompressionItem(EXRConfigVideo *gui, int value)
625 : BC_MenuItem(FileEXR::compression_to_str(value))
631 int EXRCompressionItem::handle_event()
633 gui->asset->exr_compression = value;