⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 imagefile.cpp

📁 一个英国人写的GIS查看/编辑工具。支持标准的shapefile地图文件格式和coverage地图文件格式。同时可以编辑相应的dbf文件。
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//////////////////////////////////////////////////////
//
// NRDB Pro - Spatial database and mapping application
//
// Copyright (c) 1989-2004 Richard D. Alexander
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
//
// NRDB Pro is part of the Natural Resources Database Project 
// 
// Homepage: http://www.nrdb.co.uk/
// Users' Forum: http://nrdb.mypalawan.info/
// 

#include "stdafx.h"
#include "nrdb.h"
#include "include\jpegfile.h"
#include "include\png.h"
#include "dlgprogress.h"

#include "ImageFile.h"
#include "viewmap.h"
#include "projctns.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

/////////////////////////////////////////////////////////////////////////////
//
// compress function is exported as _compress@16, however the zlib.h defines 
// it as _compress therefore need to define elsewhere!
//

extern int _stdcall compressZ(BYTE *dest, ULONG *destLen, const BYTE *source, ULONG sourceLen);
extern int _stdcall uncompressZ (BYTE *dest, ULONG *destLen, const BYTE *source, ULONG sourceLen);

/////////////////////////////////////////////////////////////////////////////

void inline write(CByteArray& aData, int n)
{
   int nLength= aData.GetSize();
   aData.SetSize(nLength + sizeof(n));      
   memcpy(&aData[nLength], &n, sizeof(n));
}

void inline write(CByteArray& aData, double n)
{
   int nLength= aData.GetSize();
   aData.SetSize(nLength + sizeof(n));      
   memcpy(&aData[nLength], &n, sizeof(n));
}

/////////////////////////////////////////////////////////////////////////////

DWORD WaitProcess(HWND hWnd, HANDLE handle);

//////////////////////////////////////////////////////////////////////
//
// Exception handling for PNG images
//

static png_structp png_ptr = NULL;
static png_infop info_ptr = NULL;

static void
png_cexcept_error(png_structp png_ptr, png_const_charp msg)
{
   throw msg;
}

//////////////////////////////////////////////////////////////////////
//
// Construction/Destruction

CImageFile::CImageFile()
{
   m_pFile = NULL;  
   m_nWaterColor = 1;
   m_pDC = NULL;
   m_pBitmap1 = NULL;
   m_pBitmap2 = NULL;
   m_pDCMask = NULL;
   m_bTransparent = FALSE;      
}

///////////////////////////////////////////////////////////////////////////////
//
// Copy constructor necessary for custom symbols

CImageFile::CImageFile(CImageFile& rSrc)
{
   *this = rSrc;   
}

CImageFile& CImageFile::operator =(CImageFile& rSrc)
{
   m_buffer = rSrc.m_buffer;
   m_pFile = NULL;
   m_bChanged = FALSE;
   m_nWaterColor = 1;
   m_pDC = FALSE;
   m_pDCMask = FALSE;
   m_pBitmap1 = FALSE;
   m_pBitmap2 = FALSE;
   //m_georef = rSrc.m_georef;

   return *this;
};

///////////////////////////////////////////////////////////////////////////////

CImageFile::~CImageFile()
{
   Close();   
}

/////////////////////////////////////////////////////////////////////////////
// CImageDoc construction/destruction

Buffer::Buffer()
{       
    width =  height = 0;    
    flags = 0;        
    image = NULL;
    nChannels = 0;
}

///////////////////////////////////////////////////////////////////////////////
//
// Converts an image to a long binary for storing in the database
//

BOOL CImageFile::Open(LPCTSTR lpszPathName, int nFlag, HWND hWnd) 
{     
   BOOL bOK = TRUE;

   if (hWnd == NULL) hWnd = GetFocus();

   // Tidy up from previous

   Close();

   m_bTransparent = nFlag & Transparent;

   // Load data

   AfxGetApp()->BeginWaitCursor();

   // Open jpeg files

   if (stricmp(lpszPathName+strlen(lpszPathName)-4,".jpg") == 0 || 
       stricmp(lpszPathName+strlen(lpszPathName)-4,".png") ==0)
   {
      if (stricmp(lpszPathName+strlen(lpszPathName)-4,".jpg") == 0)
      {
         m_buffer.image = JpegFile::JpegFileToRGB(lpszPathName, (UINT*)&m_buffer.width, 
                            (UINT*)&m_buffer.height);      

         m_buffer.flags = IMG_JPG;
         m_buffer.nChannels = 3;
      } else
      {
         bOK = PNGFileToRGB(lpszPathName, &m_buffer.width, &m_buffer.height, m_buffer.image);

         m_buffer.flags = IMG_PNG;
      }   

      // Now retrieve corresponding georeference coordinates if any
      // If retrieving map from .nrm file then only display the georeference
      // utility if not previously georeferenced

      if (nFlag & GeoRef && (!m_georef.Load(lpszPathName) || 
          m_georef.m_aPoints.GetSize() < 2))
      {
         // If image has not been georeferenced then run Image2Shp to allow
         // user opportunity

         CString sPath = BDGetAppPath();
         if (sPath.Right(1) != "\\") sPath += "\\";
         sPath += "Image2Shp.exe \"" + CString(lpszPathName) + "\" ";   
         
         // Disable window whilst Image2Shp is open to prevent
         // user from closing dialog

         CWnd::FromHandle(hWnd)->EnableWindow(FALSE);         

         // Now spawn the application

         PROCESS_INFORMATION proc = {0};
         STARTUPINFO start = {0};
         int ret;
	   
        // Initialize the STARTUPINFO structure:

         start.cb = sizeof (start);      
         start.wShowWindow = SW_SHOWNORMAL;

         // Start the shelled application:

         ret = CreateProcess(0, (LPSTR)(LPCSTR)sPath, 0, 0, TRUE,
                             NORMAL_PRIORITY_CLASS, 0, 0, &start, &proc);     
         if (ret)
         {                                  
            DWORD dw = WaitProcess(AfxGetMainWnd()->GetSafeHwnd(), proc.hProcess); 
            // dw == 0 on error 
         }

         CWnd::FromHandle(hWnd)->EnableWindow(TRUE);                 
         SetFocus(hWnd);         
         
         // Now attempt to load the georeferences again

         m_georef.Load(lpszPathName);
      };
      
      // Need to convert parameters from lat/long if necessary before
      // georefercing

      // Determine  if points are in lat/long or x,y

      BOOL bLatLon = TRUE;

      CArray <CGeoPoint,CGeoPoint>& geopoints = m_georef.m_aPoints;
      for (int i = 0; i < geopoints.GetSize(); i++)
      {
         if (geopoints[i].m_dWX < -180 || geopoints[i].m_dWX > 180 ||
             geopoints[i].m_dWY < -90 || geopoints[i].m_dWY > 90)
         {
            bLatLon = FALSE;
            break;
         }
      }
      
      // If latitude/longitude then convert to x,y

      if (bLatLon)
      {
         for (int i = 0; i < geopoints.GetSize(); i++)
         {
            long x,y;
            BDProjection()->LatLonToTransMercator(geopoints[i].m_dWY, geopoints[i].m_dWX, &x,&y);
            geopoints[i].m_dWX = x;
            geopoints[i].m_dWY = y;
         }
      }

      // Calcualate georeference

      m_georef.Initialise(m_buffer.width, m_buffer.height);
      
      bOK &= m_buffer.image != NULL;
   }   
   
   AfxGetApp()->EndWaitCursor();

   // Quit if no file selected   
   
	return bOK;
}

/////////////////////////////////////////////////////////////////////////////
//
// Load PNG image and save to buffer
//

BOOL CImageFile::PNGFileToRGB(LPCSTR pstrFileName, int* piWidth, int* piHeight, BYTE*& pbImageData)
{
   static FILE        *pfFile;
    png_byte            pbSig[8];
    int                 iBitDepth;
    int                 iColorType;
    double              dGamma;
    png_color_16       *pBackground;
    png_uint_32         ulChannels;
    png_uint_32         ulRowBytes;        
    int                 i;
    png_bytepp pbRowPointers = NULL;
        
    // open the PNG input file

    if (!pstrFileName)
    {
        pbImageData = NULL;
        return FALSE;
    }

    if (!(pfFile = fopen(pstrFileName, "rb")))
    {
        pbImageData = NULL;
        return FALSE;
    }

    // first check the eight byte PNG signature

    fread(pbSig, 1, 8, pfFile);
    if (!png_check_sig(pbSig, 8))
    {
        pbImageData = NULL;
        return FALSE;
    }

    // create the two png(-info) structures

    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,
      (png_error_ptr)png_cexcept_error, (png_error_ptr)NULL);
    if (!png_ptr)
    {
        pbImageData = NULL;
        return FALSE;
    }

    info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr)
    {
        png_destroy_read_struct(&png_ptr, NULL, NULL);
        pbImageData = NULL;
        return FALSE;
    }

    try
    {
       
        // initialize the png structure
        
        png_init_io(png_ptr, pfFile);
   
        png_set_sig_bytes(png_ptr, 8);
        
        // read all PNG info up to image data
        
        png_read_info(png_ptr, info_ptr);
        
        // get width, height, bit-depth and color-type
        
        png_get_IHDR(png_ptr, info_ptr, (unsigned long*)piWidth, (unsigned long*)piHeight, &iBitDepth,
            &iColorType, NULL, NULL, NULL);
        
        // expand images of all color-type and bit-depth to 3x8 bit RGB images
        // let the library process things like alpha, transparency, background
        
        if (iBitDepth == 16)
            png_set_strip_16(png_ptr);
        if (iColorType == PNG_COLOR_TYPE_PALETTE)
            png_set_expand(png_ptr);
        if (iBitDepth < 8)
            png_set_expand(png_ptr);
        if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
            png_set_expand(png_ptr);
        if (iColorType == PNG_COLOR_TYPE_GRAY ||
            iColorType == PNG_COLOR_TYPE_GRAY_ALPHA)
            png_set_gray_to_rgb(png_ptr);
               
        // set the background color to draw transparent and alpha images over.
        if (png_get_bKGD(png_ptr, info_ptr, &pBackground))
        {
            png_set_background(png_ptr, pBackground, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);            
        }        
        
        // if required set gamma conversion
        if (png_get_gAMA(png_ptr, info_ptr, &dGamma))
            png_set_gamma(png_ptr, (double) 2.2, dGamma);
        
        // after the transformations have been registered update info_ptr data
        
        png_read_update_info(png_ptr, info_ptr);
        
        // get again width, height and the new bit-depth and color-type
        
        png_get_IHDR(png_ptr, info_ptr, (unsigned long*)piWidth, (unsigned long*)piHeight, &iBitDepth,
            &iColorType, NULL, NULL, NULL);
                
        // row_bytes is the width x number of channels
        
        ulRowBytes = png_get_rowbytes(png_ptr, info_ptr);
        ulChannels = png_get_channels(png_ptr, info_ptr);

        m_buffer.nChannels = ulChannels;
                       
        // now we can allocate memory to store the image
        
        if (pbImageData)
        {
            delete [] pbImageData;
            pbImageData = NULL;
        }


        pbImageData = new png_byte[ulRowBytes * (*piHeight)
                            * sizeof(png_byte)];
        if (pbImageData == NULL)
        {
            png_error(png_ptr, "Visual PNG: out of memory");
        }        
        
        // and allocate memory for an array of row-pointers
        
        if ((pbRowPointers = (png_bytepp) malloc((*piHeight)
                            * sizeof(png_bytep))) == NULL)
        {
            png_error(png_ptr, "Visual PNG: out of memory");
        }
        
        // set the individual row-pointers to point at the correct offsets
                
        for (i = 0; i < (*piHeight); i++)
            pbRowPointers[i] = pbImageData + i * ulRowBytes;
        
        // now we can go ahead and just read the whole image
        
        png_read_image(png_ptr, pbRowPointers);
        
        // read the additional chunks in the PNG file (not really needed)
        
        png_read_end(png_ptr, NULL);
        
        // and we're done
        
        free (pbRowPointers);
        pbRowPointers = NULL;               
    }

    
    catch (png_const_charp)
    {
        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);

        pbImageData = NULL;
        
        if(pbRowPointers)
            free (pbRowPointers);

        fclose(pfFile);

        return FALSE;
    }

    fclose (pfFile);

    return TRUE;
}

/////////////////////////////////////////////////////////////////////////////
//
// Save a PNG file
//

BOOL CImageFile::RGBToPNGFile(LPCSTR pstrFileName, BOOL bColour)
{
    const int           ciBitDepth = 8;
    
    static FILE        *pfFile;
    png_uint_32         ulRowBytes;
    static png_byte   **ppbRowPointers = NULL;
    int                 i;
    
    // Set parameters
    int iWidth = m_buffer.width;
    int iHeight = m_buffer.height;
    png_byte *pDiData = m_buffer.image;
    int ciChannels = m_buffer.nChannels;

    // open the PNG output file

    if (!pstrFileName)
        return FALSE;

    if (!(pfFile = fopen(pstrFileName, "wb")))
        return FALSE;

    // prepare the standard PNG structures

    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL,
      (png_error_ptr)png_cexcept_error, (png_error_ptr)NULL);
    if (!png_ptr)
    {
        fclose(pfFile);
        return FALSE;
    }

    info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr) {
        fclose(pfFile);
        png_destroy_write_struct(&png_ptr, (png_infopp) NULL);
        return FALSE;
    }

    try
    {
        // initialize the png structure
        
        png_init_io(png_ptr, pfFile);
        
        // we're going to write a very simple 3x8 bit RGB image        

        png_set_IHDR(png_ptr, info_ptr, iWidth, iHeight, ciBitDepth,
            PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
            PNG_FILTER_TYPE_BASE);
        
        // write the file header information
        
        png_write_info(png_ptr, info_ptr);               
        
        // row_bytes is the width x number of channels
        
        ulRowBytes = iWidth * ciChannels;
        
        // we can allocate memory for an array of row-pointers
        
        if ((ppbRowPointers = (png_bytepp) malloc(iHeight * sizeof(png_bytep))) == NULL)
            throw "Visualpng: Out of memory";
        
        // set the individual row-pointers to point at the correct offsets
        
        for (i = 0; i < iHeight; i++)
            ppbRowPointers[i] = pDiData + i * (((ulRowBytes + 3) >> 2) << 2);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -