Found on the Internet for a long time have not been able to find the detailed coding rules of the PPM format, http://wangbingkun.spaces.live.com/blog/cns! E188E2874053C244! 215. The entry Link provides a brief introduction. So I used Matlab to read an image in PPM format, and then read the Memory Distribution of the Image Using WinEdit. Through comparison, I found that the image mainly consists of the following parts:
1. file type. The selected PPM format is P6, which occupies the first two bytes (bytes). The hexadecimal format is 50 36;
2. The pixel width of the image, separated by one byte from the file type. For example, if the width is 512, it occupies three bytes (3, 4, 5 bytes), and The hexadecimal value is 35 31 32;
3. The pixel height of the image is separated from the width by one byte. The representation is the same as the width. If the width is a three-digit number, the height value is stored from 7th bytes, if the width is a two-digit number, the height starts from 6th bytes;
4. The maximum pixel value of an image is separated by a byte from the height. Of course, its specific storage location and width are related to the number of digits of the height.
5. The image data area is separated from the maximum pixel value by one byte. The P6 type is three bytes per pixel. The scanning sequence of the entire image is from left to right, from top to bottom, the three bytes in each pixel are arranged in BGR order.
Based on the above analysis, the following code converts the P6 type PPM format to the BMP format:
HDIB CDibImage: ReadPPMFile (CFile & file)
{
Unsigned char * pHeader = new unsigned char [15];
HDIB hDIB_Des;
LPSTR pDIB_Des;
HDIB hPPM_Src;
LPSTR pPPM_Src;
DWORD dwSrc = file. GetLength (); // get the source file length
File. Read (pHeader, 15 );
If (pHeader [0]! = 80 | pHeader [1]! = 54) // determine whether the P6 format is used
{
AfxMessageBox ("not P6 format! ");
Return NULL;
}
Int j = 0, flag [4]; // locate the separator of the Main Parameter
For (int I = 2; I <15; I ++)
{
If (pHeader [I]> 57 | pHeader [I] <48)
{
Flag [j] = I;
J ++;
If (j> 3)
Break;
}
}
If (flag [0]! = 2)
Return NULL;
Int lenWidth = 0, lenHeight = 0, maxColorNum = 0; // obtain the width and height of the original image respectively.
For (I = 1; I <flag [1]-flag [0]; I ++)
{
LenWidth = lenWidth * 10 + pHeader [flag [0] + I] % 16;
}
For (I = 1; I <flag [2]-flag [1]; I ++)
{
LenHeight = lenHeight * 10 + pHeader [flag [1] + I] % 16;
}
For (I = 1; I <flag [3]-flag [2]; I ++)
{
MaxColorNum = maxColorNum * 10 + pHeader [flag [2] + I] % 16;
}
Int rowLenDes = WIDTHBYTES (24 * lenWidth); // the width and height of the bitmap are given respectively.
Int heightLenDes = lenHeight;
Int dwData = rowLenDes * heightLenDes; // the size of the bitmap data area.
Int dwInfo = 40;
Int dwTotal = dwInfo + dwData; // a 24-Bit Bitmap is constructed here.
HPPM_Src = (HDIB): GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT, dwSrc );
If (hPPM_Src = 0)
{
Return NULL;
}
PPPM_Src = (LPSTR): GlobalLock (HGLOBAL) hPPM_Src );
DWORD aaa = file. ReadHuge (pPPM_Src, dwSrc-flag [3]-1 );
If (aaa! = DwSrc-flag [3]-1) // read Pixel
{
: GlobalUnlock (HGLOBAL) hPPM_Src );
: GlobalFree (HGLOBAL) hPPM_Src );
Return NULL;
}
HDIB_Des = (HDIB): GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT, dwTotal );
If (hDIB_Des = 0)
{
Return NULL;
}
PDIB_Des = (LPSTR) GlobalLock (HGLOBAL) hDIB_Des );
BYTE * pDIBBits = (BYTE *) (40 + pDIB_Des );
Int lenRow = 3 * lenWidth;
For (I = 0; I <lenHeight; I ++)
{
For (j = 0; j <lenRow; j = j + 3)
{
PDIBBits [I * rowLenDes + j] = pPPM_Src [(lenHeight-I) * lenRow + j + 2]; // The BGR order of PPM is considered here.
PDIBBits [I * rowLenDes + j + 1] = pPPM_Src [(lenHeight-I) * lenRow + j + 1];
PDIBBits [I * rowLenDes + j + 2] = pPPM_Src [(lenHeight-I) * lenRow + j];
}
If (rowLenDes> lenRow)
{
For (j = lenRow; j <rowLenDes; j ++)
{
PDIBBits [I * rowLenDes + j] = 0;
}
}
}
(LPBITMAPINFOHEADER) pDIB_Des)-> biHeight = heightLenDes;
(LPBITMAPINFOHEADER) pDIB_Des)-> biWidth = lenWidth;
(LPBITMAPINFOHEADER) pDIB_Des)-> biClrUsed = 0;
(LPBITMAPINFOHEADER) pDIB_Des)-> biSize = 40;
(LPBITMAPINFOHEADER) pDIB_Des)-> biBitCount = 24;
(LPBITMAPINFOHEADER) pDIB_Des)-> biPlanes = 1;
(LPBITMAPINFOHEADER) pDIB_Des)-> biSizeImage = heightLenDes * lenWidth;
: GlobalUnlock (HGLOBAL) hDIB_Des );
: GlobalUnlock (HGLOBAL) hPPM_Src );
: GlobalFree (HGLOBAL) hPPM_Src );
Return hDIB_Des;
}
Since I do not know the specific data format of PPM when implementing this conversion, it is implemented only based on the pattern of the image in the PPM format stored on my machine, hope you can give more advice if you know more information about PPM.