📄 imfile.cpp
字号:
// $image\imfile.cpp 1.5 milbo$ image file io// Warning: this is raw research code -- expect it to be quite messy.// milbo durban dec05#include <windows.h>#include <io.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>#include <signal.h>#include <float.h>#include <math.h>#include <new.h>#include <direct.h>#include <sys/stat.h>#include <fstream.h>#include <iostream.h>#include "mcommon.hpp"#include "mfile.hpp"#include "image.hpp"#include "imutil.hpp"#include "rgbimutil.hpp"#include "imfile.hpp"#include "jpegutil.hpp"void __cdecl SysErr(const char *pArgs, ...); // args like printfvoid __cdecl Err(const char *pArgs, ...);void __cdecl bprintf(bool fBrief, const char *pArgs, ...);void __cdecl lprintf(const char *pArgs, ...);static char sgErr[256]; // place to store error messages//-----------------------------------------------------------------------------// Load a .bmp file. See the header of sLoadImage for some details.static char *sLoadBmp (Image *pImg, RgbImage *pRgbImg, // out const char *sPath, bool fExitOnErr, bool fRemovePad=true, bool fDeleteOnErr=false) // in{BITMAPFILEHEADER bmfHeader;BITMAPINFOHEADER bmiHeader;FILE *pBmpFile;pBmpFile = fopen(sPath, "rb");if (!pBmpFile) { if (fDeleteOnErr) unlink(sPath); if (fExitOnErr) Err("Can't open %s", sPath); else { sprintf(sgErr, "Can't open %s", sPath); return sgErr; } }unsigned Len;if ((Len = fread(&bmfHeader, 1, sizeof(bmfHeader), pBmpFile)) != sizeof(bmfHeader) || fread(&bmiHeader, 1, sizeof(bmiHeader), pBmpFile) != sizeof(bmiHeader)) { if (fDeleteOnErr) unlink(sPath); if (fExitOnErr) Err("Can't read %s%s", sPath, (Len? " (too short to be a BMP file)": "")); else { sprintf(sgErr, "Can't read %s%s", sPath, (Len? " (too short to be a BMP file)": "")); fclose(pBmpFile); return sgErr; } }if (bmfHeader.bfType != ((WORD) ('M' << 8) | 'B')) { if (fDeleteOnErr) unlink(sPath); if (fExitOnErr) Err("%s is not a BMP file (first two chars are not \"BM\")", sPath); else { sprintf(sgErr, "%s not a BMP file (first two chars are not \"BM\")", sPath); fclose(pBmpFile); return sgErr; } }if (bmiHeader.biClrUsed || bmiHeader.biBitCount != 24 || bmiHeader.biCompression) { if (fDeleteOnErr) unlink(sPath); if (fExitOnErr) Err("%s is not a windows 24 bit uncompressed RGB file", sPath); else { sprintf(sgErr, "%s not a windows 24 bit uncompressed RGB file", sPath); fclose(pBmpFile); return sgErr; } }int width = bmiHeader.biWidth;int height = bmiHeader.biHeight;if (width < 0 || width > CONF_nMaxImageDim || height > CONF_nMaxImageDim || height < 0) { if (fDeleteOnErr) unlink(sPath); if (fExitOnErr) Err("%s has a strange width %d or height", sPath, width, height); else { sprintf(sgErr, "%s has a strange width %d or height", sPath, width, height); fclose(pBmpFile); return sgErr; } }int nPad = width % 4;Len = (((3 * width) + nPad) * height);byte *pRgbTemp = (byte *)malloc(Len); // have to use a temporary buffer because of padif (fread(pRgbTemp, 1, Len, pBmpFile) != Len) { free(pRgbTemp); if (fDeleteOnErr) unlink(sPath); if (fExitOnErr) Err("Can't read %s (it's shorter than its header says it should be)", sPath); else { sprintf(sgErr, "Can't read %s (it's shorter than its header says it should be)", sPath); fclose(pBmpFile); return sgErr; } }fclose(pBmpFile);if (pImg) { // copy pRgbTemp into pImg, converting to gray and discarding the pad pImg->dim(width, height); byte *pTo = pImg->buf; for (int iy = height - 1; iy >= 0; iy--) { byte *pFrom = pRgbTemp + (3 * iy * width) + (nPad * iy); for (int ix = 0; ix < width; ix++) { tRGB Rgb = *(tRGB *)pFrom; *pTo++ = (byte)RgbToGray(Rgb); // CIE conversion to gray pFrom += 3; } } }if (pRgbImg) { // copy pRgbTemp into pRgbImg, discarding the nasty little pad pRgbImg->dim(width + (fRemovePad? 0: nPad), height); tRGB *pTo = pRgbImg->buf; tRGB *pFrom = (tRGB *)pRgbTemp; for (int iy = 0; iy < height; iy++) { for (int ix = 0; ix < width; ix++) *pTo++ = *pFrom++; byte *r = (byte *)pFrom; r += nPad; pFrom = (tRGB *)r; } }free(pRgbTemp);return NULL; // success}//-----------------------------------------------------------------------------// Load a .pgm file. See the header of sLoadImage for some details.static char *sLoadPgm (Image *pImg, RgbImage *pRgbImg, // out const char *sPath, bool fExitOnErr) // in{FILE *pFile = fopen(sPath, "rb");if (!pFile) if (fExitOnErr) Err("Can't open %s", sPath); else { sprintf(sgErr, "Can't open %s", sPath); return sgErr; }int width=-1, height=-1, DataSize, nTokens = 0;do { char sLine[SLEN]; fgets(sLine, SLEN, pFile); char *comment = strchr(sLine,'#'); if (comment != NULL) *comment = 0; char *token = NULL, *input = &sLine[0]; while (nTokens < 4 && (token = strtok(input," \t\n\r")) != NULL) { switch (nTokens) { case 0: if (strcmp(token,"P5") != 0) if (fExitOnErr) Err("%s has a bad header (first two bytes are not \"P5\")", sPath); else return "bad header (first two bytes are not \"P5\")"; break; case 1: width = atoi(token); break; case 2: height = atoi(token); break; case 3: DataSize = atoi(token); if (DataSize != 255) if (fExitOnErr) Err("This program can only deal with data sizes of 255 and " "%s has a data size of %d", sPath, DataSize); else return "data size not 255"; break; default: break; } nTokens++; input = NULL; } }while (nTokens < 4);if (width < 0 || width > CONF_nMaxImageDim || height > CONF_nMaxImageDim || height < 0) if (fExitOnErr) Err("%s has a strange width %d or height %d", sPath, width, height); else return "strange width or height";Image ImgTemp(width, height);Fread((char *)ImgTemp.buf , 1, width * height, pFile, sPath);fclose(pFile);if (pRgbImg) { pRgbImg->dim(width, height); byte *pTo = (byte *)(pRgbImg->buf); for (int iy = height-1; iy >= 0; iy--) for (int ix = 0; ix < width; ix++) { byte b = ImgTemp(ix, iy); *pTo++ = b; *pTo++ = b; *pTo++ = b; } }if (pImg) *pImg = ImgTemp;return NULL; // success}//-----------------------------------------------------------------------------char *sLoadPgm(Image &Img, // out const char *sPath, bool fExitOnErr) // in{return sLoadPgm(&Img, NULL, sPath, fExitOnErr);}//-----------------------------------------------------------------------------// Load a .ppm file. See the header of sLoadImage for some details.static char *sLoadPpm (Image *pImg, RgbImage *pRgbImg, const char *sPath, bool fExitOnErr){FILE *pFile = fopen(sPath, "rb");if (!pFile) if (fExitOnErr) Err("Can't open %s", sPath); else { sprintf(sgErr, "Can't open %s", sPath); return sgErr; }int width=-1, height=-1, DataSize, nTokens = 0;do { char sLine[SLEN]; fgets(sLine, SLEN, pFile); char *comment = strchr(sLine,'#'); if (comment != NULL) *comment = 0; char *token = NULL, *input = &sLine[0]; while (nTokens < 4 && (token = strtok(input," \t\n\r")) != NULL) { switch (nTokens) { case 0: if (strcmp(token,"P6") != 0) if (fExitOnErr) Err("%s has a bad header (first two bytes are not \"P6\")", sPath); else return "bad header (first two bytes are not \"P6\")"; break; case 1: width = atoi(token); break; case 2: height = atoi(token); break; case 3: DataSize = atoi(token); if (DataSize != 255) if (fExitOnErr) Err("This program can only deal with data sizes of 255\n" "and %s has a data size of %d", sPath, DataSize); else return "data size not 255"; break; default: break; } nTokens++; input = NULL; } }while (nTokens < 4);if (width < 0 || width > CONF_nMaxImageDim || height > CONF_nMaxImageDim || height < 0) if (fExitOnErr) Err("%s has a strange width %d or height", sPath, width, height); else return "strange width or height";RgbImage RgbTemp(width, height);Fread(RgbTemp.buf, 1, 3 * width * height, pFile, sPath);fclose(pFile);if (pImg) { // copy pRgbImg into buf, converting to gray pImg->dim(width, height); for (int iy = 0; iy < height; iy++) for (int ix = 0; ix < width; ix++) { // CIE conversion to gray, add 500 to take care of rounding // Colors are reversed so have to take care of that too tRGB c = RgbTemp(ix, iy); (*pImg)(ix, iy) = byte((299 * c.Blue + 587 * c.Green + 114 * c.Red + 500) / 1000); } }if (pRgbImg) { // Image comes in upside down with colors reversed. Fix that. pRgbImg->dim(width, height); for (int iy = 0, y1 = height-1; iy < height; iy++, y1--) for (int ix = 0; ix < width; ix++) { (*pRgbImg)(ix, iy).Red = RgbTemp(ix, y1).Blue; (*pRgbImg)(ix, iy).Green = RgbTemp(ix, y1).Green; (*pRgbImg)(ix, iy).Blue = RgbTemp(ix, y1).Red; } }return NULL; // success}//-----------------------------------------------------------------------------static FILE *pOpenTempFile (char sPath[], // out const char sTemplate[], const char sMode[]) // in{char sTemplate1[SLEN];sprintf(sTemplate1, "%sXXXXXX", sTemplate);char *sFile = _mktemp(sTemplate1);if (!sFile) SysErr("Can't generate temporary filename");char *sTmpDir = getenv("TMPDIR");if (!sTmpDir) sTmpDir = getenv("TEMP");if (!sTmpDir) sTmpDir = getenv("TMP");if (!sTmpDir) SysErr("Can't find temporary directory (no environment variables TMPDIR TEMP TMP)");_makepath(sPath, "", sTmpDir, sFile, "tmp");return Fopen(sPath, sMode); // will give err msg and exit if can't open the file}//-----------------------------------------------------------------------------// Load an image. Knows about different types of files like BMPs and JPEGs//// This uses the file extension to determine file type.//// pImg is gray version of the image. Caller must free it. Set to NULL if you don't need it.// pRgbImg is color version of the image. Caller must free it. Set to NULL if you don't need it.//// sPath is the file name.// Set fVerbose if you want to tell the user that you are reading the file.//// fRemovePad=false only applies to RGB bitmaps and is needed to for StretchDIBits() under windowschar *sLoadImage (Image *pImg, RgbImage *pRgbImg, // out const char *sPath, bool fVerbose, bool fExitOnErr, bool fRemovePad) // in{bprintf(!fVerbose, "Reading %s\n", sPath);if (sPath[0] == 0) { sprintf(sgErr, "Null path name, can't load image"); if (fExitOnErr) Err(sgErr); else return sgErr; }char sDrive[_MAX_DRIVE], sDir[_MAX_DIR], sFname[_MAX_FNAME], sExt[_MAX_EXT];_splitpath(sPath, sDrive, sDir, sFname, sExt);if (sExt[0] == 0) { sprintf(sgErr, "Filename %s has no extension: can't determine the image type to read from disk", sPath); if (fExitOnErr) Err(sgErr); else return sgErr; }switch (toupper(sExt[1])) { case 'B': return sLoadBmp(pImg, pRgbImg, sPath, fExitOnErr, fRemovePad); break; case 'J': { // file is a JPEG file: create a temporary BMP file and use that instead
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -