ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4RTJpegCoder.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4RTJpegCoder.cc
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 
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
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
116 {
117  for(int n=0; n<4; n++){
118  ForwardDCT(mYBlock[n]);
119  Quantization(0);
120  CodeHuffman(0);
121  }
123  Quantization(1);
124  CodeHuffman(1);
125 
127  Quantization(2);
128  CodeHuffman(2);
129 }
130 
131 void
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
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
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
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
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
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 = 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 );
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 );
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
359 {
360  mOBSP->SetByte( M_Marker );
361  mOBSP->SetByte( M_EOI );
362 }
363 
364 //SetJpegProperty
365 void
367 {
368  mProperty = aProperty;
369  mProperty.Dimension = 3;
371  mProperty.Format = 1;
374  mProperty.HThumbnail = 0;
375  mProperty.VThumbnail = 0;
376 }