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

📄 imagefile.cpp

📁 一个英国人写的GIS查看/编辑工具。支持标准的shapefile地图文件格式和coverage地图文件格式。同时可以编辑相应的dbf文件。
💻 CPP
📖 第 1 页 / 共 2 页
字号:
        
        // write out the entire image data in one call
        
        png_write_image (png_ptr, ppbRowPointers);
        
        // write the additional chunks to the PNG file (not really needed)
        
        png_write_end(png_ptr, info_ptr);
        
        // and we're done
        
        free (ppbRowPointers);
        ppbRowPointers = NULL;
        
        // clean up after the write, and free any memory allocated
        
        png_destroy_write_struct(&png_ptr, (png_infopp) NULL);
        
        // yepp, done
    }

    catch (png_const_charp)
    {
        png_destroy_write_struct(&png_ptr, (png_infopp) NULL);

        if(ppbRowPointers)
            free (ppbRowPointers);

        fclose(pfFile);

        return FALSE;
    }
    
    fclose (pfFile);
    
    return TRUE;

}

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

void CImageFile::Close()
{
   if (m_buffer.image != NULL) delete [] m_buffer.image;   

   m_buffer.image = NULL;   
     
   if (m_pBitmap1 != NULL && m_pDC != NULL) m_pDC->SelectObject(m_pBitmap1);
   if (m_pBitmap2 != NULL && m_pDCMask != NULL) m_pDCMask->SelectObject(m_pBitmap2);

   m_pBitmap1 = NULL;
   m_pBitmap2 = NULL;
   
   if (m_pDC != NULL) delete m_pDC;
   if (m_pDCMask != NULL) delete m_pDCMask;

   m_pDC = NULL;
   m_pDCMask = NULL;
}

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

BOOL CImageFile::IsOpen()
{
   return m_buffer.image != NULL;
}


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

void CImageFile::OnDraw(CDC* pDC, CRect rect)
{   
   CRect rectI;
        
   CPaintDC* pPaintDC = (CPaintDC*)pDC;
   CRect rcP = &pPaintDC->m_ps.rcPaint;

   if (m_buffer.image == NULL && m_pDC == NULL) return;

   if (!pDC->IsKindOf(RUNTIME_CLASS(CPaintDC))) rcP = rect;

   if (pDC->IsPrinting() && pDC->GetDeviceCaps(PHYSICALWIDTH) != 0)
   {
      rcP = CRect(0, 0, pDC->GetDeviceCaps(PHYSICALWIDTH),  
                  pDC->GetDeviceCaps(PHYSICALHEIGHT)); 
   }
   
   // Draw the base map

   if (rect.left == -1 && rect.right == -1) rect = rcP;  
   
// Optimization: Check for intersect

   if (!rectI.IntersectRect(rect, &rcP))
   {
      return;
   }
   
// Adjust aspect ratio of display area

   AspectRatio(rect);   
   
   BOOL bTransparent = FALSE;

   for (int i = max(rcP.top,rect.top); i < min(rect.bottom, rcP.bottom); i++)
   {   
      for (int j = max(rcP.left, rect.left); j < min(rcP.right, rect.right); j++)
      {         
         int xx = min(((j - rect.left) * m_buffer.width) / rect.Width(), m_buffer.width); 
         int yy = min(((i - rect.top) * m_buffer.height) / rect.Height(), m_buffer.height);
               
         int iRow = m_buffer.width * yy;

         // Determine index to colour look-up table
      
         int r,g,b;

         if (m_buffer.flags & IMG_JPG || m_buffer.flags & IMG_PNG)
         {                                   
            r = m_buffer.image[iRow*m_buffer.nChannels + xx*m_buffer.nChannels];
            g = m_buffer.image[iRow*m_buffer.nChannels + xx*m_buffer.nChannels+1];
            b = m_buffer.image[iRow*m_buffer.nChannels + xx*m_buffer.nChannels+2];                         

            if (m_buffer.nChannels == 4)
            {
               bTransparent = !m_buffer.image[iRow*m_buffer.nChannels + xx*m_buffer.nChannels+3];                         
            };
            
            r = 255-(255-r)/m_nWaterColor;
            g = 255-(255-g)/m_nWaterColor;
            b = 255-(255-b)/m_nWaterColor;
                        
               
            // Draw 'pixel'

           if (!bTransparent)                 
           {
             pDC->SetPixel(j,i, RGB(r,g,b));                           
           };
         }
      }
   }         
}

///////////////////////////////////////////////////////////////////////////////
//
// Draws an image with corresponding georeferenced coordinates into a map view
//

void CImageFile::OnDraw(CDC* pDC, CViewMap* pViewMap, CRect* pRect)
{
   // Determine the extremes of the bitmap in world coordinates

   CRectDbl rect;
   CRect rectV, rectC;
   CPoint point;

   m_georef.Convert(CPoint(0,0), rect.left, rect.top);
   m_georef.Convert(CPoint(m_buffer.width, m_buffer.height), rect.right, rect.bottom);

   // Now convert this to screen coordinates

   rectV.left = pViewMap->GetfXPos((int)rect.left);
   rectV.right = pViewMap->GetfXPos((int)rect.right);
   rectV.top = pViewMap->GetfYPos((int)rect.top);
   rectV.bottom = pViewMap->GetfYPos((int)rect.bottom);

   // Clip to map view

   CRect rect1 = pViewMap->GetRect();
   if (pRect != NULL) rect1 = *pRect;
   rectC.IntersectRect(rectV, rect1);
   
   // Now draw the map into this area

   for (int i = rectC.left; i <= rectC.right; i++)
   {
      for (int j = rectC.top; j <= rectC.bottom; j++)
      {
         // Now get the world coordinates

         double x = pViewMap->GetfXInv(i);
         double y = pViewMap->GetfYInv(j);

         // Determine this on the original image

         m_georef.Convert(x,y, point);

         if (point.x >= 0 && point.x < m_buffer.width && 
             point.y >= 0 && point.y < m_buffer.height)
         {
            // Check transparency

            if (m_buffer.nChannels != 4 ||
               m_buffer.image[(point.y*m_buffer.width+point.x)*m_buffer.nChannels+3])
            {
               int r = m_buffer.image[(point.y*m_buffer.width+point.x)*m_buffer.nChannels];
               int g = m_buffer.image[(point.y*m_buffer.width+point.x)*m_buffer.nChannels+1];
               int b = m_buffer.image[(point.y*m_buffer.width+point.x)*m_buffer.nChannels+2];

               pDC->SetPixel(i, j, RGB(r,g,b));   
            }
         }
      }
   }
}

///////////////////////////////////////////////////////////////////////////////
//
// Converts a device context back to an image file
//

BOOL CImageFile::CaptureDC(CDC* pDC, int nWidth, int nHeight)
{
   BOOL bOK = TRUE;

   // Close any existing image

   Close();

   CDlgProgress dlgProgress;
   dlgProgress.SetText(BDString(IDS_SAVING));

   // Initialise progres bar

   dlgProgress.SetRange(0, nHeight);   

   // Create memory for holding data

   m_buffer.width = nWidth;
   m_buffer.height = nHeight;
   m_buffer.image = new unsigned char[nWidth*nHeight*3];

   if (m_buffer.image != NULL)
   {
      for (int j = 0; j < nHeight && bOK; j++)
      {
         for (int i = 0; i < nWidth && bOK; i++)
         {
            COLORREF cr = pDC->GetPixel(i,j);

            m_buffer.image[(j*m_buffer.width+i)*3] = GetRValue(cr);
            m_buffer.image[(j*m_buffer.width+i)*3+1] = GetGValue(cr);
            m_buffer.image[(j*m_buffer.width+i)*3+2] = GetBValue(cr);
         }

         // Update progress bar

        if (!dlgProgress.SetProgress(j)) 
        {
           bOK = FALSE;
        }

      } 
   } else
   {
      bOK = FALSE;
   }

   return bOK;
}

///////////////////////////////////////////////////////////////////////////////
//
// Saves the current image to the file specified
//

BOOL CImageFile::OnSave(LPCSTR sFile, int nQuality, BOOL bColor)
{
   BOOL bOK = FALSE;

   if (m_buffer.image != NULL)
   {
       if (CString(sFile).Right(4).CompareNoCase(".jpg") == 0)
       {
          bOK = JpegFile::RGBToJpegFile(sFile, m_buffer.image, m_buffer.width, 
                               m_buffer.height, bColor, nQuality);
       }
       else if (CString(sFile).Right(4).CompareNoCase(".png") == 0)
       {
          m_buffer.nChannels = 3;
          bOK  = RGBToPNGFile(sFile, bColor);
       }
   }

   return bOK;
}

///////////////////////////////////////////////////////////////////////////////
//
// Adjust the aspect ratio of the display rectangle so that the image does not
// appear distorted
//
   
void CImageFile::AspectRatio(CRect& rect)
{  
   if (rect.Height() / (double)rect.Width() > m_buffer.height / (double)m_buffer.width)
   {
      int nHeight = (m_buffer.height * rect.Width()) / m_buffer.width;
      rect.top = rect.top + rect.Height()/2 - nHeight/2;
      rect.bottom = rect.top + nHeight;
   }
   else
   {
      int nWidth = (m_buffer.width * rect.Height()) / m_buffer.height;
      rect.left = rect.left + rect.Width()/2 - nWidth/2;
      rect.right = rect.left + nWidth;
   }
}

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

DWORD WaitProcess(HWND hWnd, HANDLE handle)
{
   MSG msg;       
   while (TRUE)
   {
      if (GetMessage(&msg, NULL, 0, 0))
      {
         TranslateMessage(&msg);
         DispatchMessage(&msg);                  
      };

     // Wait for exit code
               
      DWORD dword;
      if (!GetExitCodeProcess(handle, &dword) || dword != STILL_ACTIVE)
      {
         return dword;
      }
   }
}

///////////////////////////////////////////////////////////////////////////////
//
// Converts an image file into a long binary
//

BOOL CImageFile::AsLongBinary(CLongBinary& longbin)
{
   CByteArray aData;
   BOOL bOK = TRUE;

   // Add header information

   write(aData, m_buffer.width);
   write(aData, m_buffer.height);
   write(aData, m_buffer.flags);
   write(aData, m_buffer.nChannels);

   // Write image data

   int cbHeader = aData.GetSize();
   int cbImage = m_buffer.width*m_buffer.height*m_buffer.nChannels;

   aData.SetSize(cbHeader+cbImage);
   memcpy(aData.GetData()+cbHeader, m_buffer.image, cbImage);

   // Write georeference data

   write(aData, m_georef.m_aPoints.GetSize());
   for (int i = 0; i < m_georef.m_aPoints.GetSize(); i++)
   {
      write(aData, m_georef.m_aPoints[i].m_nSX);
      write(aData, m_georef.m_aPoints[i].m_nSY); 
      write(aData, m_georef.m_aPoints[i].m_dWX);
      write(aData, m_georef.m_aPoints[i].m_dWY);      
   }

   // Now compress the image to save space, this will also help with validation

   ULONG nDestLen = (size_t)(aData.GetSize() * 1.01 + 12);
   BYTE* aBuffer = new BYTE[nDestLen];

   if (aBuffer == NULL)
   {
      bOK = FALSE;
   }

   if (bOK && compressZ(aBuffer, &nDestLen, aData.GetData(), aData.GetSize()) != Z_OK)
   {
      bOK = FALSE;
   }

   // Now convert this to a longbinary

   if (longbin.m_hData != NULL) GlobalFree(longbin.m_hData);
   longbin.m_hData = GlobalAlloc(GMEM_MOVEABLE|GMEM_DISCARDABLE, nDestLen + sizeof(long)); 
   if (longbin.m_hData != NULL)
   {
      longbin.m_dwDataLength = nDestLen + sizeof(long);
      BYTE* pData = (BYTE*)GlobalLock(longbin.m_hData);
      if (pData != NULL)
      {
         // Store the uncompress size

         long cbSize = aData.GetSize();
         memcpy(pData, &cbSize, sizeof(long));  
         memcpy(pData+sizeof(long), aBuffer, nDestLen); 
         GlobalUnlock(longbin.m_hData);
      } else
      {
         bOK = FALSE;
      }
   } else
   {
      bOK = FALSE;
   }

   // Tidy up

   if (aBuffer != NULL) delete [] aBuffer;

   return bOK;

}

///////////////////////////////////////////////////////////////////////////////
//
// Converts a longbinary back into an image file
//

BOOL CImageFile::Initialise(CLongBinary& longbin, BOOL bGeoRef)
{
   BOOL bOK = TRUE;
   ULONG lSize = 0;
   BYTE* pBuffer = NULL;
   BYTE* aBuffer = NULL;

   // Firstly uncompress the image
   
   BYTE* pData = (BYTE*)GlobalLock(longbin.m_hData);
   if (pData != NULL)
   {
      memcpy(&lSize, pData, sizeof(long));

      pBuffer = aBuffer = new BYTE[lSize];

      if (pBuffer != NULL)
      {
        if (uncompressZ(pBuffer, &lSize, pData+sizeof(long), longbin.m_dwDataLength-sizeof(long)) != Z_OK)
        {
           bOK = FALSE;
        }
      } else
      {
        bOK = FALSE;
      }
   } else
   {
      bOK = FALSE;
   }

   // Now retrieve the values from the buffer

   if (bOK)
   {
      memcpy(&m_buffer.width, pBuffer, sizeof(m_buffer.width));
      pBuffer += sizeof(m_buffer.width);
      memcpy(&m_buffer.height, pBuffer, sizeof(m_buffer.height));
      pBuffer += sizeof(m_buffer.height);
      memcpy(&m_buffer.flags, pBuffer, sizeof(m_buffer.flags));
      pBuffer += sizeof(m_buffer.flags);
      memcpy(&m_buffer.nChannels, pBuffer, sizeof(m_buffer.nChannels));
      pBuffer += sizeof(m_buffer.nChannels);
   };
          
  // Retrieve image

   if (bOK)
   {
      int cbImage = m_buffer.width * m_buffer.height * m_buffer.nChannels;
      if (m_buffer.image != NULL) delete m_buffer.image;
      m_buffer.image = new BYTE [cbImage];
      if (m_buffer.image != NULL)
      {
         memcpy(m_buffer.image, pBuffer, cbImage);
         pBuffer += cbImage;
      } else
      {
         bOK = FALSE;
      }
   }

  // Retrieve georefencing

   if (bOK)
   {
      // Read number of georef points

      int nPoints = 0;
      memcpy(&nPoints, pBuffer, sizeof(nPoints));
      pBuffer += sizeof(nPoints);

      // Read in points

      m_georef.m_aPoints.SetSize(nPoints);

      for (int i = 0; i < nPoints; i++)
      {
         memcpy(&m_georef.m_aPoints[i].m_nSX, pBuffer, sizeof(m_georef.m_aPoints[i].m_nSX));
         pBuffer += sizeof(m_georef.m_aPoints[i].m_nSX);

         memcpy(&m_georef.m_aPoints[i].m_nSY, pBuffer, sizeof(m_georef.m_aPoints[i].m_nSY));
         pBuffer += sizeof(m_georef.m_aPoints[i].m_nSY);

         memcpy(&m_georef.m_aPoints[i].m_dWX, pBuffer, sizeof(m_georef.m_aPoints[i].m_dWX));
         pBuffer += sizeof(m_georef.m_aPoints[i].m_dWX);

         memcpy(&m_georef.m_aPoints[i].m_dWY, pBuffer, sizeof(m_georef.m_aPoints[i].m_dWY));
         pBuffer += sizeof(m_georef.m_aPoints[i].m_dWY);
      }
    
     // Calculate rotation etc. from pararmeters

      if (bGeoRef)
      {
         bOK = m_georef.Initialise(m_buffer.width, m_buffer.height);
      };
   }


  // Tidy up

   if (aBuffer != NULL) delete [] aBuffer;


   return bOK;
}

⌨️ 快捷键说明

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