// // ******************************************************************** // * License and Disclaimer * // * * // * The Geant4 software is copyright of the Copyright Holders of * // * the Geant4 Collaboration. It is provided under the terms and * // * conditions of the Geant4 Software License, included in the file * // * LICENSE and available at http://cern.ch/geant4/license . These * // * include a list of copyright holders. * // * * // * Neither the authors of this software system, nor their employing * // * institutes,nor the agencies providing financial support for this * // * work make any representation or warranty, express or implied, * // * regarding this software system or assume any liability for its * // * use. Please see the license in the file LICENSE and URL above * // * for the full disclaimer and the limitation of liability. * // * * // * This code implementation is the result of the scientific and * // * technical work of the GEANT4 collaboration. * // * By using, copying, modifying or distributing the software (or * // * any work based on the software) you agree to acknowledge its * // * use in resulting scientific publications, and indicate your * // * acceptance of all terms of the Geant4 Software license. * // ******************************************************************** // // // $Id: G4RTJpegCoder.cc,v 1.6 2006/06/29 21:23:55 gunter Exp $ // GEANT4 tag $Name: geant4-09-04-ref-00 $ // // // #include #include #include #include "G4RTJpeg.hh" #include "G4RTOutBitStream.hh" #include "G4RTJpegMaker.hh" #include "G4RTJpegCoder.hh" #include "G4RTJpegCoderTables.hh" G4JpegCoder::G4JpegCoder(u_char* colorR,u_char* colorG,u_char* colorB) { mRgb[0] = colorR; mRgb[1] = colorG; mRgb[2] = colorB; mPreDC[0] = mPreDC[1] = mPreDC[2] = 0; mOBSP = 0; for(int n=0; n<8; n++) for(int m=0; m<8; m++) mCosT[n][m] = std::cos((2 * m + 1) * n * PaiDiv16); } G4JpegCoder::~G4JpegCoder(void) { if(mOBSP != 0) delete mOBSP; } void G4JpegCoder::GetJpegData(char** aJpegData, int& size) { if (mOBSP != 0){ *aJpegData = (char*)mOBSP->GetStreamAddress(); size = mOBSP->GetStreamSize(); } else{ *aJpegData = 0; size = 0; } } int G4JpegCoder::DoCoding(void) { mNumVUnits = (mProperty.nRow / 16) + ((mProperty.nRow % 16) ? 1 : 0); mNumHUnits = (mProperty.nColumn / 16) + ((mProperty.nColumn % 16) ? 1 : 0); int size = mProperty.nColumn * mProperty.nRow * 3; if(size < 10240) size = 10240; try{ mOBSP = new G4OutBitStream(size); WriteHeader(); for(int yu=0; yuYCrCb #ifdef GRAY for(int i=0; i<64; i++) mCbBlock[i] = mCrBlock[i] = 0; #endif CodeMCU(); } } WriteEOI(); return M_NoError; } catch(G4MemoryError &me){ return M_RuntimeError; } catch(G4BufferError &be){ return M_RuntimeError; } catch(G4IndexError &ie){ return M_RuntimeError; } } //MCU void G4JpegCoder::CodeMCU(void) { for(int n=0; n<4; n++){ ForwardDCT(mYBlock[n]); Quantization(0); CodeHuffman(0); } ForwardDCT(mCbBlock); Quantization(1); CodeHuffman(1); ForwardDCT(mCrBlock); Quantization(2); CodeHuffman(2); } void G4JpegCoder::makeYCC(int ux, int uy) { u_char rv, gv, bv; int tCrBlock[4][64]; int tCbBlock[4][64]; for(int u=0; u<4; u++){ int *yp = mYBlock[u]; int *cbp = tCbBlock[u]; int *crp = tCrBlock[u]; int sx = ux * 16 + ((u&1) ? 8 : 0); int ex = sx + 8; int sy = uy * 16 + ((u>1) ? 8 : 0); int ey = sy + 8; for(int iv=sy; iv 0){ absDiff >>= 1; dIdx++; } if(dIdx > dcT.numOfElement) throw(G4IndexError(dcT.numOfElement, dIdx, "CodeHuffman:DC")); mOBSP->SetBits((dcT.CodeT)[dIdx], (dcT.SizeT)[dIdx]); if(dIdx){ if(diff < 0) diff--; mOBSP->SetBits(diff, dIdx); } int run = 0; for(int n=1; n<64; n++){ int absCoefficient = std::abs( mDCTData[ Zigzag[n] ] ); if( absCoefficient ){ while( run > 15 ){ mOBSP->SetBits((acT.CodeT)[zrlIdx], (acT.SizeT)[zrlIdx]); run -= 16; } int s = 0; while( absCoefficient > 0 ){ absCoefficient >>= 1; s++; } int aIdx = run * 10 + s + (run == 15); if( aIdx >= acT.numOfElement ) throw( G4IndexError( acT.numOfElement, aIdx, "CodeHuffman:AC" ) ); mOBSP->SetBits( (acT.CodeT)[aIdx], (acT.SizeT)[aIdx] ); int v = mDCTData[ Zigzag[n] ]; if( v < 0 ) v--; mOBSP->SetBits( v, s ); run = 0; } else{ if(n == 63) mOBSP->SetBits( (acT.CodeT)[eobIdx], (acT.SizeT)[eobIdx] ); else run++; } } } void G4JpegCoder::Quantization(int cs) { int* qt = (int*)(cs ? CQuantumT : YQuantumT); for( int i=0; i<64; i++ ){ mDCTData[i] /= qt[i]; } } void G4JpegCoder::ForwardDCT(int* picData) { for( int v=0; v<8; v++ ){ double cv = v ? 1.0 : DisSqrt2; for( int u=0; u<8; u++ ){ double cu = u ? 1.0 : DisSqrt2; double sum = 0; for( int y=0; y<8; y++ ) for( int x=0; x<8; x++ ) sum += picData[ y * 8 + x ] * mCosT[u][x] * mCosT[v][y]; mDCTData[ v * 8 + u ] = int( sum * cu * cv / 4 ); } } } void G4JpegCoder::WriteHeader( void ) { int i = 0; //counter //SOI mOBSP->SetByte( M_Marker ); //FF mOBSP->SetByte( M_SOI ); //SOI //APP0(JFIF Header) mOBSP->SetByte( M_Marker ); //FF mOBSP->SetByte( M_APP0 ); //APP0 mOBSP->SetWord( JFIFLength ); //parameter mOBSP->CopyByte( (char*)JFIF, 5 ); //"JFIF\0" mOBSP->SetWord( JFIFVersion ); //Version mOBSP->SetByte( mProperty.Units ); mOBSP->SetWord( mProperty.HDensity ); mOBSP->SetWord( mProperty.VDensity ); mOBSP->SetByte( 0 ); mOBSP->SetByte( 0 ); //comment if( mProperty.Comment != 0 ){ mOBSP->SetByte( M_Marker ); //FF mOBSP->SetByte( M_COM ); //comment int length = strlen( mProperty.Comment ) + 1; mOBSP->SetWord( length + 2 ); mOBSP->CopyByte( mProperty.Comment, length ); } //DQT mOBSP->SetByte( M_Marker ); mOBSP->SetByte( M_DQT ); mOBSP->SetWord( 67 ); mOBSP->SetByte( 0 ); for( i=0; i<64; i++ ) mOBSP->SetByte( u_char( YQuantumT[Zigzag[i]] ) ); mOBSP->SetByte( M_Marker ); mOBSP->SetByte( M_DQT ); mOBSP->SetWord( 67 ); mOBSP->SetByte( 1 ); for( i=0; i<64; i++ ) mOBSP->SetByte( u_char( CQuantumT[Zigzag[i]] ) ); // DHT mOBSP->CopyByte( (char*)YDcDht, DcDhtLength ); mOBSP->CopyByte( (char*)CDcDht, DcDhtLength ); mOBSP->CopyByte( (char*)YAcDht, AcDhtLength ); mOBSP->CopyByte( (char*)CAcDht, AcDhtLength ); // Frame Header mOBSP->SetByte( M_Marker ); // FF mOBSP->SetByte( M_SOF0 ); mOBSP->SetWord( 3 * mProperty.Dimension + 8 ); mOBSP->SetByte( mProperty.SamplePrecision ); mOBSP->SetWord( mProperty.nRow ); mOBSP->SetWord( mProperty.nColumn ); mOBSP->SetByte( mProperty.Dimension ); mOBSP->SetByte( 0 ); mOBSP->SetByte( YSampleF ); mOBSP->SetByte( 0 ); mOBSP->SetByte( 1 ); mOBSP->SetByte( CSampleF ); mOBSP->SetByte( 1 ); mOBSP->SetByte( 2 ); mOBSP->SetByte( CSampleF ); mOBSP->SetByte( 1 ); //Scan Header mOBSP->SetByte( M_Marker ); mOBSP->SetByte( M_SOS ); mOBSP->SetWord( 2 * mProperty.Dimension + 6 ); mOBSP->SetByte( mProperty.Dimension ); for( i=0; iSetByte( i ); mOBSP->SetByte( i==0 ? 0 : 0x11 ); } mOBSP->SetByte( 0 ); //Ss mOBSP->SetByte( 63 ); //Se mOBSP->SetByte( 0 ); //Ah,Al } //EOI void G4JpegCoder::WriteEOI( void ) { mOBSP->SetByte( M_Marker ); mOBSP->SetByte( M_EOI ); } //SetJpegProperty void G4JpegCoder::SetJpegProperty(const G4JpegProperty& aProperty ) { mProperty = aProperty; mProperty.Dimension = 3; mProperty.SamplePrecision = 8; mProperty.Format = 1; mProperty.MajorRevisions = 1; mProperty.MinorRevisions = 2; mProperty.HThumbnail = 0; mProperty.VThumbnail = 0; }