Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members

fileexr.C

Go to the documentation of this file.
00001 #include "asset.h"
00002 #include "bcsignals.h"
00003 #include "clip.h"
00004 #include "fileexr.h"
00005 #include "filesystem.h"
00006 #include "interlacemodes.h"
00007 
00008 #include <ImathBox.h>
00009 #include <ImfChannelList.h>
00010 #include <ImfChromaticities.h>
00011 #include <ImfCompression.h>
00012 #include <ImfIO.h>
00013 #include <ImfInputFile.h>
00014 #include <ImfOutputFile.h>
00015 #include <ImfPixelType.h>
00016 #include <ImfRgbaFile.h>
00017 #include <ImfRgbaYca.h>
00018 #include <ImfVersion.h>
00019 #include "mwindow.inc"
00020 #include "vframe.h"
00021 
00022 
00023 class EXRIStream : public Imf::IStream
00024 {
00025 public:
00026         EXRIStream(char *data, int size);
00027         ~EXRIStream();
00028 
00029         bool read (char c[], int n);
00030         Imf::Int64 tellg ();
00031         void seekg (Imf::Int64 pos);
00032         void clear ();
00033 
00034 private:
00035         char *data;
00036         int size;
00037         int position;
00038 };
00039 
00040 class EXROStream : public Imf::OStream
00041 {
00042 public:
00043         EXROStream(VFrame *data);
00044         ~EXROStream();
00045 
00046     virtual void write(const char c[], int n);
00047     virtual Imf::Int64 tellp();
00048     virtual void seekp(Imf::Int64 pos);
00049 
00050 private:
00051         VFrame *data;
00052         int position;
00053 };
00054 
00055 
00056 
00057 EXRIStream::EXRIStream(char *data, int size)
00058  : Imf::IStream("mypath")
00059 {
00060         this->data = data;
00061         this->size = size;
00062         position = 0;
00063 }
00064 
00065 EXRIStream::~EXRIStream()
00066 {
00067 }
00068 
00069 bool EXRIStream::read(char c[], int n)
00070 {
00071         int fragment = n;
00072         if(position + fragment > size)
00073         {
00074                 fragment = size - position;
00075         }
00076         memcpy(c, data + position, fragment);
00077         position += fragment;
00078 
00079         if(n != fragment)
00080         {
00081                 throw Iex::InputExc ("EXRIStream::read: Unexpected end of file.");
00082         }
00083         return position >= size;
00084 }
00085 
00086 Imf::Int64 EXRIStream::tellg ()
00087 {
00088         return position;
00089 }
00090 
00091 void EXRIStream::seekg(Imf::Int64 pos)
00092 {
00093         position = pos;
00094 }
00095 
00096 void EXRIStream::clear()
00097 {
00098 }
00099 
00100 
00101 
00102 
00103 
00104 
00105 
00106 
00107 
00108 
00109 
00110 EXROStream::EXROStream(VFrame *data)
00111  : Imf::OStream("mypath")
00112 {
00113         this->data = data;
00114         position = 0;
00115 }
00116 EXROStream::~EXROStream()
00117 {
00118 }
00119 
00120 void EXROStream::write(const char c[], int n)
00121 {
00122         if(position + n > data->get_compressed_allocated())
00123                 data->allocate_compressed_data(MAX(position + n, data->get_compressed_allocated() * 2));
00124 
00125         memcpy(data->get_data() + position, c, n);
00126         position += n;
00127         data->set_compressed_size(MAX(position, data->get_compressed_size()));
00128 }
00129 
00130 Imf::Int64 EXROStream::tellp()
00131 {
00132         return position;
00133 }
00134 
00135 void EXROStream::seekp(Imf::Int64 pos)
00136 {
00137         position = pos;
00138 }
00139 
00140 
00141 
00142 
00143 
00144 
00145 
00146 
00147 
00148 
00149 
00150 FileEXR::FileEXR(Asset *asset, File *file)
00151  : FileList(asset, file, "EXRLIST", ".exr", FILE_EXR, FILE_EXR_LIST)
00152 {
00153         native_cmodel = BC_RGB_FLOAT;
00154         is_yuv = 0;
00155         temp_y = 0;
00156         temp_u = 0;
00157         temp_v = 0;
00158 }
00159 
00160 FileEXR::~FileEXR()
00161 {
00162         if(temp_y) delete [] temp_y;
00163         if(temp_u) delete [] temp_u;
00164         if(temp_v) delete [] temp_v;
00165 }
00166 
00167 char* FileEXR::compression_to_str(int compression)
00168 {
00169         switch(compression)
00170         {
00171                 case FileEXR::NONE: return "None"; break;
00172                 case FileEXR::PIZ: return "PIZ"; break;
00173                 case FileEXR::ZIP: return "ZIP"; break;
00174                 case FileEXR::ZIPS: return "ZIPS"; break;
00175                 case FileEXR::RLE: return "RLE"; break;
00176                 case FileEXR::PXR24: return "PXR24"; break;
00177         }
00178         return "None";
00179 }
00180 
00181 int FileEXR::compression_to_exr(int compression)
00182 {
00183         switch(compression)
00184         {
00185                 case FileEXR::NONE: return (int)Imf::NO_COMPRESSION; break;
00186                 case FileEXR::PIZ: return (int)Imf::PIZ_COMPRESSION; break;
00187                 case FileEXR::ZIP: return (int)Imf::ZIP_COMPRESSION; break;
00188                 case FileEXR::ZIPS: return (int)Imf::ZIPS_COMPRESSION; break;
00189                 case FileEXR::RLE: return (int)Imf::RLE_COMPRESSION; break;
00190                 case FileEXR::PXR24: return (int)Imf::PXR24_COMPRESSION; break;
00191         }
00192         return Imf::NO_COMPRESSION;
00193 }
00194 
00195 int FileEXR::str_to_compression(char *string)
00196 {
00197         if(!strcmp(compression_to_str(FileEXR::NONE), string))  
00198                 return FileEXR::NONE;
00199         if(!strcmp(compression_to_str(FileEXR::PIZ), string))   
00200                 return FileEXR::PIZ;
00201         if(!strcmp(compression_to_str(FileEXR::ZIP), string))   
00202                 return FileEXR::ZIP;
00203         if(!strcmp(compression_to_str(FileEXR::ZIPS), string))  
00204                 return FileEXR::ZIPS;
00205         if(!strcmp(compression_to_str(FileEXR::RLE), string))   
00206                 return FileEXR::RLE;
00207         if(!strcmp(compression_to_str(FileEXR::PXR24), string))         
00208                 return PXR24;
00209         return FileEXR::NONE;
00210 }
00211 
00212 int FileEXR::check_sig(Asset *asset, char *test)
00213 {
00214         if(Imf::isImfMagic(test)) return 1;
00215         if(test[0] == 'E' && test[1] == 'X' && test[2] == 'R' && 
00216                 test[3] == 'L' && test[4] == 'I' && test[5] == 'S' && test[6] == 'T')
00217         {
00218                 return 1;
00219         }
00220 
00221         return 0;
00222 }
00223 
00224 void FileEXR::get_parameters(BC_WindowBase *parent_window, 
00225         Asset *asset, 
00226         BC_WindowBase* &format_window,
00227         int audio_options,
00228         int video_options)
00229 {
00230         if(video_options)
00231         {
00232                 EXRConfigVideo *window = new EXRConfigVideo(parent_window, asset);
00233                 format_window = window;
00234                 window->create_objects();
00235                 window->run_window();
00236                 delete window;
00237         }
00238 }
00239 
00240 int FileEXR::colormodel_supported(int colormodel)
00241 {
00242         return native_cmodel;
00243 }
00244 
00245 int FileEXR::get_best_colormodel(Asset *asset, int driver)
00246 {
00247         if(asset->exr_use_alpha)
00248                 return BC_RGBA_FLOAT;
00249         else
00250                 return BC_RGB_FLOAT;
00251 }
00252 
00253 int FileEXR::get_memory_usage()
00254 {
00255         int result = FileList::get_memory_usage();
00256         if(temp_y) result += asset->width * asset->height * 3 / 2;
00257         return result;
00258 }
00259 
00260 
00261 int FileEXR::read_frame_header(char *path)
00262 {
00263         int result = 0;
00264 
00265 // This may have been used by VFS
00266 //      FILE *stream;
00267 // 
00268 //      if(!(stream = fopen(path, "rb")))
00269 //      {
00270 //              perror("FileEXR::read_frame_header");
00271 //              return 1;
00272 //      }
00273 //      int size = FileSystem::get_size(path);
00274 //      char *buffer = new char[size];
00275 //      fread(buffer, size, 1, stream);
00276 //      fclose(stream);
00277 // 
00278 //      EXRIStream exr_stream(buffer, size);
00279 //      Imf::InputFile file(exr_stream);
00280 
00281 
00282         Imf::InputFile file(path);
00283 
00284         Imath::Box2i dw = file.header().dataWindow();
00285         
00286         asset->width = dw.max.x - dw.min.x + 1;
00287         asset->height = dw.max.y - dw.min.y + 1;
00288         asset->interlace_mode = BC_ILACE_MODE_NOTINTERLACED;
00289 
00290         const Imf::ChannelList &channels = file.header().channels();
00291 
00292         if(channels.findChannel("A"))
00293                 native_cmodel = BC_RGBA_FLOAT;
00294         else
00295                 native_cmodel = BC_RGB_FLOAT;
00296 
00297         if(channels.findChannel("Y"))
00298                 is_yuv = 1;
00299 // for (Imf::ChannelList::ConstIterator i = channels.begin(); i != channels.end(); ++i)
00300 // {
00301 // printf("%s\n", i.name());
00302 // }
00303 
00304 //      delete [] buffer;
00305         return result;
00306 }
00307 
00308 int FileEXR::read_frame(VFrame *frame, VFrame *data)
00309 {
00310         EXRIStream exr_stream((char*)data->get_data(), data->get_compressed_size());
00311         Imf::InputFile file(exr_stream);
00312         Imath::Box2i dw = file.header().dataWindow();
00313     int dx = dw.min.x;
00314     int dy = dw.min.y;
00315         Imf::FrameBuffer framebuffer;
00316         float **rows = (float**)frame->get_rows();
00317         int components = cmodel_components(frame->get_color_model());
00318 
00319         if(is_yuv)
00320         {
00321                 if(!temp_y) temp_y = new float[asset->width * asset->height];
00322                 if(!temp_u) temp_u = new float[asset->width * asset->height / 4];
00323                 if(!temp_v) temp_v = new float[asset->width * asset->height / 4];
00324                 framebuffer.insert("Y", Imf::Slice(Imf::FLOAT, 
00325                         (char*)(temp_y - dy * asset->width - dx),
00326                         sizeof(float),
00327                         sizeof(float) * frame->get_w()));
00328                 framebuffer.insert("BY", Imf::Slice(Imf::FLOAT, 
00329                         (char*)(temp_u - dy * asset->width / 4 - dx / 2),
00330                         sizeof(float),
00331                         sizeof(float) * frame->get_w() / 2,
00332                         2, 
00333                         2));
00334                 framebuffer.insert("RY", Imf::Slice(Imf::FLOAT, 
00335                         (char*)(temp_v - dy * asset->width / 4 - dx / 2),
00336                         sizeof(float),
00337                         sizeof(float) * frame->get_w() / 2,
00338                         2, 
00339                         2));
00340         }
00341         else
00342         {
00343                 framebuffer.insert("R", Imf::Slice(Imf::FLOAT, 
00344                         (char*)(&rows[-dy][-dx * components]),
00345                         sizeof(float) * components,
00346                         sizeof(float) * components * frame->get_w()));
00347                 framebuffer.insert("G", Imf::Slice(Imf::FLOAT, 
00348                         (char*)(&rows[-dy][-dx * components + 1]),
00349                         sizeof(float) * components,
00350                         sizeof(float) * components * frame->get_w()));
00351                 framebuffer.insert("B", Imf::Slice(Imf::FLOAT, 
00352                         (char*)(&rows[-dy][-dx * components + 2]),
00353                         sizeof(float) * components,
00354                         sizeof(float) * components * frame->get_w()));
00355         }
00356 
00357 // Alpha always goes directly to the output frame
00358         if(components == 4)
00359         {
00360                 framebuffer.insert("A", Imf::Slice(Imf::FLOAT, 
00361                         (char*)(&rows[-dy][-dx * components + 3]),
00362                         sizeof(float) * components,
00363                         sizeof(float) * components * frame->get_w()));
00364         }
00365 
00366         file.setFrameBuffer(framebuffer);
00367         file.readPixels (dw.min.y, dw.max.y);
00368 
00369 
00370 
00371         if(is_yuv)
00372         {
00373 // Convert to RGB using crazy ILM equations
00374                 Imath::V3f yw;
00375                 Imf::Chromaticities cr;
00376                 yw = Imf::RgbaYca::computeYw(cr);
00377 
00378                 for(int i = 0; i < asset->height - 1; i += 2)
00379                 {
00380                         float *y_row1 = temp_y + i * asset->width;
00381                         float *y_row2 = temp_y + (i + 1) * asset->width;
00382                         float *u_row = temp_u + (i * asset->width / 4);
00383                         float *v_row = temp_v + (i * asset->width / 4);
00384                         float *out_row1 = rows[i];
00385                         float *out_row2 = rows[i + 1];
00386                         for(int j = 0; j < asset->width - 1; j += 2)
00387                         {
00388                                 float v = *u_row++;
00389                                 float u = *v_row++;
00390                                 float y;
00391 
00392                                 float r, g, b;
00393                                 y = *y_row1++;
00394                                 r = (u + 1) * y;
00395                                 b = (v + 1) * y;
00396                                 g = (y - r * yw.x - b * yw.z) / yw.y;
00397                                 *out_row1++ = r;
00398                                 *out_row1++ = g;
00399                                 *out_row1++ = b;
00400                                 if(components == 4) out_row1++;
00401 
00402                                 y = *y_row1++;
00403                                 r = (u + 1) * y;
00404                                 b = (v + 1) * y;
00405                                 g = (y - r * yw.x - b * yw.z) / yw.y;
00406                                 *out_row1++ = r;
00407                                 *out_row1++ = g;
00408                                 *out_row1++ = b;
00409                                 if(components == 4) out_row1++;
00410 
00411                                 y = *y_row2++;
00412                                 r = (u + 1) * y;
00413                                 b = (v + 1) * y;
00414                                 g = (y - r * yw.x - b * yw.z) / yw.y;
00415                                 *out_row2++ = r;
00416                                 *out_row2++ = g;
00417                                 *out_row2++ = b;
00418                                 if(components == 4) out_row1++;
00419 
00420                                 y = *y_row2++;
00421                                 r = (u + 1) * y;
00422                                 b = (v + 1) * y;
00423                                 g = (y - r * yw.x - b * yw.z) / yw.y;
00424                                 *out_row2++ = r;
00425                                 *out_row2++ = g;
00426                                 *out_row2++ = b;
00427                                 if(components == 4) out_row1++;
00428                         }
00429                 }
00430         }
00431 }
00432 
00433 
00434 
00435 
00436 int FileEXR::write_frame(VFrame *frame, VFrame *data, FrameWriterUnit *unit)
00437 {
00438 //printf("FileEXR::write_frame 1\n");
00439         EXRUnit *exr_unit = (EXRUnit*)unit;
00440         int result = 0;
00441 
00442         VFrame *output_frame;
00443         data->set_compressed_size(0);
00444 
00445 
00446         int native_cmodel = asset->exr_use_alpha ? BC_RGBA_FLOAT : BC_RGB_FLOAT;
00447         int components = cmodel_components(native_cmodel);
00448 
00449         if(frame->get_color_model() != native_cmodel)
00450         {
00451                 if(!exr_unit->temp_frame) exr_unit->temp_frame = new VFrame(0,
00452                         asset->width,
00453                         asset->height,
00454                         native_cmodel);
00455                 cmodel_transfer(exr_unit->temp_frame->get_rows(), /* Leave NULL if non existent */
00456                         frame->get_rows(),
00457                         exr_unit->temp_frame->get_y(), /* Leave NULL if non existent */
00458                         exr_unit->temp_frame->get_u(),
00459                         exr_unit->temp_frame->get_v(),
00460                         frame->get_y(), /* Leave NULL if non existent */
00461                         frame->get_u(),
00462                         frame->get_v(),
00463                         0,        /* Dimensions to capture from input frame */
00464                         0, 
00465                         asset->width, 
00466                         asset->height,
00467                         0,       /* Dimensions to project on output frame */
00468                         0, 
00469                         asset->width, 
00470                         asset->height,
00471                         frame->get_color_model(), 
00472                         native_cmodel,
00473                         0,         /* When transfering BC_RGBA8888 to non-alpha this is the background color in 0xRRGGBB hex */
00474                         asset->width,       /* For planar use the luma rowspan */
00475                         asset->height);
00476                 output_frame = exr_unit->temp_frame;
00477         }
00478         else
00479                 output_frame = frame;
00480 
00481         Imf::Header header(output_frame->get_w(), output_frame->get_h());
00482         header.compression() = (Imf::Compression)compression_to_exr(
00483                 asset->exr_compression);
00484         header.channels().insert("R", Imf::Channel(Imf::FLOAT));
00485         header.channels().insert("G", Imf::Channel(Imf::FLOAT));
00486         header.channels().insert("B", Imf::Channel(Imf::FLOAT));
00487         if(asset->exr_use_alpha) header.channels().insert("A", Imf::Channel(Imf::FLOAT));
00488 
00489         EXROStream exr_stream(data);
00490         Imf::OutputFile file(exr_stream, header);
00491         Imf::FrameBuffer framebuffer;
00492         float **rows = (float**)output_frame->get_rows();
00493         framebuffer.insert("R",
00494                 Imf::Slice(Imf::FLOAT,
00495                         (char*)(rows[0]),
00496                         sizeof(float) * components,
00497                         sizeof(float) * components * output_frame->get_w()));
00498         framebuffer.insert("G",
00499                 Imf::Slice(Imf::FLOAT,
00500                         (char*)(rows[0] + 1),
00501                         sizeof(float) * components,
00502                         sizeof(float) * components * output_frame->get_w()));
00503         framebuffer.insert("B",
00504                 Imf::Slice(Imf::FLOAT,
00505                         (char*)(rows[0] + 2),
00506                         sizeof(float) * components,
00507                         sizeof(float) * components * output_frame->get_w()));
00508         if(asset->exr_use_alpha)
00509                 framebuffer.insert("A",
00510                         Imf::Slice(Imf::FLOAT,
00511                                 (char*)(rows[0] + 3),
00512                                 sizeof(float) * components,
00513                                 sizeof(float) * components * output_frame->get_w()));
00514         file.setFrameBuffer(framebuffer);
00515         file.writePixels(asset->height);
00516 //printf("FileEXR::write_frame 10\n");
00517 }
00518 
00519 FrameWriterUnit* FileEXR::new_writer_unit(FrameWriter *writer)
00520 {
00521         return new EXRUnit(this, writer);
00522 }
00523 
00524 
00525 
00526 
00527 
00528 
00529 
00530 
00531 
00532 
00533 
00534 
00535 EXRUnit::EXRUnit(FileEXR *file, FrameWriter *writer)
00536  : FrameWriterUnit(writer)
00537 {
00538         this->file = file;
00539         temp_frame = 0;
00540 }
00541 
00542 EXRUnit::~EXRUnit()
00543 {
00544         if(temp_frame) delete temp_frame;
00545 }
00546 
00547 
00548 
00549 
00550 
00551 
00552 
00553 
00554 
00555 
00556 
00557 EXRConfigVideo::EXRConfigVideo(BC_WindowBase *parent_window, Asset *asset)
00558  : BC_Window(PROGRAM_NAME ": Video Compression",
00559         parent_window->get_abs_cursor_x(1),
00560         parent_window->get_abs_cursor_y(1),
00561         300,
00562         BC_OKButton::calculate_h() + 100)
00563 {
00564         this->parent_window = parent_window;
00565         this->asset = asset;
00566 }
00567 
00568 EXRConfigVideo::~EXRConfigVideo()
00569 {
00570 }
00571 
00572 int EXRConfigVideo::create_objects()
00573 {
00574         int x = 10, y = 10;
00575         add_subwindow(new EXRUseAlpha(this, x, y));
00576         y += 30;
00577         EXRCompression *menu;
00578         add_subwindow(new BC_Title(x, y, "Compression:"));
00579         x += 110;
00580         add_subwindow(menu = new EXRCompression(this, x, y, 100));
00581         menu->create_objects();
00582         add_subwindow(new BC_OKButton(this));
00583         return 0;
00584 }
00585 
00586 int EXRConfigVideo::close_event()
00587 {
00588         set_done(0);
00589         return 1;
00590 }
00591 
00592 
00593 EXRUseAlpha::EXRUseAlpha(EXRConfigVideo *gui, int x, int y)
00594  : BC_CheckBox(x, y, gui->asset->exr_use_alpha, _("Use alpha"))
00595 {
00596         this->gui = gui;
00597 }
00598 
00599 int EXRUseAlpha::handle_event()
00600 {
00601         gui->asset->exr_use_alpha = get_value();
00602         return 1;
00603 }
00604 
00605 
00606 
00607 EXRCompression::EXRCompression(EXRConfigVideo *gui, int x, int y, int w)
00608  : BC_PopupMenu(x, 
00609         y, 
00610         w, 
00611         FileEXR::compression_to_str(gui->asset->exr_compression))
00612 {
00613         this->gui = gui;
00614 }
00615 void EXRCompression::create_objects()
00616 {
00617         add_item(new EXRCompressionItem(gui, FileEXR::NONE));
00618         add_item(new EXRCompressionItem(gui, FileEXR::PIZ));
00619         add_item(new EXRCompressionItem(gui, FileEXR::ZIP));
00620         add_item(new EXRCompressionItem(gui, FileEXR::ZIPS));
00621         add_item(new EXRCompressionItem(gui, FileEXR::RLE));
00622         add_item(new EXRCompressionItem(gui, FileEXR::PXR24));
00623 }
00624 
00625 int EXRCompression::handle_event()
00626 {
00627         return 1;
00628 }
00629 
00630 EXRCompressionItem::EXRCompressionItem(EXRConfigVideo *gui, int value)
00631  : BC_MenuItem(FileEXR::compression_to_str(value))
00632 {
00633         this->gui = gui;
00634         this->value = value;
00635 }
00636 
00637 int EXRCompressionItem::handle_event()
00638 {
00639         gui->asset->exr_compression = value;
00640         return 0;
00641 }
00642 

Generated on Sun Jan 8 13:38:54 2006 for Cinelerra-svn by  doxygen 1.4.4