Geant4 Cross Reference |
1 // 2 // ******************************************************************** 3 // * License and Disclaimer * 4 // * * 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. * 10 // * * 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitation of liability. * 17 // * * 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboration. * 20 // * By using, copying, modifying or distributing the software (or * 21 // * any work based on the software) you agree to acknowledge its * 22 // * use in resulting scientific publications, and indicate your * 23 // * acceptance of all terms of the Geant4 Software license. * 24 // ******************************************************************** 25 // 26 // 27 // 28 // 29 // 30 31 #include <stdlib.h> 32 #include <string.h> 33 #include <cmath> 34 35 #include "G4RTJpeg.hh" 36 #include "G4RTOutBitStream.hh" 37 #include "G4RTJpegMaker.hh" 38 #include "G4RTJpegCoder.hh" 39 #include "G4RTJpegCoderTables.hh" 40 41 42 G4JpegCoder::G4JpegCoder(u_char* colorR,u_char* colorG,u_char* colorB) 43 { 44 mRgb[0] = colorR; 45 mRgb[1] = colorG; 46 mRgb[2] = colorB; 47 48 mPreDC[0] = mPreDC[1] = mPreDC[2] = 0; 49 mOBSP = 0; 50 51 for(int n=0; n<8; n++) 52 for(int im=0; im<8; im++) 53 mCosT[n][im] = std::cos((2 * im + 1) * n * PaiDiv16); 54 } 55 56 G4JpegCoder::~G4JpegCoder(void) 57 {} 58 59 void 60 G4JpegCoder::GetJpegData(char** aJpegData, int& size) 61 { 62 if (mOBSP != 0){ 63 *aJpegData = (char*)mOBSP->GetStreamAddress(); 64 size = mOBSP->GetStreamSize(); 65 } 66 else{ 67 *aJpegData = 0; 68 size = 0; 69 } 70 71 } 72 73 int 74 G4JpegCoder::DoCoding(void) 75 { 76 mNumVUnits = (mProperty.nRow / 16) + ((mProperty.nRow % 16) ? 1 : 0); 77 mNumHUnits = (mProperty.nColumn / 16) + ((mProperty.nColumn % 16) ? 1 : 0); 78 79 int size = mProperty.nColumn * mProperty.nRow * 3; 80 if(size < 10240) 81 size = 10240; 82 83 try{ 84 mOBSP = new G4OutBitStream(size); 85 WriteHeader(); 86 for(int yu=0; yu<mNumVUnits; yu++){ 87 for(int xu=0; xu<mNumHUnits; xu++){ 88 makeYCC(xu, yu); 89 90 //mRgb->YCrCb 91 #ifdef GRAY 92 for(int i=0; i<64; i++) 93 mCbBlock[i] = mCrBlock[i] = 0; 94 #endif 95 CodeMCU(); 96 } 97 } 98 WriteEOI(); 99 return M_NoError; 100 } 101 102 catch(G4MemoryError &me){ 103 return M_RuntimeError; 104 } 105 catch(G4BufferError &be){ 106 return M_RuntimeError; 107 } 108 catch(G4IndexError &ie){ 109 return M_RuntimeError; 110 } 111 } 112 113 //MCU 114 void 115 G4JpegCoder::CodeMCU(void) 116 { 117 for(int n=0; n<4; n++){ 118 ForwardDCT(mYBlock[n]); 119 Quantization(0); 120 CodeHuffman(0); 121 } 122 ForwardDCT(mCbBlock); 123 Quantization(1); 124 CodeHuffman(1); 125 126 ForwardDCT(mCrBlock); 127 Quantization(2); 128 CodeHuffman(2); 129 } 130 131 void 132 G4JpegCoder::makeYCC(int ux, int uy) 133 { 134 u_char rv, gv, bv; 135 int tCrBlock[4][64]; 136 int tCbBlock[4][64]; 137 138 for(int u=0; u<4; u++){ 139 int *yp = mYBlock[u]; 140 int *cbp = tCbBlock[u]; 141 int *crp = tCrBlock[u]; 142 143 int sx = ux * 16 + ((u&1) ? 8 : 0); 144 int ex = sx + 8; 145 int sy = uy * 16 + ((u>1) ? 8 : 0); 146 int ey = sy + 8; 147 148 for(int iv=sy; iv<ey; iv++){ 149 int ii = iv < mProperty.nRow ? iv : mProperty.nRow - 1; 150 for(int ih=sx; ih<ex; ih++){ 151 int jj = ih < mProperty.nColumn ? ih : mProperty.nColumn - 1; 152 int index = ii * mProperty.nColumn + jj; 153 rv = mRgb[0][index]; 154 gv = mRgb[1][index]; 155 bv = mRgb[2][index]; 156 157 *yp++ = int((0.2990 * rv) + (0.5870 * gv) + (0.1140 * bv) - 128) 158 ; 159 *cbp++ = int(-(0.1687 * rv) - (0.3313 * gv) + (0.5000 * bv)); 160 *crp++ = int((0.5000 * rv) - (0.4187 * gv) - (0.0813 * bv)); 161 } // ih 162 } //iv 163 } //u 164 165 int n = 0; 166 for(int b=0; b<4; b++){ 167 switch(b){ 168 case 0: n=0; break; 169 case 1: n=4; break; 170 case 2: n=32; break; 171 case 3: n=36; 172 } 173 for(int y=0; y<8; y+=2){ 174 for(int x=0; x<8; x+=2){ 175 int idx = y * 8 + x; 176 mCrBlock[n] = tCrBlock[b][idx]; 177 mCbBlock[n] = tCbBlock[b][idx]; 178 n++; 179 } 180 n += 4; 181 } 182 } 183 } 184 185 void 186 G4JpegCoder::CodeHuffman(int cs) 187 { 188 const G4HuffmanCodeTable& dcT = cs ? CDcHuffmanT : YDcHuffmanT; 189 const G4HuffmanCodeTable& acT = cs ? CAcHuffmanT : YAcHuffmanT; 190 const int eobIdx = cs ? CEOBidx : YEOBidx; 191 const int zrlIdx = cs ? CZRLidx : YZRLidx; 192 193 int diff = mDCTData[0] - mPreDC[cs]; 194 mPreDC[cs] = mDCTData[0]; 195 int absDiff = std::abs(diff); 196 int dIdx = 0; 197 198 while(absDiff > 0){ 199 absDiff >>= 1; 200 dIdx++; 201 } 202 if(dIdx > dcT.numOfElement) 203 throw(G4IndexError(dcT.numOfElement, dIdx, "CodeHuffman:DC")); 204 mOBSP->SetBits((dcT.CodeT)[dIdx], (dcT.SizeT)[dIdx]); 205 206 if(dIdx){ 207 if(diff < 0) 208 diff--; 209 mOBSP->SetBits(diff, dIdx); 210 } 211 212 int run = 0; 213 for(int n=1; n<64; n++){ 214 int absCoefficient = std::abs( mDCTData[ Zigzag[n] ] ); 215 if( absCoefficient ){ 216 while( run > 15 ){ 217 mOBSP->SetBits((acT.CodeT)[zrlIdx], (acT.SizeT)[zrlIdx]); 218 run -= 16; 219 } 220 int is = 0; 221 while( absCoefficient > 0 ){ 222 absCoefficient >>= 1; 223 is++; 224 } 225 int aIdx = run * 10 + is + (run == 15); 226 if( aIdx >= acT.numOfElement ) 227 throw( G4IndexError( acT.numOfElement, aIdx, "CodeHuffman:AC" ) 228 ); 229 mOBSP->SetBits( (acT.CodeT)[aIdx], (acT.SizeT)[aIdx] ); 230 int v = mDCTData[ Zigzag[n] ]; 231 if( v < 0 ) 232 v--; 233 mOBSP->SetBits( v, is ); 234 run = 0; 235 } 236 else{ 237 if(n == 63) 238 mOBSP->SetBits( (acT.CodeT)[eobIdx], (acT.SizeT)[eobIdx] ); 239 else 240 run++; 241 } 242 } 243 } 244 245 246 void 247 G4JpegCoder::Quantization(int cs) 248 { 249 int* qt = (int*)(cs ? CQuantumT : YQuantumT); 250 for( int i=0; i<64; i++ ){ 251 mDCTData[i] /= qt[i]; 252 } 253 } 254 255 256 void 257 G4JpegCoder::ForwardDCT(int* picData) 258 { 259 for( int v=0; v<8; v++ ){ 260 double cv = v ? 1.0 : DisSqrt2; 261 for( int u=0; u<8; u++ ){ 262 double cu = u ? 1.0 : DisSqrt2; 263 double sum = 0; 264 for( int y=0; y<8; y++ ) 265 for( int x=0; x<8; x++ ) 266 sum += picData[ y * 8 + x ] * mCosT[u][x] * mCosT[v][y]; 267 mDCTData[ v * 8 + u ] = int( sum * cu * cv / 4 ); 268 } 269 } 270 } 271 272 273 void 274 G4JpegCoder::WriteHeader( void ) 275 { 276 int i = 0; //counter 277 //SOI 278 mOBSP->SetByte( M_Marker ); //FF 279 mOBSP->SetByte( M_SOI ); //SOI 280 281 //APP0(JFIF Header) 282 mOBSP->SetByte( M_Marker ); //FF 283 mOBSP->SetByte( M_APP0 ); //APP0 284 mOBSP->SetWord( JFIFLength ); //parameter 285 mOBSP->CopyByte( (char*)JFIF, 5 ); //"JFIF\0" 286 mOBSP->SetWord( JFIFVersion ); //Version 287 mOBSP->SetByte( mProperty.Units ); 288 mOBSP->SetWord( mProperty.HDensity ); 289 mOBSP->SetWord( mProperty.VDensity ); 290 mOBSP->SetByte( 0 ); 291 mOBSP->SetByte( 0 ); 292 293 //comment 294 if( mProperty.Comment != 0 ){ 295 mOBSP->SetByte( M_Marker ); //FF 296 mOBSP->SetByte( M_COM ); //comment 297 int length = (int)strlen( mProperty.Comment ) + 1; 298 mOBSP->SetWord( length + 2 ); 299 mOBSP->CopyByte( mProperty.Comment, length ); 300 } 301 302 //DQT 303 mOBSP->SetByte( M_Marker ); 304 mOBSP->SetByte( M_DQT ); 305 mOBSP->SetWord( 67 ); 306 mOBSP->SetByte( 0 ); 307 for( i=0; i<64; i++ ) 308 mOBSP->SetByte( u_char( YQuantumT[Zigzag[i]] ) ); 309 mOBSP->SetByte( M_Marker ); 310 mOBSP->SetByte( M_DQT ); 311 mOBSP->SetWord( 67 ); 312 mOBSP->SetByte( 1 ); 313 for( i=0; i<64; i++ ) 314 mOBSP->SetByte( u_char( CQuantumT[Zigzag[i]] ) ); 315 // DHT 316 mOBSP->CopyByte( (char*)YDcDht, DcDhtLength ); 317 mOBSP->CopyByte( (char*)CDcDht, DcDhtLength ); 318 mOBSP->CopyByte( (char*)YAcDht, AcDhtLength ); 319 mOBSP->CopyByte( (char*)CAcDht, AcDhtLength ); 320 321 // Frame Header 322 mOBSP->SetByte( M_Marker ); // FF 323 mOBSP->SetByte( M_SOF0 ); 324 mOBSP->SetWord( 3 * mProperty.Dimension + 8 ); 325 mOBSP->SetByte( mProperty.SamplePrecision ); 326 mOBSP->SetWord( mProperty.nRow ); 327 mOBSP->SetWord( mProperty.nColumn ); 328 mOBSP->SetByte( mProperty.Dimension ); 329 330 mOBSP->SetByte( 0 ); 331 mOBSP->SetByte( YSampleF ); 332 mOBSP->SetByte( 0 ); 333 334 mOBSP->SetByte( 1 ); 335 mOBSP->SetByte( CSampleF ); 336 337 mOBSP->SetByte( 1 ); 338 mOBSP->SetByte( 2 ); 339 mOBSP->SetByte( CSampleF ); 340 mOBSP->SetByte( 1 ); 341 342 //Scan Header 343 mOBSP->SetByte( M_Marker ); 344 mOBSP->SetByte( M_SOS ); 345 mOBSP->SetWord( 2 * mProperty.Dimension + 6 ); 346 mOBSP->SetByte( mProperty.Dimension ); 347 for( i=0; i<mProperty.Dimension; i++ ){ 348 mOBSP->SetByte( i ); 349 mOBSP->SetByte( i==0 ? 0 : 0x11 ); 350 } 351 mOBSP->SetByte( 0 ); //Ss 352 mOBSP->SetByte( 63 ); //Se 353 mOBSP->SetByte( 0 ); //Ah,Al 354 } 355 356 //EOI 357 void 358 G4JpegCoder::WriteEOI( void ) 359 { 360 mOBSP->SetByte( M_Marker ); 361 mOBSP->SetByte( M_EOI ); 362 } 363 364 //SetJpegProperty 365 void 366 G4JpegCoder::SetJpegProperty(const G4JpegProperty& aProperty ) 367 { 368 mProperty = aProperty; 369 mProperty.Dimension = 3; 370 mProperty.SamplePrecision = 8; 371 mProperty.Format = 1; 372 mProperty.MajorRevisions = 1; 373 mProperty.MinorRevisions = 2; 374 mProperty.HThumbnail = 0; 375 mProperty.VThumbnail = 0; 376 } 377