📄 imfile.cpp
字号:
char sTempPath[SLEN]; FILE *pTempFile = pOpenTempFile(sTempPath, "image", "w+b"); ConvertJpgFileToBmpFile(sPath, pTempFile, 0); fclose(pTempFile); char *s = sLoadBmp(pImg, pRgbImg, sTempPath, fExitOnErr, true /* fDeleteOnErr */); unlink(sTempPath); return s; } break; case 'P': if (toupper(sExt[2]) == 'G') return sLoadPgm(pImg, pRgbImg, sPath, fExitOnErr); else return sLoadPpm(pImg, pRgbImg, sPath, fExitOnErr); break; default: { FILE *pFile = fopen(sPath, "rb"); if (!pFile) { sprintf(sgErr, "Can't open %s", sPath); if (fExitOnErr) Err(sgErr); else return sgErr; } fclose(pFile); sprintf(sgErr, "Unknown image type %s", sPath); if (fExitOnErr) Err(sgErr); else return sgErr; break; } }return NULL; // success}//-----------------------------------------------------------------------------// Load an image. Knows about different types of files like BMPs and JPEGs.// This uses the file extension to determine file type.//// Img is the gray image// sPath is the file name// Set fVerbose if you want to tell the user that you are reading the filechar *sLoadImage (Image &Img, // out const char *sPath, bool fVerbose, bool fExitOnErr) // in{return sLoadImage(&Img, NULL, sPath, fVerbose, fExitOnErr, true);}//-----------------------------------------------------------------------------// See above header. RgbImg is the color image.// fRemovePad=false is needed to for StretchDIBits() under windowschar *sLoadImage (RgbImage &RgbImg, // out const char *sPath, bool fVerbose, bool fExitOnErr, bool fRemovePad) // in{return sLoadImage(NULL, &RgbImg, sPath, fVerbose, fExitOnErr, fRemovePad);}//-----------------------------------------------------------------------------// Return the directory at index iDir in sDirs, where sDirs has the form dir1;dir2;dir3static char *sGetDir (const char *sDirs, int iDir){static char sDirs1[SLEN]; strcpy(sDirs1, sDirs); // needed because strtok replaces ; with a 0int iDir1 = 0;char *sDir = strtok(sDirs1, ";");while (iDir1++ < iDir && sDir != NULL) sDir = strtok(NULL, ";");return sDir;}//-----------------------------------------------------------------------------// Returns the full pathname or NULL if filename not in any of sDirschar *sGetFilenameGivenDirs (const char *sDirs, const char *sFile){static char sLastDir[SLEN];static char sPath[SLEN];char *pPath = NULL;// try the same directory we used last time (for efficiency)if (sLastDir[0]) { sprintf(sPath, "%s/%s", sLastDir, sFile); FILE *pFile = fopen(sPath, "r"); if (pFile) { // success fclose(pFile); pPath = sPath; } }if (pPath == NULL) // couldn't open file? { // path we used last time failed, try each directory in sDirs one by one int iDir = 0; char *sDir; while (NULL != (sDir = sGetDir(sDirs, iDir++))) { sprintf(sPath, "%s/%s", sDir, sFile); FILE *pFile = fopen(sPath, "r"); if (pFile) { // success fclose(pFile); pPath = sPath; strcpy(sLastDir, sDir); break; } } }return pPath;}//-----------------------------------------------------------------------------static char *sLoadImageGivenDirs (Image *pImg, RgbImage *pRgbImg, // out const char *sDirs, const char *sFile, // in bool fVerbose, bool fExitOnErr, bool fRemovePad) // in{static char sLastDir[SLEN];char sPath[SLEN];char *sErrMsg = "err";// first try the same directory we used last time (for efficiency)if (sLastDir[0]) { sprintf(sPath, "%s/%s", sLastDir, sFile); sErrMsg = sLoadImage(pImg, pRgbImg, sPath, fVerbose, false, fRemovePad); if (sErrMsg) bprintf(!fVerbose, "Can't open, looking in next directory\n"); }if (sErrMsg) // if couldn't load image? { // path we used last time failed, try each directory in sDirs one by one int iDir = 0; char *sDir; while (NULL != (sDir = sGetDir(sDirs, iDir++))) { sprintf(sPath, "%s/%s", sDir, sFile); sErrMsg = sLoadImage(pImg, pRgbImg, sPath, fVerbose, false, fRemovePad); if (sErrMsg == NULL) { // succesfully opened the file strcpy(sLastDir, sDir); break; } bprintf(!fVerbose, "Can't open, looking in next directory\n"); } }if (sErrMsg && fExitOnErr) Err("Can't open %s (searched in directories %s)", sFile, sDirs);return sErrMsg;}//-----------------------------------------------------------------------------char *sLoadImageGivenDirs (Image &Img, // out const char *sDirs, const char *sFile, // in bool fVerbose, bool fExitOnErr) // in{return sLoadImageGivenDirs(&Img, NULL, sDirs, sFile, fVerbose, fExitOnErr, true);}char *sLoadImageGivenDirs (RgbImage &Img, // out const char *sDirs, const char *sFile, // in bool fVerbose, bool fExitOnErr, bool fRemovePad) // in{return sLoadImageGivenDirs(NULL, &Img, sDirs, sFile, fVerbose, fExitOnErr, fRemovePad);}//-----------------------------------------------------------------------------void CheckFileExistsGivenDirs (const char *sDirs, const char *sFile, const char *sMsg){static char sLastDir[SLEN];FILE *pFile = NULL;char sPath[SLEN];// first try the same directory we used last time (for efficiency)if (sLastDir[0]) { sprintf(sPath, "%s/%s", sLastDir, sFile); pFile = fopen(sPath, "r"); }if (!pFile) // if couldn't load image? { // path we used last time failed, try each directory in sDirs one by one int iDir = 0; char *sDir; while (sDir = sGetDir(sDirs, iDir++)) { sprintf(sPath, "%s/%s", sDir, sFile); char sPath1[SLEN]; strcpy(sPath1, sPath); pFile = fopen(sPath1, "r"); if (pFile) { // succesfully opened the file strcpy(sLastDir, sDir); break; } } }if (pFile == NULL) Err("%s %s doesn't exist %s (searched in directories %s)", sMsg, sFile, sDirs);fclose(pFile);}//-----------------------------------------------------------------------------void WriteBmpHeader (FILE *pBmpFile, char sPath[], int width, int height) // in{BITMAPFILEHEADER bmfHeader;BITMAPINFOHEADER bmiHeader;DASSERT(width > 0 && height > 0);int nPad = width % 4;int nNewWidth = width * 3 + nPad;bmfHeader.bfType = ((WORD) ('M' << 8) | 'B');bmfHeader.bfSize = (height * nNewWidth) + 56;bmfHeader.bfReserved1 = 0;bmfHeader.bfReserved2 = 0;bmfHeader.bfOffBits = 54;Fwrite(&bmfHeader, 1, sizeof(bmfHeader), pBmpFile, sPath);bmiHeader.biSize = 40; // sizeof(bmiHeader) always 40bmiHeader.biWidth = width; // widthbmiHeader.biHeight = height; // heightbmiHeader.biPlanes = 1; // 1 These numbers are for RGBbmiHeader.biBitCount = 24; // 24 24 bit uncompressed filesbmiHeader.biCompression = 0; // 0 no compressionbmiHeader.biSizeImage = 0; // 0bmiHeader.biXPelsPerMeter = 2834; // 2834 magic number copied from existing bitmapsbmiHeader.biYPelsPerMeter = 2834; // 2834 dittobmiHeader.biClrUsed = 0; // 0 no color map entriesbmiHeader.biClrImportant = 0; // 0Fwrite(&bmiHeader, 1, sizeof(bmiHeader), pBmpFile, sPath);}//-----------------------------------------------------------------------------void WriteBmpPixels (FILE *pBmpFile, char sPath[], byte *buf, int width, int height) // in{int nPad = width % 4;unsigned Pixel;for (int iy = height - 1; iy >= 0; iy--) { for (int ix = 0; ix < width; ix++) { Pixel = *(buf + ix + iy * width); Pixel = (Pixel | (Pixel << 8) | (Pixel << 16)); // gray to RGB Fwrite(&Pixel, 1, 3, pBmpFile, sPath); } if (nPad) { Pixel = 0; Fwrite(&Pixel, 1, nPad, pBmpFile, sPath); } }Pixel = 0;Fwrite(&Pixel, 1, 2, pBmpFile, sPath); // photoshop puts 2 bytes on end, so we do too}//-----------------------------------------------------------------------------void WriteBmpPixels (FILE *pBmpFile, char sPath[], tRGB *buf, int width, int height) // in{int nPad = width % 4;unsigned PadPixel = 0;for (int iy = 0; iy < height; iy++) { Fwrite(buf + iy * width, 1, 3 * width, pBmpFile, sPath); if (nPad) Fwrite(&PadPixel, 1, nPad, pBmpFile, sPath); }Fwrite(&PadPixel, 1, 2, pBmpFile, sPath); // photoshop puts 2 bytes on end, so we do too}//-----------------------------------------------------------------------------// Write the given buffer as a 24 bit uncompressed windows BMP file//// A bitmap file looks like this://// BITMAPFILEHEADER bmfHeader;// BITMAPINFOHEADER bmiHeader; <---hDib points to start of this// RGBTRIPLE Colors[]//// where (values given in comments are for windows 24 bit uncompressed RGB files)//// typedef struct tagBITMAPFILEHEADER {// WORD bfType; // always "BM"// DWORD bfSize; // (height * width * 3) + padding (see below)// WORD bfReserved1; // always 0// WORD bfReserved2; // always 0// DWORD bfOffBits; // always 54 (24bit uncompressed BMPs)// } BITMAPFILEHEADER, FAR *LPBITMAPFILEHEADER, *PBITMAPFILEHEADER;//// typedef struct tagBITMAPINFOHEADER {// DWORD biSize; // sizeof(bmiHeader) always 40// LONG biWidth; // width// LONG biHeight; // height// WORD biPlanes; // 1 These numbers are for RGB// WORD biBitCount; // 24 24 bit uncompressed files// DWORD biCompression; // 0 uncompressed data// DWORD biSizeImage; // 0 usually// LONG biXPelsPerMeter; // magic number copied from existing bitmaps// LONG biYPelsPerMeter; // ditto (doesn't matter in this application)// DWORD biClrUsed; // 0// DWORD biClrImportant; // 0// } BITMAPINFOHEADER, FAR *LPBITMAPINFOHEADER, *PBITMAPINFOHEADER;void WriteBmp (const Image &Img, const char sPath[], bool fVerbose) // in{FILE *pBmpFile;int width = Img.width, height = Img.height;char sDrive[_MAX_DRIVE], sDir[_MAX_DIR], sFname[_MAX_FNAME], sExt[_MAX_EXT];char sPath1[SLEN];_splitpath(sPath, sDrive, sDir, sFname, sExt); // make sure file has a .bmp extensionASSERT(strlen(sExt) <= 4); // if user has strange extension don't silently overwrite it (4 is ".bmp")_makepath(sPath1, sDrive, sDir, sFname, ".bmp");if (fVerbose) lprintf("Writing %s\n", sPath1);pBmpFile = Fopen(sPath1, "wb");WriteBmpHeader(pBmpFile, sPath1, width, height);WriteBmpPixels(pBmpFile, sPath1, Img.buf, width, height);fclose(pBmpFile);}//-----------------------------------------------------------------------------void WriteBmp (const RgbImage &Img, const char sPath[], bool fVerbose) // in{FILE *pBmpFile;int width = Img.width, height = Img.height;char sDrive[_MAX_DRIVE], sDir[_MAX_DIR], sFname[_MAX_FNAME], sExt[_MAX_EXT];char sPath1[SLEN];_splitpath(sPath, sDrive, sDir, sFname, sExt); // make sure file has a .bmp extensionASSERT(strlen(sExt) <= 4); // if user has strange extension don't silently overwrite it (4 is ".bmp")_makepath(sPath1, sDrive, sDir, sFname, ".bmp");if (fVerbose) lprintf("Writing %s %dx%d\n", sPath1, width, height);pBmpFile = Fopen(sPath1, "wb");WriteBmpHeader(pBmpFile, sPath1, width, height);WriteBmpPixels(pBmpFile, sPath1, Img.buf, width, height);fclose(pBmpFile);}//-----------------------------------------------------------------------------static void DumpBmpHeaderBuf (const BITMAPINFOHEADER *pBmi) // in{lprintf("bmi.biSize = %d 0x%x always 40\n", pBmi->biSize, pBmi->biSize);lprintf("bmi.biWidth = %d 0x%x\n", pBmi->biWidth, pBmi->biWidth);lprintf("bmi.biHeight = %d 0x%x", pBmi->biHeight, pBmi->biHeight);if (pBmi->biWidth % 4) lprintf(" (width of pad is %d)", pBmi->biWidth % 4);lprintf("\n");lprintf("bmi.biPlanes = %d always 1\n", pBmi->biPlanes);lprintf("bmi.biBitCount = %d 0x%x always 24\n", pBmi->biBitCount, pBmi->biBitCount);lprintf("bmi.biCompression = %d always 0\n", pBmi->biCompression);lprintf("bmi.biSizeImage = %d usually 0\n",pBmi->biSizeImage);lprintf("bmi.biXPelsPerMeter = %d 0x%4.4x varies\n", pBmi->biXPelsPerMeter, pBmi->biXPelsPerMeter);lprintf("bmi.biYPelsPerMeter = %d 0x%4.4x varies\n", pBmi->biYPelsPerMeter, pBmi->biYPelsPerMeter);lprintf("bmi.biClrUsed = %d always 0\n", pBmi->biClrUsed);lprintf("bmi.biClrImportant = %d always 0\n", pBmi->biClrImportant);}//-----------------------------------------------------------------------------void DumpBmpHeader (const char sPath[]){FILE *pBmpFile;BITMAPFILEHEADER bmf;BITMAPINFOHEADER bmi;byte Contents[10];lprintf("Dump %s\n", sPath);pBmpFile = Fopen(sPath, "rb");Fread(&bmf, 1, sizeof(bmf), pBmpFile, sPath);if (bmf.bfType != ((WORD) ('M' << 8) | 'B')) Err("%s is not a BMP file", sPath);Fread(&bmi, 1, sizeof(bmi), pBmpFile, sPath);// the displayed "always" values are for 24 bit uncompressed RGB fileslprintf("bmf.bfType = 0x%x always 0x%x\n", bmf.bfType, bmf.bfType, ((WORD) ('M' << 8) | 'B'));int nNewWidth = bmi.biWidth * 3 + bmi.biWidth % 4;int Size = (nNewWidth * bmi.biHeight) + 56;lprintf("bmf.bfSize = %d 0x%x expect %d, %d is also ok\n", bmf.bfSize, bmf.bfSize, Size, Size-2);lprintf("bmf.bfReserved1 = %d always 0\n", bmf.bfReserved1);lprintf("bmf.bfReserved2 = %d always 0\n", bmf.bfReserved2);lprintf("bmf.bfOffBits = %d 0x%x always 54\n", bmf.bfOffBits, bmf.bfOffBits);DumpBmpHeaderBuf(&bmi);static const int CONF_nPixelsToDump = 128;// It would be nice if this indicated pixels that were part of the pad. For now it doesn't.for (int i = 0; i < CONF_nPixelsToDump/24; i++) { for (int j = 0; j < 24; j += 3) if (fread(Contents, 1, 3, pBmpFile) == 3) lprintf("%2.2x.%2.2x.%2.2x ", Contents[0], Contents[1], Contents[2]); else { printf("\n"); break; } printf("\n"); }fclose(pBmpFile);lprintf("%s is %sa windows 24 bit uncompressed RGB file\n", sPath, ((!bmi.biClrUsed && bmi.biBitCount == 24 && !bmi.biCompression)? "": "not "));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -