Logo Search packages:      
Sourcecode: magics++ version File versions  Download package

BaseDriverImages.h

Go to the documentation of this file.
/******************************** LICENSE ********************************


  Copyright 2009 European Centre for Medium-Range Weather Forecasts (ECMWF)

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.


 ******************************** LICENSE ********************************/

/*! \file BaseDriverImages.h
    \brief Implementation of methods to display images of driver base class.

    Magics Team - ECMWF 2005

    Started: March 2005

    Changes:

*/

#ifdef MAGICS_RASTER
#include <gd.h>
#endif

using namespace magics;


static inline int getRealLine(ifstream& I, char* cline)
{
      int k = 0;
      char ch;
      while ( I.get(ch) )
      {
            cline[k] = ch;
            if ( ch == '\n' || ch == '\0' || I.eof() )
                  break;
            k++;
      }
      cline[k] = '\0';
      return k;
}

static inline int getGoodLine(ifstream& I, char* cline,const int& n)
{
      int k = 0;
      char ch;
      while(I.get(ch))
      {
            cline[k] = ch;
            if ( ch == '\n' || ch == '\0' || I.eof() || k == n ) break;
            k++;
      }
      cline[k] = '\0';
      return k;
}

static inline int check_ps(const string& file, int& boxx, int& boxy, int& orientation)
{
      ifstream I(file.c_str());
      if (!I) return 1;

      string::size_type x,y;
      char *cline;
      cline = new char[2048];
      int k = getGoodLine(I,cline,2048);
      string s(cline,k);

      // level 3 only "%!PS-Adobe-3.0";
      x = s.find("%!PS");
      if(x == string::npos) return 1;  //no PostScript

      // Looks like a PostScript file
      int r = 0;
      boxx = boxy = 0;
      orientation = 0; // Portrait
      int boundingbox_found = 1;
      int orientation_found = 1;
      float xx = 0.0,yy = 0.0;

      while(!I.eof()) // look for  %%BoundingBox: %%Orientation:
      {
            k = getGoodLine(I, cline,2048);
            int i = ( k > 15 ) ? 15 : k;
            if ( i < 15 )  // dont bother
                  continue;
            string f(cline,i);

            if ( boundingbox_found )
            {
                  x = f.find("%%BoundingBox:");
                  if ( x != string::npos  )
                  {
                        string str(cline,k);
                        y = str.find("atend");
                        if ( y != string::npos )
                              continue;
                        else
                        {
                              str.erase(0,x+15);
                              istringstream ist(str.c_str());

                              float dum1, dum2;
                              ist >>dum1 >> dum2 >> xx >> yy;
                              xx = xx - dum1;
                              yy = yy - dum2;
                              boundingbox_found = 0;
                        }
                  }
            }
            if ( orientation_found )
            {
                  x = f.find("%%Orientation:");
                  if ( x != string::npos )
                  {
                        string str(cline,k);
                        y = str.find("atend");
                        if ( y != string::npos )
                              continue;
                        else
                        {
                              y = str.find("Landscape");
                              orientation = ( y != string::npos  ) ? 1 : 0;
                              orientation_found = 0;
                        }
                  }
            }
            if ( (orientation_found + boundingbox_found) == 0 ) break;
      }

      boxx = (int) xx;  boxy = (int) yy;
      if ( boxx == 0 || boxy == 0 ) // No boundingbox
      {
            boxx = 595;
            boxy = 841;
      }

      I.close();
      delete [] cline;
      return r;
}

static inline int check_ppmHeader(ifstream& I, int& col, int& row)
{
      int colours;
      char *cline = new char[2048];

      int k = getRealLine(I, cline);
      string s = cline;
      int r = 0;
      int x = s.find("P6");

      if(x<0) r = 1;// not PPM P6 format

      if(!r)
      {
            cline[0] = '#';
            while ( cline[0] == '#')  // skip comments
                  k = getRealLine(I,cline);
            istringstream ist1(cline);
            ist1 >> col >> row;
            k = getRealLine(I,cline);
            istringstream ist2(cline);
            ist2 >> colours;

            if ( col == 0 || row == 0 || colours == 0 ) r =  1;
      }

      delete [] cline;
      return r;
}


/*!
  \brief Image render method for ALL drivers.

  This method should be used by all Magics++ drivers to render image objects.
*/
00189 MAGICS_NO_EXPORT void BaseDriver::renderImage(const ImportObject& obj) const
{
      std::string f = obj.getFormat();
      GraphicsFormat format = PNG;
      if(magCompare(f,"ps")) format = PS;
      else if(magCompare(f,"eps")) format = EPS;
      else if(magCompare(f,"gif")) format = GIF;
      else if(magCompare(f,"jpeg") || magCompare(f,"jpg")) format = JPG;
      else if(magCompare(f,"png")) format = PNG;
      else if(magCompare(f,"svg")) format = SVG;

      float width=0;
      float height=0;

      if(obj.getWidth()==-1 && ( magCompare(f,"gif") || magCompare(f,"png") || magCompare(f,"jpeg")|| magCompare(f,"jpg") ) )
      {
#ifndef MAGICS_RASTER
            Log::error() << "BaseDriverImages: Dimension is -1 and default size can not be determined (GD library required)!" << endl;
            return;
#else
            FILE *in = fopen(obj.getPath().c_str(), "rb");
            gdImagePtr image = 0;
            if(magCompare(f,"png")) image = gdImageCreateFromPng(in);
            else if(magCompare(f,"jpeg") || magCompare(f,"jpg")) image = gdImageCreateFromJpeg(in);
            else if(magCompare(f,"gif"))
            {
#ifdef MAGICS_GIF
                  image = gdImageCreateFromGif(in);
#else
                  Log::error() << "GIF import is not supported in this version! You need a GIF enabled GD library." << endl;
                  return;
#endif
            }
            fclose(in);
            width  = gdImageSX(image);
            height = gdImageSY(image);
            gdImageDestroy(image);
#endif
      }
      else
      {
            width  = obj.getWidth();
            height = obj.getHeight();
      }

      convertToPixmap(obj.getPath(),format, 300,
                  projectX(obj.getOrigin().x()),
                  projectY(obj.getOrigin().y()),
                  projectX(obj.getOrigin().x()+width),
                  projectY(obj.getOrigin().y()+height) );

/*
      convertToPixmap(obj.getPath(),format, 300,
                  projectX(obj.getOrigin().x()),
                  projectY(obj.getOrigin().y()),
                  projectX(obj.getOrigin().x()+(convertCM( width  /coordRatioX_) )),
                  projectY(obj.getOrigin().y()+(convertCM( height /coordRatioY_) )) );
*/
}//end BaseDriver::renderImage()


/*!
  \brief converting object to pixmap

  This method should be used by all Magics++ drivers

*/
00256 MAGICS_NO_EXPORT bool BaseDriver::convertToPixmap(const string &fname, const GraphicsFormat format, const int reso,
                   const float wx0, const float wy0,const float wx1,const float wy1) const
{
      debugOutput("Start Image conversion");

      int Landscape = 0;
      float bx1=100.;
      float by1=100.;
      unsigned char *image = 0;
      int col=0,row=0;
      int status = 0;
      string s2(" ");
      string pixmapFormat("rgb");

      if(format==PS || format==EPS) //File is PostScript
      {
//          FILE* fd3;
//          char buf[1024];
            string cmd;
            int x1 = 0;
            int y1 = 0;

            if(check_ps(fname,x1,y1,Landscape) )
            {
                  Log::error() << "BaseDriverImages: Open of source PostScript file failed!" << endl;
                  return false;
                  }

            s2 = getTmpName()+".ppm";
            if(s2==" ")
            {
                  Log::error() << "BaseDriverImages: Open of temp file failed!" << endl;
                  return false;
            }

      //    if(format==PS)  // does not work with EPS
            {
              const float Xres = float(reso);
              bx1 = float(x1)/72.*Xres + 0.5;
              x1  = (int) bx1;
              by1 = float(y1)/72.*Xres + 0.5;
              y1  = (int) by1;

              char boxx[5];
              char boxy[5];
              char boxz[5];
              sprintf(boxx,"%d",x1);
              sprintf(boxy,"%d",y1);
              sprintf(boxz,"%d",reso);

              cmd = "( gs -q -dNOPAUSE -dSAFER -sDEVICE=ppmraw -sOutputFile=" + s2 +
                  " -dGraphicsAlphaBits=4 -dTextAlphaBits=4 -dCOLORSCREEN -dBATCH -g" +
                  boxx + "x" + boxy + " -r" + boxz + " " + fname + " < /dev/null )";
            }

            status = system(cmd.c_str());

            if(status)
            {
                  Log::error() << "BaseDriverImages: Command exit Not zero" << endl;
                  return false;
            }
            ifstream I(s2.c_str());
            if(!I)
            {
                  Log::error() << "BaseDriverImages: Incorrect PostScript Format!" << endl;
                  return false;
            }
            if(check_ppmHeader(I,col,row) )
            {
                  return 1;
            }

            image = new unsigned char [row*col*3];
            I.read((char*)image,row*col*3);
            I.close();
            remove(s2.c_str());
      }
#ifdef MAGICS_RASTER
      else if(format==GIF || format==PNG || format==JPG)
      {
            // convert png to ppm(raw) like image
            FILE* fd3 = fopen(fname.c_str(),"rb");
            if(!fd3)
            {
                  Log::error() << "BaseDriverImages: Open failed for raster source > "<< fname << endl;
                  return false;
            }
            gdImagePtr imp = 0;
            if(format==JPG)      imp = gdImageCreateFromJpeg(fd3);
            else if(format==PNG) imp = gdImageCreateFromPng(fd3);
            else if(format==GIF)
            {
#ifdef MAGICS_GIF
                  imp = gdImageCreateFromGif(fd3);
#else
                  Log::error() << "GIF pixmap import is not supported in this version! You need a GIF enabled GD library." << endl;
                  return false;
#endif
            }
            fclose(fd3);
            if(!imp)
            {
                  Log::error() << "BaseDriverImages: Incorrect raster file format (can not be handled by GD) !" << endl;
                  return false;
            }

            col = gdImageSX(imp);
            row = gdImageSY(imp);
            bx1 = (float) col;
            by1 = (float) row;
            Landscape = 0;

            if(format == PNG && // imp->transparent == 1 &&
                   alphaEnabled_ == true)
            {
                  pixmapFormat="rgba";

                  image = new unsigned char [col*row*4];
                  unsigned char *p = image;
                  int i,j;
                  for (i = 0; i<row; i++)
                  for (j = 0; j<col; j++)
                  {
                        int c = gdImageGetPixel(imp,j,i);
                        int r = gdImageRed(imp,c);
                        int g = gdImageGreen(imp,c);
                        int b = gdImageBlue(imp,c);
                        int a = gdImageAlpha(imp,c);
                        *(p++) = (unsigned char) r;
                        *(p++) = (unsigned char) g;
                        *(p++) = (unsigned char) b;
                        *(p++) = (unsigned char) 255-2*a;
                  }
            }
            else
            {
                  image = new unsigned char [col*row*3];
                  unsigned char *p = image;
                  int i,j;
                  for (i = 0; i<row; i++)
                  for (j = 0; j<col; j++)
                  {
                        int c = gdImageGetPixel(imp,j,i);
                        int r = gdImageRed(imp,c);
                        int g = gdImageGreen(imp,c);
                        int b = gdImageBlue(imp,c);
                        *(p++) = (unsigned char) r;
                        *(p++) = (unsigned char) g;
                        *(p++) = (unsigned char) b;
                  }
            }

            gdImageDestroy(imp);
      }
#endif
      else 
      {
            Log::warning() << "BaseDriverImages: graphics formats ("<<format<<") is NOT supported!" << endl;
            return 1;//No PPM
      }

      float x0 = wx0; //Left
      float x1 = wx1; //Right
      float y0 = wy0;
      float y1 = wy1;

      // const float aspect = bx1/by1;
      //if ( Landscape == 1 )       y1 = y0 + abs(x1-x0)*aspect;
      //else if ( Landscape == 0 )  x1 = x0 + abs(y1-y0)*aspect;

      bool alpha = (pixmapFormat == "rgba");
      status = renderPixmap(x0,y0,x1,y1,col,row,image,Landscape,alpha);

      if(!status) Log::warning() <<"BaseDriver::convertToPixmap() -> no Pixmap could be drawn! Zero size of at least one dimension."<<endl;
      delete [] image;

      return status;
}

/*
bool BaseDriver::renderPixmap(float ,float,float,float ,int w,int h,unsigned char* IOUT,int, bool hasAlpha) const
{
#ifndef MAGICS_RASTER
      Log::warning() << "Image import is not implemented for the used driver!!!" << endl;
      return false;
#else
      gdImagePtr im = gdImageCreateTrueColor(w,h);
      unsigned char *p = IOUT;
      gdImageColorAllocateAlpha(im, 255, 255, 255, 127);
      int a = 0;

      for(int i=h-1;i>=0;i--)
      {
            for(int j=0;j<w; j++)
            {
                  const int r = (int) *(p++);
                  const int g = (int) *(p++);
                  const int b = (int) *(p++);
                  if(hasAlpha) a = (int) *(p++);
                  const int col = gdImageColorResolveAlpha(im,r,g,b,a);
                  gdImageSetPixel(im, w, h, col);
            }
      }
      gdImageDestroy(im);
      gdImageAlphaBlending(im, 1);
      gdImageSaveAlpha(im, 1); // save transparency

      stringstream out;
      out << output_resource_list_.size();
      string filename = "magics_resource_"+out.str()+".png";

      output_resource_list_.push_back(filename);


      FILE *outFile = fopen(filename.c_str(),"wb");
      gdImagePng(im,outFile);
      fclose(outFile);

      return true;
#endif
}
*/

Generated by  Doxygen 1.6.0   Back to index