00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include <stdlib.h>
00033 #include <string.h>
00034 #include <cmath>
00035
00036 #include "G4RTJpeg.hh"
00037 #include "G4RTOutBitStream.hh"
00038 #include "G4RTJpegMaker.hh"
00039 #include "G4RTJpegCoder.hh"
00040 #include "G4RTJpegCoderTables.hh"
00041
00042
00043 G4JpegCoder::G4JpegCoder(u_char* colorR,u_char* colorG,u_char* colorB)
00044 {
00045 mRgb[0] = colorR;
00046 mRgb[1] = colorG;
00047 mRgb[2] = colorB;
00048
00049 mPreDC[0] = mPreDC[1] = mPreDC[2] = 0;
00050 mOBSP = 0;
00051
00052 for(int n=0; n<8; n++)
00053 for(int im=0; im<8; im++)
00054 mCosT[n][im] = std::cos((2 * im + 1) * n * PaiDiv16);
00055 }
00056
00057 G4JpegCoder::~G4JpegCoder(void)
00058 {}
00059
00060 void
00061 G4JpegCoder::GetJpegData(char** aJpegData, int& size)
00062 {
00063 if (mOBSP != 0){
00064 *aJpegData = (char*)mOBSP->GetStreamAddress();
00065 size = mOBSP->GetStreamSize();
00066 }
00067 else{
00068 *aJpegData = 0;
00069 size = 0;
00070 }
00071
00072 }
00073
00074 int
00075 G4JpegCoder::DoCoding(void)
00076 {
00077 mNumVUnits = (mProperty.nRow / 16) + ((mProperty.nRow % 16) ? 1 : 0);
00078 mNumHUnits = (mProperty.nColumn / 16) + ((mProperty.nColumn % 16) ? 1 : 0);
00079
00080 int size = mProperty.nColumn * mProperty.nRow * 3;
00081 if(size < 10240)
00082 size = 10240;
00083
00084 try{
00085 mOBSP = new G4OutBitStream(size);
00086 WriteHeader();
00087 for(int yu=0; yu<mNumVUnits; yu++){
00088 for(int xu=0; xu<mNumHUnits; xu++){
00089 makeYCC(xu, yu);
00090
00091
00092 #ifdef GRAY
00093 for(int i=0; i<64; i++)
00094 mCbBlock[i] = mCrBlock[i] = 0;
00095 #endif
00096 CodeMCU();
00097 }
00098 }
00099 WriteEOI();
00100 return M_NoError;
00101 }
00102
00103 catch(G4MemoryError &me){
00104 return M_RuntimeError;
00105 }
00106 catch(G4BufferError &be){
00107 return M_RuntimeError;
00108 }
00109 catch(G4IndexError &ie){
00110 return M_RuntimeError;
00111 }
00112 }
00113
00114
00115 void
00116 G4JpegCoder::CodeMCU(void)
00117 {
00118 for(int n=0; n<4; n++){
00119 ForwardDCT(mYBlock[n]);
00120 Quantization(0);
00121 CodeHuffman(0);
00122 }
00123 ForwardDCT(mCbBlock);
00124 Quantization(1);
00125 CodeHuffman(1);
00126
00127 ForwardDCT(mCrBlock);
00128 Quantization(2);
00129 CodeHuffman(2);
00130 }
00131
00132 void
00133 G4JpegCoder::makeYCC(int ux, int uy)
00134 {
00135 u_char rv, gv, bv;
00136 int tCrBlock[4][64];
00137 int tCbBlock[4][64];
00138
00139 for(int u=0; u<4; u++){
00140 int *yp = mYBlock[u];
00141 int *cbp = tCbBlock[u];
00142 int *crp = tCrBlock[u];
00143
00144 int sx = ux * 16 + ((u&1) ? 8 : 0);
00145 int ex = sx + 8;
00146 int sy = uy * 16 + ((u>1) ? 8 : 0);
00147 int ey = sy + 8;
00148
00149 for(int iv=sy; iv<ey; iv++){
00150 int ii = iv < mProperty.nRow ? iv : mProperty.nRow - 1;
00151 for(int ih=sx; ih<ex; ih++){
00152 int jj = ih < mProperty.nColumn ? ih : mProperty.nColumn - 1;
00153 int index = ii * mProperty.nColumn + jj;
00154 rv = mRgb[0][index];
00155 gv = mRgb[1][index];
00156 bv = mRgb[2][index];
00157
00158 *yp++ = int((0.2990 * rv) + (0.5870 * gv) + (0.1140 * bv) - 128)
00159 ;
00160 *cbp++ = int(-(0.1687 * rv) - (0.3313 * gv) + (0.5000 * bv));
00161 *crp++ = int((0.5000 * rv) - (0.4187 * gv) - (0.0813 * bv));
00162 }
00163 }
00164 }
00165
00166 int n = 0;
00167 for(int b=0; b<4; b++){
00168 switch(b){
00169 case 0: n=0; break;
00170 case 1: n=4; break;
00171 case 2: n=32; break;
00172 case 3: n=36;
00173 }
00174 for(int y=0; y<8; y+=2){
00175 for(int x=0; x<8; x+=2){
00176 int idx = y * 8 + x;
00177 mCrBlock[n] = tCrBlock[b][idx];
00178 mCbBlock[n] = tCbBlock[b][idx];
00179 n++;
00180 }
00181 n += 4;
00182 }
00183 }
00184 }
00185
00186 void
00187 G4JpegCoder::CodeHuffman(int cs)
00188 {
00189 const G4HuffmanCodeTable& dcT = cs ? CDcHuffmanT : YDcHuffmanT;
00190 const G4HuffmanCodeTable& acT = cs ? CAcHuffmanT : YAcHuffmanT;
00191 const int eobIdx = cs ? CEOBidx : YEOBidx;
00192 const int zrlIdx = cs ? CZRLidx : YZRLidx;
00193
00194 int diff = mDCTData[0] - mPreDC[cs];
00195 mPreDC[cs] = mDCTData[0];
00196 int absDiff = std::abs(diff);
00197 int dIdx = 0;
00198
00199 while(absDiff > 0){
00200 absDiff >>= 1;
00201 dIdx++;
00202 }
00203 if(dIdx > dcT.numOfElement)
00204 throw(G4IndexError(dcT.numOfElement, dIdx, "CodeHuffman:DC"));
00205 mOBSP->SetBits((dcT.CodeT)[dIdx], (dcT.SizeT)[dIdx]);
00206
00207 if(dIdx){
00208 if(diff < 0)
00209 diff--;
00210 mOBSP->SetBits(diff, dIdx);
00211 }
00212
00213 int run = 0;
00214 for(int n=1; n<64; n++){
00215 int absCoefficient = std::abs( mDCTData[ Zigzag[n] ] );
00216 if( absCoefficient ){
00217 while( run > 15 ){
00218 mOBSP->SetBits((acT.CodeT)[zrlIdx], (acT.SizeT)[zrlIdx]);
00219 run -= 16;
00220 }
00221 int is = 0;
00222 while( absCoefficient > 0 ){
00223 absCoefficient >>= 1;
00224 is++;
00225 }
00226 int aIdx = run * 10 + is + (run == 15);
00227 if( aIdx >= acT.numOfElement )
00228 throw( G4IndexError( acT.numOfElement, aIdx, "CodeHuffman:AC" )
00229 );
00230 mOBSP->SetBits( (acT.CodeT)[aIdx], (acT.SizeT)[aIdx] );
00231 int v = mDCTData[ Zigzag[n] ];
00232 if( v < 0 )
00233 v--;
00234 mOBSP->SetBits( v, is );
00235 run = 0;
00236 }
00237 else{
00238 if(n == 63)
00239 mOBSP->SetBits( (acT.CodeT)[eobIdx], (acT.SizeT)[eobIdx] );
00240 else
00241 run++;
00242 }
00243 }
00244 }
00245
00246
00247 void
00248 G4JpegCoder::Quantization(int cs)
00249 {
00250 int* qt = (int*)(cs ? CQuantumT : YQuantumT);
00251 for( int i=0; i<64; i++ ){
00252 mDCTData[i] /= qt[i];
00253 }
00254 }
00255
00256
00257 void
00258 G4JpegCoder::ForwardDCT(int* picData)
00259 {
00260 for( int v=0; v<8; v++ ){
00261 double cv = v ? 1.0 : DisSqrt2;
00262 for( int u=0; u<8; u++ ){
00263 double cu = u ? 1.0 : DisSqrt2;
00264 double sum = 0;
00265
00266 for( int y=0; y<8; y++ )
00267 for( int x=0; x<8; x++ )
00268 sum += picData[ y * 8 + x ] * mCosT[u][x] * mCosT[v][y];
00269 mDCTData[ v * 8 + u ] = int( sum * cu * cv / 4 );
00270 }
00271 }
00272 }
00273
00274
00275 void
00276 G4JpegCoder::WriteHeader( void )
00277 {
00278 int i = 0;
00279
00280 mOBSP->SetByte( M_Marker );
00281 mOBSP->SetByte( M_SOI );
00282
00283
00284 mOBSP->SetByte( M_Marker );
00285 mOBSP->SetByte( M_APP0 );
00286 mOBSP->SetWord( JFIFLength );
00287 mOBSP->CopyByte( (char*)JFIF, 5 );
00288 mOBSP->SetWord( JFIFVersion );
00289 mOBSP->SetByte( mProperty.Units );
00290 mOBSP->SetWord( mProperty.HDensity );
00291 mOBSP->SetWord( mProperty.VDensity );
00292 mOBSP->SetByte( 0 );
00293 mOBSP->SetByte( 0 );
00294
00295
00296 if( mProperty.Comment != 0 ){
00297 mOBSP->SetByte( M_Marker );
00298 mOBSP->SetByte( M_COM );
00299 int length = strlen( mProperty.Comment ) + 1;
00300 mOBSP->SetWord( length + 2 );
00301 mOBSP->CopyByte( mProperty.Comment, length );
00302 }
00303
00304
00305 mOBSP->SetByte( M_Marker );
00306 mOBSP->SetByte( M_DQT );
00307 mOBSP->SetWord( 67 );
00308 mOBSP->SetByte( 0 );
00309 for( i=0; i<64; i++ )
00310 mOBSP->SetByte( u_char( YQuantumT[Zigzag[i]] ) );
00311 mOBSP->SetByte( M_Marker );
00312 mOBSP->SetByte( M_DQT );
00313 mOBSP->SetWord( 67 );
00314 mOBSP->SetByte( 1 );
00315 for( i=0; i<64; i++ )
00316 mOBSP->SetByte( u_char( CQuantumT[Zigzag[i]] ) );
00317
00318 mOBSP->CopyByte( (char*)YDcDht, DcDhtLength );
00319 mOBSP->CopyByte( (char*)CDcDht, DcDhtLength );
00320 mOBSP->CopyByte( (char*)YAcDht, AcDhtLength );
00321 mOBSP->CopyByte( (char*)CAcDht, AcDhtLength );
00322
00323
00324 mOBSP->SetByte( M_Marker );
00325 mOBSP->SetByte( M_SOF0 );
00326 mOBSP->SetWord( 3 * mProperty.Dimension + 8 );
00327 mOBSP->SetByte( mProperty.SamplePrecision );
00328 mOBSP->SetWord( mProperty.nRow );
00329 mOBSP->SetWord( mProperty.nColumn );
00330 mOBSP->SetByte( mProperty.Dimension );
00331
00332 mOBSP->SetByte( 0 );
00333 mOBSP->SetByte( YSampleF );
00334 mOBSP->SetByte( 0 );
00335
00336 mOBSP->SetByte( 1 );
00337 mOBSP->SetByte( CSampleF );
00338
00339 mOBSP->SetByte( 1 );
00340 mOBSP->SetByte( 2 );
00341 mOBSP->SetByte( CSampleF );
00342 mOBSP->SetByte( 1 );
00343
00344
00345 mOBSP->SetByte( M_Marker );
00346 mOBSP->SetByte( M_SOS );
00347 mOBSP->SetWord( 2 * mProperty.Dimension + 6 );
00348 mOBSP->SetByte( mProperty.Dimension );
00349 for( i=0; i<mProperty.Dimension; i++ ){
00350 mOBSP->SetByte( i );
00351 mOBSP->SetByte( i==0 ? 0 : 0x11 );
00352 }
00353 mOBSP->SetByte( 0 );
00354 mOBSP->SetByte( 63 );
00355 mOBSP->SetByte( 0 );
00356 }
00357
00358
00359 void
00360 G4JpegCoder::WriteEOI( void )
00361 {
00362 mOBSP->SetByte( M_Marker );
00363 mOBSP->SetByte( M_EOI );
00364 }
00365
00366
00367 void
00368 G4JpegCoder::SetJpegProperty(const G4JpegProperty& aProperty )
00369 {
00370 mProperty = aProperty;
00371 mProperty.Dimension = 3;
00372 mProperty.SamplePrecision = 8;
00373 mProperty.Format = 1;
00374 mProperty.MajorRevisions = 1;
00375 mProperty.MinorRevisions = 2;
00376 mProperty.HThumbnail = 0;
00377 mProperty.VThumbnail = 0;
00378 }