pic_io.cpp

00001 /* ***** BEGIN LICENSE BLOCK *****
00002 *
00003 * $Id: pic_io.cpp,v 1.2 2005/01/30 05:11:40 gabest Exp $ $Name:  $
00004 *
00005 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00006 *
00007 * The contents of this file are subject to the Mozilla Public License
00008 * Version 1.1 (the "License"); you may not use this file except in compliance
00009 * with the License. You may obtain a copy of the License at
00010 * http://www.mozilla.org/MPL/
00011 *
00012 * Software distributed under the License is distributed on an "AS IS" basis,
00013 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
00014 * the specific language governing rights and limitations under the License.
00015 *
00016 * The Original Code is BBC Research and Development code.
00017 *
00018 * The Initial Developer of the Original Code is the British Broadcasting
00019 * Corporation.
00020 * Portions created by the Initial Developer are Copyright (C) 2004.
00021 * All Rights Reserved.
00022 *
00023 * Contributor(s): Thomas Davies (Original Author),
00024 *                 Scott Robert Ladd,
00025 *                 Stuart Cunningham,
00026 *                 Tim Borer
00027 *
00028 * Alternatively, the contents of this file may be used under the terms of
00029 * the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser
00030 * Public License Version 2.1 (the "LGPL"), in which case the provisions of
00031 * the GPL or the LGPL are applicable instead of those above. If you wish to
00032 * allow use of your version of this file only under the terms of the either
00033 * the GPL or LGPL and not to allow others to use your version of this file
00034 * under the MPL, indicate your decision by deleting the provisions above
00035 * and replace them with the notice and other provisions required by the GPL
00036 * or LGPL. If you do not delete the provisions above, a recipient may use
00037 * your version of this file under the terms of any one of the MPL, the GPL
00038 * or the LGPL.
00039 * ***** END LICENSE BLOCK ***** */
00040 
00041 #include <libdirac_common/pic_io.h>
00042 #include <libdirac_common/dirac_assertions.h>
00043 using namespace dirac;
00044 
00045 /*************************************Output***********************************/
00046 
00047 StreamPicOutput::StreamPicOutput()
00048 {}
00049 
00050 StreamPicOutput::~StreamPicOutput()
00051 {}
00052 
00053 StreamPicOutput::StreamPicOutput (const SeqParams& sp) :
00054     m_sparams(sp),
00055     m_op_pic_ptr(0)
00056 { }
00057 
00058 
00059 bool StreamPicOutput::WriteNextFrame( const Frame& myframe )
00060 {
00061     bool ret_val;
00062 
00063     ret_val=WriteComponent(myframe.Ydata() , Y_COMP );
00064 
00065     if ( m_sparams.CFormat() != Yonly )
00066     {
00067         ret_val|=WriteComponent( myframe.Udata() , U_COMP );
00068         ret_val|=WriteComponent( myframe.Vdata() , V_COMP );
00069     }
00070 
00071     return ret_val;
00072 }
00073 
00074 bool StreamPicOutput::WriteComponent( const PicArray& pic_data , const CompSort& cs)
00075 {
00076     //initially set up for 10-bit data input, rounded to 8 bits on file output
00077     //This will throw out any padding to the right and bottom of a frame
00078 
00079     int xl,yl;
00080     if (cs == Y_COMP)
00081     {
00082         xl = m_sparams.Xl();
00083         yl = m_sparams.Yl();
00084     }
00085     else
00086     {
00087         xl = m_sparams.ChromaWidth();
00088         yl = m_sparams.ChromaHeight();
00089     }
00090 
00091     unsigned char* tempc=new unsigned char[xl];
00092     ValueType tempv;
00093 
00094     if (m_op_pic_ptr)
00095     {
00096         for (int j=0 ; j<yl ;++j)
00097         {
00098             for (int i=0 ; i<xl ; ++i)
00099             {                
00100                 tempv = pic_data[j][i]+2;
00101                 tempv >>= 2;
00102                 tempc[i] = (unsigned char) tempv;                
00103             }//I
00104 
00105             m_op_pic_ptr->write((char*) tempc,xl);
00106 
00107         }//J
00108     }
00109     else
00110     {
00111         std::cerr<<std::endl<<"Can't open picture data file for writing";
00112 
00113         //tidy up        
00114         delete[] tempc;
00115 
00116         //exit failure
00117         return false;
00118     }
00119 
00120     m_op_pic_ptr->flush();
00121 
00122     delete[] tempc;
00123 
00124     //exit success
00125     return true;
00126 }
00127 
00128 MemoryStreamOutput::MemoryStreamOutput()
00129 {
00130     //picture input
00131     m_op_pic_ptr =
00132         new std::ostream(&m_membuf);
00133 }
00134 
00135 MemoryStreamOutput::~MemoryStreamOutput()
00136 {
00137     delete m_op_pic_ptr;
00138 }
00139 
00140 void MemoryStreamOutput::SetMembufReference (unsigned char *buf, int buf_size)
00141 {
00142     m_membuf.SetMembufReference(buf, buf_size);
00143 }
00144 
00145 
00146 FileStreamOutput::FileStreamOutput(const char* output_name,
00147                      const SeqParams& sp,
00148                      bool write_header_only) : StreamPicOutput(sp)
00149 {
00150     m_op_head_ptr = NULL;
00151 
00152     OpenHeader(output_name);
00153     if (! write_header_only)
00154         OpenYUV(output_name);
00155 }
00156 
00157 bool FileStreamOutput::OpenHeader(const char* output_name)
00158 {
00159     char output_name_hdr[FILENAME_MAX];
00160 
00161     strncpy(output_name_hdr, output_name, sizeof(output_name_hdr));
00162     strcat(output_name_hdr, ".hdr");
00163 
00164     //header output
00165     m_op_head_ptr =
00166         new std::ofstream(output_name_hdr,std::ios::out | std::ios::binary);
00167 
00168     if (!(*m_op_head_ptr))
00169     {
00170         std::cerr <<std::endl <<
00171             "Can't open output header file for output: " << 
00172              output_name_hdr << std::endl;
00173 
00174         return false;    
00175 
00176     }
00177 
00178     return true;
00179 }
00180 
00181 bool FileStreamOutput::OpenYUV(const char* output_name)
00182 {
00183     char output_name_yuv[FILENAME_MAX];
00184 
00185     strncpy(output_name_yuv,output_name, sizeof(output_name_yuv));
00186     strcat(output_name_yuv,".yuv");
00187 
00188     //picture output
00189     m_op_pic_ptr =
00190         new std::ofstream(output_name_yuv,std::ios::out | std::ios::binary);
00191 
00192     if (!(*m_op_pic_ptr))
00193     {
00194         std::cerr << std::endl << 
00195             "Can't open output picture data file for output: " << 
00196             output_name_yuv<<std::endl;
00197 
00198         return false;    
00199 
00200     }
00201 
00202     return true;
00203 }
00204 
00205 FileStreamOutput::~FileStreamOutput()
00206 {
00207     if (m_op_head_ptr && *m_op_head_ptr)
00208     {
00209         m_op_head_ptr->close();
00210         delete m_op_head_ptr;
00211     }
00212 
00213     if (m_op_pic_ptr && *m_op_pic_ptr)
00214     {
00215         static_cast<std::ofstream *>(m_op_pic_ptr)->close();
00216         delete m_op_pic_ptr;
00217     }
00218 }
00219 
00220 //write a human-readable picture header as separate file
00221 bool FileStreamOutput::WritePicHeader()
00222 {
00223     if (!m_op_head_ptr || !*m_op_head_ptr)
00224         return false;
00225 
00226     *m_op_head_ptr << m_sparams.CFormat() << std::endl;
00227     *m_op_head_ptr << m_sparams.Xl() << std::endl;
00228     *m_op_head_ptr << m_sparams.Yl() << std::endl;
00229     *m_op_head_ptr << m_sparams.Interlace() << std::endl;
00230     *m_op_head_ptr << m_sparams.TopFieldFirst() << std::endl;
00231     *m_op_head_ptr << m_sparams.FrameRate() << std::endl;
00232 
00233     return true;
00234 
00235 }
00236 
00237 /**************************************Input***********************************/
00238 
00239 StreamPicInput::StreamPicInput () :
00240     m_ip_pic_ptr(0),
00241     m_xpad(0),
00242     m_ypad(0)
00243 {}
00244 
00245 StreamPicInput::StreamPicInput (std::istream *ip_pic_ptr, const SeqParams &sparams) :
00246     m_sparams(m_sparams),
00247     m_ip_pic_ptr(ip_pic_ptr),
00248     m_xpad(0),
00249     m_ypad(0)
00250 {}
00251 
00252 StreamPicInput::~StreamPicInput ()
00253 {}
00254 
00255 void StreamPicInput::SetPadding(const int xpd, const int ypd)
00256 {
00257     m_xpad=xpd;
00258     m_ypad=ypd;
00259 }
00260 
00261 bool StreamPicInput::ReadNextFrame(Frame& myframe)
00262 {
00263     //return value. Failure if one of the components can't be read,
00264     //success otherwise/.
00265 
00266     bool ret_val;
00267     ret_val=ReadComponent( myframe.Ydata() , Y_COMP);
00268 
00269     if (m_sparams.CFormat() != Yonly)
00270     {
00271         ret_val|=ReadComponent(myframe.Udata() , U_COMP);
00272         ret_val|=ReadComponent(myframe.Vdata() , V_COMP);
00273     }
00274 
00275     return ret_val;
00276 }
00277 
00278 
00279 bool StreamPicInput::ReadComponent(PicArray& pic_data, const CompSort& cs)
00280 {
00281     if (! *m_ip_pic_ptr)
00282         return false;
00283 
00284     //initially set up for 8-bit file input expanded to 10 bits for array output
00285 
00286     int xl,yl;
00287     if (cs == Y_COMP){
00288         xl = m_sparams.Xl();
00289         yl = m_sparams.Yl();
00290     }
00291     else{
00292         if (m_sparams.CFormat() == format411)
00293         {
00294             xl = m_sparams.Xl()/4;
00295             yl = m_sparams.Yl();
00296         }
00297         else if (m_sparams.CFormat()==format420)
00298         {
00299             xl = m_sparams.Xl()/2;
00300             yl = m_sparams.Yl()/2;
00301         }
00302         else if (m_sparams.CFormat() == format422)
00303         {
00304             xl = m_sparams.Xl()/2;
00305             yl = m_sparams.Yl();
00306         }
00307         else{
00308             xl = m_sparams.Xl();
00309             yl = m_sparams.Yl();
00310         }
00311     }
00312 
00313     unsigned char * temp = new unsigned char[xl];//array big enough for one line
00314 
00315     for (int j=0 ; j<yl ; ++j)
00316     {        
00317         m_ip_pic_ptr->read((char*) temp, xl);        
00318 
00319         for (int i=0 ; i<xl ; ++i)
00320         {            
00321             pic_data[j][i] = (ValueType) temp[i];
00322             pic_data[j][i] <<= 2;
00323         }//I
00324 
00325         //pad the columns on the rhs using the edge value        
00326         for (int i=xl ; i<pic_data.LengthX() ; ++i ){
00327             pic_data[j][i] = pic_data[j][xl-1];
00328         }//I
00329 
00330     }//J
00331 
00332     delete [] temp;
00333 
00334     //now do the padded lines, using the last true line
00335     for (int j=yl ; j<pic_data.LengthY() ; ++j )
00336     {
00337         for (int i=0 ; i<pic_data.LengthX() ; ++i )
00338         {
00339             pic_data[j][i] = pic_data[yl-1][i];
00340         }//I
00341     }//J
00342 
00343     return true;
00344 }
00345 
00346 MemoryStreamInput::MemoryStreamInput()
00347 {
00348     //picture input
00349     m_ip_pic_ptr =
00350         new std::istream(&m_membuf);
00351 }
00352 
00353 MemoryStreamInput::~MemoryStreamInput()
00354 {
00355     delete m_ip_pic_ptr;
00356 }
00357 
00358 void MemoryStreamInput::SetMembufReference (unsigned char *buf, int buf_size)
00359 {
00360     m_membuf.SetMembufReference(buf, buf_size);
00361 }
00362 
00363 void MemoryStreamInput::Skip(const int num)
00364 {
00365     REPORTM (false, "MemoryStreamInput::Skip - Reached unimplemented function");
00366 }
00367 
00368 FileStreamInput::FileStreamInput(const char* input_name)
00369 {
00370 
00371     char input_name_yuv[FILENAME_MAX];
00372     char input_name_hdr[FILENAME_MAX];
00373 
00374     strncpy(input_name_yuv, input_name, sizeof(input_name_yuv));
00375     strncpy(input_name_hdr, input_name, sizeof(input_name_hdr));
00376     strcat(input_name_yuv, ".yuv");
00377     strcat(input_name_hdr, ".hdr");
00378 
00379     //header output
00380     m_ip_head_ptr =
00381         new std::ifstream(input_name_hdr,std::ios::in | std::ios::binary);
00382     //picture output
00383     m_ip_pic_ptr =
00384         new std::ifstream(input_name_yuv,std::ios::in | std::ios::binary);
00385 
00386     if (!(*m_ip_head_ptr))
00387         std::cerr << std::endl <<
00388             "Can't open input header file: " << input_name_hdr << std::endl;
00389     if (!(*m_ip_pic_ptr))
00390         std::cerr << std::endl<<
00391             "Can't open input picture data file: " <<
00392             input_name_yuv << std::endl;
00393 }
00394 
00395 FileStreamInput::~FileStreamInput()
00396 {
00397     static_cast<std::ifstream *>(m_ip_pic_ptr)->close();
00398     m_ip_head_ptr->close();
00399     delete m_ip_pic_ptr;
00400     delete m_ip_head_ptr;
00401 }
00402 
00403 //read a picture header from a separate file
00404 bool FileStreamInput::ReadPicHeader()
00405 {
00406     if (! *m_ip_head_ptr)
00407         return false;
00408 
00409     int temp_int;
00410     bool temp_bool;
00411 
00412     *m_ip_head_ptr >> temp_int;
00413     m_sparams.SetCFormat( (ChromaFormat)temp_int );
00414 
00415     *m_ip_head_ptr >> temp_int;
00416     m_sparams.SetXl( temp_int );
00417  
00418    *m_ip_head_ptr >> temp_int;
00419     m_sparams.SetYl( temp_int );
00420 
00421     *m_ip_head_ptr >> temp_bool;
00422     m_sparams.SetInterlace( temp_bool );
00423 
00424     *m_ip_head_ptr >> temp_bool;
00425     m_sparams.SetTopFieldFirst( temp_bool );
00426 
00427     *m_ip_head_ptr >> temp_int;    
00428     m_sparams.SetFrameRate( temp_int );
00429 
00430     return true;
00431 }
00432 
00433 void FileStreamInput::Skip(const int num)
00434 {
00435     const int num_pels = m_sparams.Xl()*m_sparams.Yl();
00436     int num_bytes;
00437  
00438     const ChromaFormat cf = m_sparams.CFormat();
00439 
00440     if ( cf == Yonly)
00441         num_bytes = num_pels;
00442     else if ( cf == format411 || cf == format420 )
00443        num_bytes = (num_pels*3)/2;
00444     else if ( cf == format422 )
00445        num_bytes = num_pels*2;
00446     else
00447        num_bytes = num_pels*3;
00448 
00449     m_ip_pic_ptr->seekg( num*num_bytes , std::ios::cur );
00450 }
00451 
00452 bool StreamPicInput::End() const
00453 {
00454     return m_ip_pic_ptr->eof();
00455 }

Generated on Tue Dec 13 14:47:15 2005 for guliverkli by  doxygen 1.4.5