glcgi_image.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:9k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: glcgi_image.cpp,v $
  4.  * PRODUCTION Revision 1000.2  2004/06/01 20:53:02  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.7
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: glcgi_image.cpp,v 1000.2 2004/06/01 20:53:02 gouriano Exp $
  10.  * ===========================================================================
  11.  *
  12.  *                            PUBLIC DOMAIN NOTICE
  13.  *               National Center for Biotechnology Information
  14.  *
  15.  *  This software/database is a "United States Government Work" under the
  16.  *  terms of the United States Copyright Act.  It was written as part of
  17.  *  the author's official duties as a United States Government employee and
  18.  *  thus cannot be copyrighted.  This software/database is freely available
  19.  *  to the public for use. The National Library of Medicine and the U.S.
  20.  *  Government have not placed any restriction on its use or reproduction.
  21.  *
  22.  *  Although all reasonable efforts have been taken to ensure the accuracy
  23.  *  and reliability of the software and data, the NLM and the U.S.
  24.  *  Government do not and cannot warrant the performance or results that
  25.  *  may be obtained by using this software or data. The NLM and the U.S.
  26.  *  Government disclaim all warranties, express or implied, including
  27.  *  warranties of performance, merchantability or fitness for any particular
  28.  *  purpose.
  29.  *
  30.  *  Please cite the author in any work or product based on this material.
  31.  *
  32.  * ===========================================================================
  33.  *
  34.  * Author:  Denis Vakatov
  35.  *
  36.  * File Description:
  37.  *    CGlCgiImage -- base class for producing images via a CGI using OpenGL
  38.  */
  39. #include <ncbi_pch.hpp>
  40. #include <gui/opengl/mesa/glcgi_image.hpp>
  41. #include <gui/opengl/mesa/gloscontext.hpp>
  42. #include <html/page.hpp>
  43. #include <util/image/image.hpp>
  44. #include <util/image/image_util.hpp>
  45. #include <util/image/image_io.hpp>
  46. BEGIN_NCBI_SCOPE
  47. //
  48. // content-type headers for images
  49. //
  50. struct SContentType
  51. {
  52.     CImageIO::EType m_Type;
  53.     const char* m_Encoding;
  54. };
  55. static const SContentType kContentTypes[] = {
  56.     { CImageIO::eBmp,  "image/bmp" },
  57.     { CImageIO::eGif,  "image/gif" },
  58.     { CImageIO::eJpeg, "image/jpeg" },
  59.     { CImageIO::ePng,  "image/png" },
  60.     { CImageIO::eSgi,  "image/sgi" },
  61.     { CImageIO::eTiff, "image/tiff" },
  62.     { CImageIO::eXpm,  "image/xmp" },
  63.     // must be last
  64.     { CImageIO::eUnknown, NULL }
  65. };
  66. //
  67. // default error template
  68. // this can be replaced as needed
  69. //
  70. //
  71. // default ctor
  72. //
  73. CGlCgiImageApplication::CGlCgiImageApplication()
  74.     : m_Width (800),
  75.       m_Height(600),
  76.       m_Format(CImageIO::ePng)
  77. {
  78. }
  79. CGlCgiImageApplication::~CGlCgiImageApplication()
  80. {
  81. }
  82. //
  83. // get our aspect ratio
  84. //
  85. float CGlCgiImageApplication::GetAspectRatio(void) const
  86. {
  87.     if (m_Context) {
  88.         size_t width  = m_Context->GetBuffer().GetWidth();
  89.         size_t height = m_Context->GetBuffer().GetHeight();
  90.         return (float)width / (float)height;
  91.     }
  92.     return 1.0f;
  93. }
  94. //
  95. // Init()
  96. // Initialize our renderer to a default size (800x600 pixels)
  97. void CGlCgiImageApplication::Init()
  98. {
  99.     m_ErrorTemplate = GetConfig().Get("filesystem", "ErrorTemplate");
  100. }
  101. CGlOsContext& CGlCgiImageApplication::x_GetContext(void)
  102. {
  103.     if ( !m_Context ) {
  104.         // create an off-screen renderer that handles a virtual frame buffer
  105.         m_Context.Reset(new CGlOsContext(m_Width, m_Height));
  106.     }
  107.     return *m_Context;
  108. }
  109. //
  110. // ProcessRequest()
  111. // Here, we do a minimal amount of set-up and pass off to our rendering hook.
  112. // When this hook completes, we write out the resulting image to the response.
  113. //
  114. int CGlCgiImageApplication::ProcessRequest(CCgiContext& ctx)
  115. {
  116.     CStopWatch sw;
  117.     sw.Start();
  118.     double render_time = 0;
  119.     double image_flip_time = 0;
  120.     try {
  121.         // user hook: pre-rpocess
  122.         x_PreProcess(ctx);
  123.         // create an off-screen renderer that handles a virtual frame buffer
  124.         if ( !x_GetContext().MakeCurrent() ) {
  125.             LOG_POST(Error << "CGlCgiImageApplication::ProcessRequest(): "
  126.                      "Failed to make off-screen renderer current");
  127.             return 1;
  128.         }
  129.         // call the rendering hook
  130.         Render(ctx);
  131.         // call glFinish() - VERY IMPORTANT FOR OFF_SCREEN RENDERING
  132.         // this forces any buffered OpenGL requests to complete now.
  133.         glFinish();
  134.         render_time = sw.Elapsed();
  135.         // final image preparation
  136.         // the image is upside-down because frame buffers are, in general,
  137.         // upside-down.  Also, we have an alpha channel we need to flatten.
  138.         m_Context->SetBuffer().SetDepth(3);
  139.         CImageUtil::FlipY(m_Context->SetBuffer());
  140.         image_flip_time = sw.Elapsed();
  141.         // user hook: post-process
  142.         x_PostProcess(ctx);
  143.     }
  144.     catch (CException& e) {
  145.         x_HandleError(ctx, e.GetMsg());
  146.         return 1;
  147.     }
  148.     catch (exception& e) {
  149.         x_HandleError(ctx, e.what());
  150.         return 1;
  151.     }
  152. #ifndef _DEBUG
  153.     catch (...) {
  154.         x_HandleError(ctx, "unknown error");
  155.         return 1;
  156.     }
  157. #endif
  158.     //
  159.     // and stream back the image
  160.     // this requires that we first write the image to a temporary file and then
  161.     // echo the contents of this image back
  162.     //
  163.     // don't forget to set our content-type
  164.     string encoding("image/unknown");
  165.     for (const SContentType* type = kContentTypes;  type->m_Encoding;  ++type) {
  166.         if (type->m_Type == m_Format) {
  167.             encoding = type->m_Encoding;
  168.             break;
  169.         }
  170.     }
  171.     CCgiResponse& response = ctx.GetResponse();
  172.     response.SetContentType(encoding);
  173.     //
  174.     // write the standard CGI headers
  175.     // if this line is commented out, the image will be dumped to stdout anc
  176.     // can be redirected to a file for local access
  177.     //
  178.     response.WriteHeader();
  179.     //
  180.     // write the image
  181.     // we wrap the management of the temporary file in a class in case one of
  182.     // our operations throws; this way, the stack unwinding for the exception
  183.     // will insure that our temporary file gets cleaned up
  184.     //
  185.     CImageIO::WriteImage(m_Context->GetBuffer(), response.out(), m_Format);
  186.     double image_encode_time = sw.Elapsed();
  187.     LOG_POST(Info << "CGlCgiImage::ProcessRequest():n"
  188.              << "  render time  = " << render_time << "n"
  189.              << "  process time = " << image_flip_time - render_time << "n"
  190.              << "  encode time  = " << image_encode_time - image_flip_time << "n");
  191.     return 0;
  192. }
  193. void CGlCgiImageApplication::x_HandleError(CCgiContext& ctx,
  194.                                            const string& msg)
  195. {
  196.     CCgiResponse& response = ctx.GetResponse();
  197.     response.SetContentType("text/html");
  198.     response.WriteHeader();
  199.     if (m_ErrorTemplate.empty()) {
  200.         CHTMLPage page("CGI Error", m_ErrorTemplate);
  201.         page.AppendChild(new CHTMLPlainText(msg));
  202.         page.Print(response.out());
  203.     } else {
  204.         CHTMLPage page("", m_ErrorTemplate);
  205.         page.AddTagMap("message", new CHTMLPlainText(msg));
  206.         page.Print(response.out());
  207.     }
  208. }
  209. void CGlCgiImageApplication::x_PreProcess(CCgiContext& ctx)
  210. {
  211.     // set the width and height from the 'width=' and 'height=' keys
  212.     {{
  213.          TCgiEntries::const_iterator width_iter =
  214.              ctx.GetRequest().GetEntries().find("width");
  215.          if (width_iter != ctx.GetRequest().GetEntries().end()) {
  216.              m_Width = NStr::StringToInt(width_iter->second);
  217.          }
  218.          TCgiEntries::const_iterator height_iter =
  219.              ctx.GetRequest().GetEntries().find("height");
  220.          if (height_iter != ctx.GetRequest().GetEntries().end()) {
  221.              m_Height = NStr::StringToInt(height_iter->second);
  222.          }
  223.      }}
  224.     // set the image format using the 'fmt=' key
  225.     TCgiEntries::const_iterator fmt_iter =
  226.         ctx.GetRequest().GetEntries().find("fmt");
  227.     if (fmt_iter != ctx.GetRequest().GetEntries().end()) {
  228.         string fmt(fmt_iter->second);
  229.         fmt = "." + fmt;
  230.         m_Format = CImageIO::GetTypeFromFileName(fmt);
  231.     }
  232. }
  233. void CGlCgiImageApplication::x_PostProcess(CCgiContext& ctx)
  234. {
  235. }
  236. END_NCBI_SCOPE
  237. /*
  238.  * ===========================================================================
  239.  * $Log: glcgi_image.cpp,v $
  240.  * Revision 1000.2  2004/06/01 20:53:02  gouriano
  241.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.7
  242.  *
  243.  * Revision 1.7  2004/05/21 22:27:45  gorelenk
  244.  * Added PCH ncbi_pch.hpp
  245.  *
  246.  * Revision 1.6  2004/04/08 13:40:52  dicuccio
  247.  * Wrapped context creation in a simple function
  248.  *
  249.  * Revision 1.5  2004/03/22 17:40:57  dicuccio
  250.  * Added generic error handling.
  251.  *
  252.  * Revision 1.4  2004/01/20 12:10:23  dicuccio
  253.  * Added user hooks for process request.  Moved off-screen context creation into ProcessRequest()
  254.  *
  255.  * Revision 1.3  2004/01/08 12:01:14  dicuccio
  256.  * Use CImageUtil::FlipY() instead of CImage::Flip().  Use direct stream write
  257.  * instead of writing to a temporary file.
  258.  *
  259.  * Revision 1.2  2003/06/12 19:47:00  dicuccio
  260.  * Added better management of temporary files, internal timing for rendering
  261.  * components
  262.  *
  263.  * Revision 1.1  2003/06/09 19:21:44  dicuccio
  264.  * Initial revision
  265.  *
  266.  * ===========================================================================
  267.  */