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