source: trunk/source/visualization/RayTracer/src/G4RTJpegCoder.cc @ 1347

Last change on this file since 1347 was 1347, checked in by garnier, 13 years ago

geant4 tag 9.4

File size: 10.4 KB
Line 
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: geant4-09-04-ref-00 $
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
44G4JpegCoder::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
58G4JpegCoder::~G4JpegCoder(void)
59{
60  if(mOBSP != 0)
61                delete mOBSP;
62}
63
64void
65G4JpegCoder::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
78int
79G4JpegCoder::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
119void
120G4JpegCoder::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
136void
137G4JpegCoder::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
190void
191G4JpegCoder::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
251void
252G4JpegCoder::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
261void
262G4JpegCoder::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
279void
280G4JpegCoder::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
363void
364G4JpegCoder::WriteEOI( void )
365{
366  mOBSP->SetByte( M_Marker );
367  mOBSP->SetByte( M_EOI );
368}
369
370//SetJpegProperty
371void
372G4JpegCoder::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}
Note: See TracBrowser for help on using the repository browser.