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