CMS 3D CMS Logo

FWTEveViewer.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: Subsystem/Package
4 // Class : FWTEveViewer
5 //
6 // Implementation:
7 // [Notes on implementation]
8 //
9 // Original Author:
10 // Created: Tue, 03 Feb 2015 21:46:04 GMT
11 //
12 
13 // system include files
14 
15 #include "png.h"
16 #include "jpeglib.h"
17 
18 
19 // user include files
20 
21 #include "TMath.h"
22 #include "TGLIncludes.h"
23 #include "TGLFBO.h"
24 
27 
28 //
29 // constants, enums and typedefs
30 //
31 
32 //
33 // static data member definitions
34 //
35 
36 //
37 // constructors and destructor
38 //
39 FWTEveViewer::FWTEveViewer(const char* n, const char* t) :
40  TEveViewer(n, t),
41  m_fwGlViewer(nullptr)
42 {}
43 
44 // FWTEveViewer::FWTEveViewer(const FWTEveViewer& rhs)
45 // {
46 // // do actual copying here;
47 // }
48 
50 {
51  if (m_thr) m_thr->detach();
52 
53  {
54  std::unique_lock<std::mutex> lk(m_moo);
55 
56  m_thr_exit = true;
57  m_cnd.notify_one();
58  }
59 
60  delete m_thr;
61 }
62 
63 //
64 // assignment operators
65 //
66 // const FWTEveViewer& FWTEveViewer::operator=(const FWTEveViewer& rhs)
67 // {
68 // //An exception safe implementation is
69 // FWTEveViewer temp(rhs);
70 // swap(rhs);
71 //
72 // return *this;
73 // }
74 
75 //==============================================================================
76 
77 //
78 // member functions
79 //
80 
82 {
83  std::unique_lock<std::mutex> lko(m_moo);
84 
85  m_thr = new std::thread([=]() {
86  { std::unique_lock<std::mutex> lk(m_moo); m_cnd.notify_one(); }
87  while (true)
88  {
89  {
90  std::unique_lock<std::mutex> lk(m_moo);
91  m_cnd.wait(lk);
92 
93  if (m_thr_exit)
94  {
95  return;
96  }
97  }
98  if (m_name.EndsWith(".jpg"))
99  {
101  }
102  else
103  {
105  }
106 
107  m_prom.set_value(0);
108  }
109  });
110 
111  m_cnd.wait(lko);
112 }
113 
114 //------------------------------------------------------------------------------
115 
117 {
118  TGCompositeFrame* cf = GetGUICompositeFrame();
119 
120  m_fwGlViewer = new FWTGLViewer(cf);
121  SetGLViewer(m_fwGlViewer, m_fwGlViewer->GetFrame());
122 
123  cf->AddFrame(fGLViewerFrame, new TGLayoutHints(kLHintsNormal | kLHintsExpandX | kLHintsExpandY));
124 
125  fGLViewerFrame->MapWindow();
126 
127  if (fEveFrame == nullptr)
128  PreUndock();
129 
130  return m_fwGlViewer;
131 }
132 
133 std::future<int>
134 FWTEveViewer::CaptureAndSaveImage(const TString& file, int height)
135 {
136  static const TString eh("FWTEveViewer::CaptureAndSaveImage");
137 
138  TGLFBO *fbo = nullptr;
139  if (height == -1)
140  fbo = m_fwGlViewer->MakeFbo();
141  else
142  fbo = m_fwGlViewer->MakeFboHeight(height);
143 
144  if (fbo == nullptr)
145  {
146  ::Error(eh, "Returned FBO is 0.");
147  m_prom = std::promise<int>();
148  m_prom.set_value(-1);
149  return m_prom.get_future();
150  }
151 
152  int ww, hh;
153  if (fbo->GetIsRescaled())
154  {
155  ww = TMath::Nint(fbo->GetW() * fbo->GetWScale());
156  hh = TMath::Nint(fbo->GetH() * fbo->GetHScale());
157  }
158  else
159  {
160  ww = fbo->GetW();
161  hh = fbo->GetH();
162  }
163 
164  fbo->SetAsReadBuffer();
165 
166  size_t bufsize = 3 * ww * hh;
167  if (bufsize != m_imgBuffer.size())
168  {
169  m_imgBuffer.resize(bufsize);
170  }
171 
172  glPixelStorei(GL_PACK_ALIGNMENT, 1);
173  glReadPixels(0, 0, ww, hh, GL_RGB, GL_UNSIGNED_BYTE, &m_imgBuffer[0]);
174 
175  if (m_thr == nullptr) spawn_image_thread();
176 
177  {
178  std::unique_lock<std::mutex> lk(m_moo);
179 
180  m_prom = std::promise<int>();
181  m_name = file;
182  m_ww = ww;
183  m_hh = hh;
184 
185  m_cnd.notify_one();
186  }
187 
188  return m_prom.get_future();
189 }
190 
191 //
192 // const member functions
193 //
194 
195 //
196 // static member functions
197 //
198 
199 bool FWTEveViewer::SavePng(const TString& file, UChar_t* xx, int ww, int hh)
200 {
201  png_structp png_ptr;
202  png_infop info_ptr;
203 
204  /* Create and initialize the png_struct with the desired error handler
205  * functions. If you want to use the default stderr and longjump method,
206  * you can supply NULL for the last three parameters. We also check that
207  * the library version is compatible with the one used at compile time,
208  * in case we are using dynamically linked libraries. REQUIRED.
209  */
210  png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
211  if (png_ptr == nullptr) {
212  printf("Error creating png write struct\n");
213  return false;
214  }
215 
216  // Allocate/initialize the image information data. REQUIRED
217  info_ptr = png_create_info_struct(png_ptr);
218  if (info_ptr == nullptr) {
219  printf("Error creating png info struct\n");
220  png_destroy_write_struct(&png_ptr, &info_ptr);
221  return false;
222  }
223 
224  /*// Set error handling. REQUIRED if you aren't supplying your own
225  // error handling functions in the png_create_write_struct() call.
226  if (setjmp(png_jmpbuf(png_ptr))) {
227  // If we get here, we had a problem reading the file
228  png_destroy_write_struct(&png_ptr, &info_ptr);
229  ilSetError(IL_LIB_PNG_ERROR);
230  return IL_FALSE;
231  }*/
232 
233  FILE *fp = fopen(file, "w");
234 
235  png_init_io(png_ptr, fp);
236 
237 
238  // Use PNG_INTERLACE_ADAM7 for interlacing
239  png_set_IHDR(png_ptr, info_ptr, ww, hh, 8, PNG_COLOR_TYPE_RGB,
240  PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
241 
242  /* Optional gamma chunk is strongly suggested if you have any guess
243  * as to the correct gamma of the image.
244  */
245  // png_set_gAMA(png_ptr, info_ptr, gamma);
246 
247  // Optionally write comments into the image.
248  // png_text text;
249  // text.key = "Generated by";
250  // text.text = "Generated by cmsShow";
251  // text.compression = PNG_TEXT_COMPRESSION_NONE;
252  // png_set_text(png_ptr, info_ptr, &text, 1);
253 
254  // Write the file header information. REQUIRED.
255  png_write_info(png_ptr, info_ptr);
256 
257  std::vector<UChar_t*> rows(hh);
258  {
259  int j = hh - 1;
260  for (int i = 0; i < hh; i++, j--) {
261  rows[i] = xx + j * ww * 3;
262  }
263  }
264 
265  // Writes the image.
266  png_write_image(png_ptr, &rows[0]);
267 
268  // It is REQUIRED to call this to finish writing the rest of the file
269  png_write_end(png_ptr, info_ptr);
270 
271  // clean up after the write, and ifree any memory allocated
272  png_destroy_write_struct(&png_ptr, &info_ptr);
273 
274  fclose(fp);
275 
276  return true;
277 }
278 
279 bool FWTEveViewer::SaveJpg(const TString& file, UChar_t* xx, int ww, int hh)
280 {
281  struct jpeg_compress_struct JpegInfo;
282  struct jpeg_error_mgr Error;
283 
284  JpegInfo.err = jpeg_std_error(&Error);
285 
286  // Now we can initialize the JPEG compression object.
287  jpeg_create_compress(&JpegInfo);
288 
289  FILE *fp = fopen(file, "w");
290  jpeg_stdio_dest(&JpegInfo, fp);
291 
292  JpegInfo.image_width = ww;
293  JpegInfo.image_height = hh;
294  JpegInfo.input_components = 3;
295  JpegInfo.in_color_space = JCS_RGB;
296 
297  jpeg_set_defaults(&JpegInfo);
298 
299  JpegInfo.write_JFIF_header = TRUE;
300 
301  // Set the quality output
302  // const int quality = 98;
303  // jpeg_set_quality(&JpegInfo, quality, true); // bool force_baseline ????
304 
305  jpeg_start_compress(&JpegInfo, TRUE);
306 
307  std::vector<UChar_t*> rows(hh);
308  {
309  int j = hh - 1;
310  for (int i = 0; i < hh; i++, j--) {
311  rows[i] = xx + j * ww * 3;
312  }
313  }
314 
315  jpeg_write_scanlines(&JpegInfo, &rows[0], hh);
316 
317  // Step 6: Finish compression
318  jpeg_finish_compress(&JpegInfo);
319 
320  // Step 7: release JPEG compression object
321 
322  // This is an important step since it will release a good deal of memory.
323  jpeg_destroy_compress(&JpegInfo);
324 
325  return true;
326 }
std::mutex m_moo
Definition: FWTEveViewer.h:77
#define TRUE
Definition: scimark2.h:12
TString m_name
Definition: FWTEveViewer.h:72
TGLFBO * MakeFboHeight(Int_t height, Bool_t pixel_object_scale=kTRUE)
Definition: FWTGLViewer.cc:132
std::condition_variable m_cnd
Definition: FWTEveViewer.h:78
std::thread * m_thr
Definition: FWTEveViewer.h:75
std::vector< unsigned char > m_imgBuffer
Definition: FWTEveViewer.h:70
#define nullptr
FWTEveViewer(const char *n="FWTEveViewer", const char *t="")
Definition: FWTEveViewer.cc:39
~FWTEveViewer() override
Definition: FWTEveViewer.cc:49
std::promise< int > m_prom
Definition: FWTEveViewer.h:76
static bool SaveJpg(const TString &file, UChar_t *xx, int ww, int hh)
std::future< int > CaptureAndSaveImage(const TString &file, int height=-1)
FWTGLViewer * m_fwGlViewer
Definition: FWTEveViewer.h:68
static bool SavePng(const TString &file, UChar_t *xx, int ww, int hh)
FWTGLViewer * SpawnFWTGLViewer()
TGLFBO * MakeFbo()
Definition: FWTGLViewer.cc:111
void spawn_image_thread()
Definition: FWTEveViewer.cc:81