📄 imagefile.cpp
字号:
// 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 + -