contrib/oxl/oxp/SGIMovieFileWrite.cxx

Go to the documentation of this file.
00001 // This is oxl/oxp/SGIMovieFileWrite.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 
00006 #include "SGIMovieFileWrite.h"
00007 
00008 #include <vcl_cstring.h>
00009 #include <vcl_string.h>
00010 #include <vcl_vector.h>
00011 #undef sprintf // works around a bug in libintl.h
00012 #undef fprintf
00013 #include <vcl_cstdio.h>
00014 
00015 #include <vil1/vil1_jpeglib.h>
00016 #include <vil1/vil1_memory_image_of.h>
00017 #include <vil1/vil1_rgb.h>
00018 
00019 const int align = 4;
00020 inline int ROUNDUP(int x)
00021 {
00022   return int((x + align - 1) / align) * align;
00023 }
00024 
00025 void send4(FILE* fp, unsigned int val)
00026 {
00027   vcl_fwrite(&val, 4, 1, fp);
00028 }
00029 
00030 struct Vars {
00031   vcl_vector<vcl_string> names;
00032   vcl_vector<vcl_string> values;
00033   char buf[1024];
00034 
00035   void add(char const* tag, const char* value) {
00036     names.push_back(vcl_string(tag));
00037     values.push_back(vcl_string(value));
00038   }
00039 
00040   void add(char const* tag, int value) {
00041     vcl_sprintf(buf, "%d", value);
00042     add(tag, buf);
00043   }
00044   void add(char const* tag, double value) {
00045     vcl_sprintf(buf, "%g", value);
00046     add(tag, buf);
00047   }
00048 
00049   void send(FILE* fp) {
00050     send4(fp, 0);
00051     send4(fp, names.size());
00052     send4(fp, 0);
00053     for (unsigned i = 0; i < names.size(); ++i) {
00054       // Send name
00055       int l = names[i].size();
00056       vcl_strncpy(buf, names[i].c_str(), l);
00057       while (l < 16) buf[l++] = 0;
00058       vcl_fwrite(buf, 16, 1, fp);
00059       // Send values
00060       l = values[i].size();
00061       send4(fp, l + 1);
00062       vcl_fwrite(values[i].c_str(), l+1, 1, fp);
00063     }
00064   }
00065 };
00066 
00067 struct SGIMovieFileWriteData {
00068   SGIMovieFileWriteData(char const* filename,
00069                         int w,
00070                         int h,
00071                         int length);
00072 
00073   void PutFrame(int i);
00074   void Finish();
00075 
00076   int w,h,l;
00077   vcl_vector<unsigned> frame_ends;
00078 
00079   bool interlaced;
00080 
00081   vil1_memory_image_of<vil1_rgb<unsigned char> > buffer;
00082   vcl_vector<JSAMPLE*> rows;
00083   FILE *fp;
00084   int directory_pos;
00085   int first_frame;
00086 
00087   jpeg_compress_struct cinfo;
00088   jpeg_error_mgr jerr;
00089 
00090   void send4(unsigned int val) { vcl_fwrite(&val, 4, 1, fp); }
00091 };
00092 
00093 SGIMovieFileWriteData::SGIMovieFileWriteData(char const* filename,
00094                                              int w_,
00095                                              int h_,
00096                                              int l_):
00097   w(w_),h(h_),l(l_),
00098   frame_ends(l, (unsigned)0),
00099   buffer(w_, h_),
00100   rows(h_)
00101 {
00102   fp = vcl_fopen(filename, "w");
00103   if (!fp) {
00104     vcl_cerr << "SGIMovieFileWriteData: Can't open " << filename << '\n';
00105     return;
00106   }
00107 
00108   interlaced = true;
00109 
00110   // Write header
00111   vcl_fprintf(fp, "MOVI");
00112   send4(3);
00113   send4(0);
00114 
00115   Vars glob;
00116   glob.add("__NUM_I_TRACKS", 1);
00117   glob.add("__NUM_A_TRACKS", 0);
00118   glob.add("LOOP_MODE", 0);
00119   glob.add("OPTIMIZED", 0);
00120   glob.add("NUM_LOOPS", 0);
00121   glob.send(fp);
00122 
00123   Vars itrack;
00124   itrack.add("WIDTH", w);
00125   itrack.add("COMPRESSION", 10);
00126   itrack.add("ORIENTATION", 1100);
00127   itrack.add("Q_TEMPORAL", 0.750000);
00128   itrack.add("HEIGHT", h);
00129   itrack.add("PIXEL_ASPECT", 1.000000);
00130   itrack.add("__DIR_COUNT", l);
00131   itrack.add("INTERLACING", (int)interlaced);
00132   itrack.add("FPS", 30.000000);
00133   itrack.add("Q_SPATIAL", 0.750000);
00134   itrack.add("PACKING", 1001);
00135   itrack.send(fp);
00136 
00137   directory_pos = ftell(fp);
00138   first_frame = ROUNDUP(directory_pos + 4*4*l);
00139   fseek(fp, first_frame, 0);
00140 
00141   // Make jpegger
00142   cinfo.err = jpeg_std_error(&jerr);
00143 
00144   jpeg_create_compress(&cinfo);
00145 
00146   jpeg_stdio_dest(&cinfo, fp);
00147 
00148   cinfo.image_width = w;      /* image width and height, in pixels */
00149   cinfo.image_height = h / (1 + interlaced);
00150   cinfo.input_components = 3;     /* # of color components per pixel */
00151   cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
00152 
00153   jpeg_set_defaults(&cinfo);
00154   /* Make optional parameter settings here */
00155 
00156   // Build jpeg rows.
00157   if (interlaced)
00158     for (int y = 0; y < h / 2; ++y) {
00159       rows[y] = (JSAMPLE*)&buffer(0,2*y);
00160       rows[y + h/2] = (JSAMPLE*)&buffer(0,2*y+1);
00161     }
00162   else
00163     for (int y = 0; y < h; ++y)
00164       rows[y] = (JSAMPLE*)&buffer(0,y);
00165 }
00166 
00167 struct FrameIndex {
00168   int offset;
00169   int size;
00170   int pad;
00171   int frame;
00172 };
00173 
00174 void SGIMovieFileWriteData::Finish()
00175 {
00176   if (l != (int)frame_ends.size()) {
00177     vcl_cerr << "ZOKZOK: " << l << " != " << frame_ends.size() << '\n';
00178     return;
00179   }
00180   fseek(fp, directory_pos, 0);
00181   for (int i = 0; i < l; ++i) {
00182     FrameIndex f;
00183     int start = (i == 0)?first_frame : frame_ends[i-1];
00184     int end = frame_ends[i];
00185 
00186     f.offset = start;
00187     f.size = end - start;
00188     f.pad = 0;
00189     f.frame = 0;
00190     vcl_fwrite(&f, 4, 4, fp);
00191   }
00192 
00193   jpeg_destroy_compress(&cinfo);
00194   vcl_fclose(fp);
00195 }
00196 
00197 extern unsigned long jpeg_stdio_ftell(jpeg_compress_struct*);
00198 
00199 void SGIMovieFileWriteData::PutFrame(int i)
00200 {
00201   bool write_all_tables = true;
00202   if (!interlaced) {
00203     jpeg_start_compress (&cinfo, write_all_tables);
00204     jpeg_write_scanlines(&cinfo, &rows[0], h);
00205     jpeg_finish_compress(&cinfo);
00206   } else {
00207     jpeg_start_compress (&cinfo, write_all_tables);
00208     jpeg_write_scanlines(&cinfo, &rows[0], h/2);
00209     jpeg_finish_compress(&cinfo);
00210     jpeg_start_compress (&cinfo, write_all_tables);
00211     jpeg_write_scanlines(&cinfo, &rows[h/2], h/2);
00212     jpeg_finish_compress(&cinfo);
00213   }
00214 
00215   int pos = ROUNDUP(ftell(fp));
00216   fseek(fp, pos, SEEK_SET);
00217   frame_ends[i] = pos;
00218 }
00219 
00220 /////////////////////////////////////////////////////////////////////////////
00221 
00222 SGIMovieFileWrite::SGIMovieFileWrite(char const* filename,
00223                                      int w,
00224                                      int h,
00225                                      int length)
00226 {
00227   p = new SGIMovieFileWriteData(filename, w, h, length);
00228 }
00229 
00230 SGIMovieFileWrite::~SGIMovieFileWrite()
00231 {
00232   delete p;
00233 }
00234 
00235 void SGIMovieFileWrite::Finish()
00236 {
00237   p->Finish();
00238 }
00239 
00240 unsigned char* SGIMovieFileWrite::GetBuffer()
00241 {
00242   return (unsigned char*)p->buffer.get_buffer();
00243 }
00244 
00245 void SGIMovieFileWrite::PutBuffer(int frame_index)
00246 {
00247   p->PutFrame(frame_index);
00248 }

Generated on Tue Dec 2 05:14:28 2008 for contrib/oxl/oxp by  doxygen 1.5.1