Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 13:27:19

0001 // -*- C++ -*-
0002 //
0003 // Package:     Subsystem/Package
0004 // Class  :     FWTEveViewer
0005 //
0006 // Implementation:
0007 //     [Notes on implementation]
0008 //
0009 // Original Author:
0010 //         Created:  Tue, 03 Feb 2015 21:46:04 GMT
0011 //
0012 
0013 // system include files
0014 
0015 #include "png.h"
0016 #include "jpeglib.h"
0017 
0018 // user include files
0019 
0020 #include "TMath.h"
0021 #include "TGLIncludes.h"
0022 #include "TGLFBO.h"
0023 
0024 #include "Fireworks/Core/interface/FWTEveViewer.h"
0025 #include "Fireworks/Core/interface/FWTGLViewer.h"
0026 
0027 //
0028 // constants, enums and typedefs
0029 //
0030 
0031 //
0032 // static data member definitions
0033 //
0034 
0035 //
0036 // constructors and destructor
0037 //
0038 FWTEveViewer::FWTEveViewer(const char* n, const char* t) : TEveViewer(n, t), m_fwGlViewer(nullptr) {}
0039 
0040 // FWTEveViewer::FWTEveViewer(const FWTEveViewer& rhs)
0041 // {
0042 //    // do actual copying here;
0043 // }
0044 
0045 FWTEveViewer::~FWTEveViewer() {
0046   if (m_thr)
0047     m_thr->detach();
0048 
0049   {
0050     std::unique_lock<std::mutex> lk(m_moo);
0051 
0052     m_thr_exit = true;
0053     m_cnd.notify_one();
0054   }
0055 
0056   delete m_thr;
0057 }
0058 
0059 //
0060 // assignment operators
0061 //
0062 // const FWTEveViewer& FWTEveViewer::operator=(const FWTEveViewer& rhs)
0063 // {
0064 //   //An exception safe implementation is
0065 //   FWTEveViewer temp(rhs);
0066 //   swap(rhs);
0067 //
0068 //   return *this;
0069 // }
0070 
0071 //==============================================================================
0072 
0073 //
0074 // member functions
0075 //
0076 
0077 void FWTEveViewer::spawn_image_thread() {
0078   std::unique_lock<std::mutex> lko(m_moo);
0079 
0080   m_thr = new std::thread([=]() {
0081     {
0082       std::unique_lock<std::mutex> lk(m_moo);
0083       m_cnd.notify_one();
0084     }
0085     while (true) {
0086       {
0087         std::unique_lock<std::mutex> lk(m_moo);
0088         m_cnd.wait(lk);
0089 
0090         if (m_thr_exit) {
0091           return;
0092         }
0093       }
0094       if (m_name.EndsWith(".jpg")) {
0095         SaveJpg(m_name, &m_imgBuffer[0], m_ww, m_hh);
0096       } else {
0097         SavePng(m_name, &m_imgBuffer[0], m_ww, m_hh);
0098       }
0099 
0100       m_prom.set_value(0);
0101     }
0102   });
0103 
0104   m_cnd.wait(lko);
0105 }
0106 
0107 //------------------------------------------------------------------------------
0108 
0109 FWTGLViewer* FWTEveViewer::SpawnFWTGLViewer() {
0110   TGCompositeFrame* cf = GetGUICompositeFrame();
0111 
0112   m_fwGlViewer = new FWTGLViewer(cf);
0113   SetGLViewer(m_fwGlViewer, m_fwGlViewer->GetFrame());
0114 
0115   cf->AddFrame(fGLViewerFrame, new TGLayoutHints(kLHintsNormal | kLHintsExpandX | kLHintsExpandY));
0116 
0117   fGLViewerFrame->MapWindow();
0118 
0119   if (fEveFrame == nullptr)
0120     PreUndock();
0121 
0122   return m_fwGlViewer;
0123 }
0124 
0125 std::future<int> FWTEveViewer::CaptureAndSaveImage(const TString& file, int height) {
0126   static const TString eh("FWTEveViewer::CaptureAndSaveImage");
0127 
0128   TGLFBO* fbo = nullptr;
0129   if (height == -1)
0130     fbo = m_fwGlViewer->MakeFbo();
0131   else
0132     fbo = m_fwGlViewer->MakeFboHeight(height);
0133 
0134   if (fbo == nullptr) {
0135     ::Error(eh, "Returned FBO is 0.");
0136     m_prom = std::promise<int>();
0137     m_prom.set_value(-1);
0138     return m_prom.get_future();
0139   }
0140 
0141   int ww, hh;
0142   if (fbo->GetIsRescaled()) {
0143     ww = TMath::Nint(fbo->GetW() * fbo->GetWScale());
0144     hh = TMath::Nint(fbo->GetH() * fbo->GetHScale());
0145   } else {
0146     ww = fbo->GetW();
0147     hh = fbo->GetH();
0148   }
0149 
0150   fbo->SetAsReadBuffer();
0151 
0152   size_t bufsize = 3 * ww * hh;
0153   if (bufsize != m_imgBuffer.size()) {
0154     m_imgBuffer.resize(bufsize);
0155   }
0156 
0157   glPixelStorei(GL_PACK_ALIGNMENT, 1);
0158   glReadPixels(0, 0, ww, hh, GL_RGB, GL_UNSIGNED_BYTE, &m_imgBuffer[0]);
0159 
0160   if (m_thr == nullptr)
0161     spawn_image_thread();
0162 
0163   {
0164     std::unique_lock<std::mutex> lk(m_moo);
0165 
0166     m_prom = std::promise<int>();
0167     m_name = file;
0168     m_ww = ww;
0169     m_hh = hh;
0170 
0171     m_cnd.notify_one();
0172   }
0173 
0174   return m_prom.get_future();
0175 }
0176 
0177 //
0178 // const member functions
0179 //
0180 
0181 //
0182 // static member functions
0183 //
0184 
0185 bool FWTEveViewer::SavePng(const TString& file, UChar_t* xx, int ww, int hh) {
0186   png_structp png_ptr;
0187   png_infop info_ptr;
0188 
0189   /* Create and initialize the png_struct with the desired error handler
0190     * functions.  If you want to use the default stderr and longjump method,
0191     * you can supply NULL for the last three parameters.  We also check that
0192     * the library version is compatible with the one used at compile time,
0193     * in case we are using dynamically linked libraries.  REQUIRED.
0194     */
0195   png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
0196   if (png_ptr == nullptr) {
0197     printf("Error creating png write struct\n");
0198     return false;
0199   }
0200 
0201   // Allocate/initialize the image information data.      REQUIRED
0202   info_ptr = png_create_info_struct(png_ptr);
0203   if (info_ptr == nullptr) {
0204     printf("Error creating png info struct\n");
0205     png_destroy_write_struct(&png_ptr, &info_ptr);
0206     return false;
0207   }
0208 
0209   /*// Set error handling.  REQUIRED if you aren't supplying your own
0210    //      error handling functions in the png_create_write_struct() call.
0211    if (setjmp(png_jmpbuf(png_ptr))) {
0212    // If we get here, we had a problem reading the file
0213    png_destroy_write_struct(&png_ptr, &info_ptr);
0214    ilSetError(IL_LIB_PNG_ERROR);
0215    return IL_FALSE;
0216    }*/
0217 
0218   FILE* fp = fopen(file, "w");
0219 
0220   png_init_io(png_ptr, fp);
0221 
0222   // Use PNG_INTERLACE_ADAM7 for interlacing
0223   png_set_IHDR(png_ptr,
0224                info_ptr,
0225                ww,
0226                hh,
0227                8,
0228                PNG_COLOR_TYPE_RGB,
0229                PNG_INTERLACE_NONE,
0230                PNG_COMPRESSION_TYPE_BASE,
0231                PNG_FILTER_TYPE_BASE);
0232 
0233   /* Optional gamma chunk is strongly suggested if you have any guess
0234     * as to the correct gamma of the image.
0235     */
0236   // png_set_gAMA(png_ptr, info_ptr, gamma);
0237 
0238   // Optionally write comments into the image.
0239   // png_text text;
0240   // text.key  = "Generated by";
0241   // text.text = "Generated by cmsShow";
0242   // text.compression = PNG_TEXT_COMPRESSION_NONE;
0243   // png_set_text(png_ptr, info_ptr, &text, 1);
0244 
0245   // Write the file header information.  REQUIRED.
0246   png_write_info(png_ptr, info_ptr);
0247 
0248   std::vector<UChar_t*> rows(hh);
0249   {
0250     int j = hh - 1;
0251     for (int i = 0; i < hh; i++, j--) {
0252       rows[i] = xx + j * ww * 3;
0253     }
0254   }
0255 
0256   // Writes the image.
0257   png_write_image(png_ptr, &rows[0]);
0258 
0259   // It is REQUIRED to call this to finish writing the rest of the file
0260   png_write_end(png_ptr, info_ptr);
0261 
0262   // clean up after the write, and ifree any memory allocated
0263   png_destroy_write_struct(&png_ptr, &info_ptr);
0264 
0265   fclose(fp);
0266 
0267   return true;
0268 }
0269 
0270 bool FWTEveViewer::SaveJpg(const TString& file, UChar_t* xx, int ww, int hh) {
0271   struct jpeg_compress_struct JpegInfo;
0272   struct jpeg_error_mgr Error;
0273 
0274   JpegInfo.err = jpeg_std_error(&Error);
0275 
0276   // Now we can initialize the JPEG compression object.
0277   jpeg_create_compress(&JpegInfo);
0278 
0279   FILE* fp = fopen(file, "w");
0280   jpeg_stdio_dest(&JpegInfo, fp);
0281 
0282   JpegInfo.image_width = ww;
0283   JpegInfo.image_height = hh;
0284   JpegInfo.input_components = 3;
0285   JpegInfo.in_color_space = JCS_RGB;
0286 
0287   jpeg_set_defaults(&JpegInfo);
0288 
0289   JpegInfo.write_JFIF_header = TRUE;
0290 
0291   // Set the quality output
0292   // const int quality = 98;
0293   // jpeg_set_quality(&JpegInfo, quality, true); // bool force_baseline ????
0294 
0295   jpeg_start_compress(&JpegInfo, TRUE);
0296 
0297   std::vector<UChar_t*> rows(hh);
0298   {
0299     int j = hh - 1;
0300     for (int i = 0; i < hh; i++, j--) {
0301       rows[i] = xx + j * ww * 3;
0302     }
0303   }
0304 
0305   jpeg_write_scanlines(&JpegInfo, &rows[0], hh);
0306 
0307   // Step 6: Finish compression
0308   jpeg_finish_compress(&JpegInfo);
0309 
0310   // Step 7: release JPEG compression object
0311 
0312   // This is an important step since it will release a good deal of memory.
0313   jpeg_destroy_compress(&JpegInfo);
0314 
0315   return true;
0316 }