📄 imappend.cpp
字号:
// $image\imappend.cpp 1.5 milbo$ routines for reading and writing appended image files// 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 "imtab.hpp"#include "imappend.hpp"#include "imfile.hpp"#include "jpegutil.hpp"#include "util.hpp"#include "err.hpp"static const bool CONF_fShowEveryFilename = false;//-----------------------------------------------------------------------------// Allocate an image array. Each image is inited to width=0 and height=0Image *pAllocImageArray (size_t nImages){Image *p = (Image *)calloc(nImages * sizeof(Image), 1);return p;}//-----------------------------------------------------------------------------void FreeImageArray (Image aImages[], size_t nImages){if (aImages && nImages) { for (size_t iImage = 0; iImage < nImages; iImage++) aImages[iImage].free(); free(aImages); }}//-----------------------------------------------------------------------------// Return an app image path name given a base name etc.char *sAppImagePathName (const char sBasePath[], const char sFileSpec[], const char sExtra[]){static char *sPath;if (!sPath) sPath = (char *)malloc(PLEN);sprintf(sPath, "%s/%s%s.ap", sBasePath, sMungeFileSpec(sFileSpec, NULL), sExtra);return sPath;}//-----------------------------------------------------------------------------// This accesses sgFiles to get the image namesvoid WriteAppendedImagesAsBmpFiles (const char sDir0[], const char sDir1[], int iStartIndex, Image aImages[], int nImages){char sPath[SLEN];if (fgUserInt) return;sprintf(sPath, "%s/%s/%s", sDir0, sDir1, sgFiles[iStartIndex+0]);if (!CONF_fShowEveryFilename) { lprintf("Writing %d %dx%d images %s", nImages, aImages[0].width, aImages[0].height, sPath); if (nImages > 1) { sprintf(sPath, "%s/%s/%s", sDir0, sDir1, sgFiles[iStartIndex+nImages-1]); lprintf(" to %s ", sPath); } }InitPacifyUser(nImages);for (int iImage = 0; iImage < nImages && !fgUserInt; iImage++) { if (!CONF_fShowEveryFilename) PacifyUser(iImage); sprintf(sPath, "%s/%s/%s", sDir0, sDir1, sgFiles[iStartIndex+iImage]); WriteBmp(aImages[iImage], sPath); }if (!CONF_fShowEveryFilename) lprintf("\n");}//-----------------------------------------------------------------------------// Read in all the files in sgFiles and append them to aImages//// sFileSpec is used to get the directory name// because directory names are not stored in sgFiles//// Use nExpectedWidth and nExpectedHeight of 0 if you don't expect anything.void AppendImagesToBuffer (const char *sFileSpec, int iStart, int nImages, Image aImages[], int nExpectedWidth, int nExpectedHeight){InitPacifyUser(nImages);for (int iImage = 0; iImage < nImages && !fgUserInt; iImage++) { char drive[_MAX_DRIVE], dir[_MAX_DIR]; char fname[_MAX_FNAME], ext[_MAX_EXT]; char driveTmp[_MAX_DRIVE], dirTmp[_MAX_DIR]; char fnameTmp[_MAX_FNAME], extTmp[_MAX_EXT]; char sPath[PLEN]; PacifyUser(iImage); // get the directory from sFileSpec and the filename from sgFiles _splitpath(sFileSpec, drive, dir, fnameTmp, extTmp); _splitpath(sgFiles[iStart+iImage], driveTmp, dirTmp, fname, ext); _makepath(sPath, drive, dir, sgFiles[iStart+iImage], ""); Image Img; sLoadImage(Img, sPath); // this code checks against the expected width and height if (nExpectedWidth && Img.width != nExpectedWidth) Err("%s width is %d, expected %d", sgFiles[iStart+iImage], Img.width, nExpectedWidth); if (nExpectedHeight && Img.height != nExpectedHeight) Err("%s height is %d, expected %d", sgFiles[iStart+iImage], Img.height, nExpectedHeight); // this code is is effective even if the expected height or width are 0 if (Img.width == 0 || Img.height == 0) Err("Can't determine image size of %s", sgFiles[iStart+iImage]); aImages[iImage] = Img; }lprintf("\n");}//-----------------------------------------------------------------------------// The interface to this func is confusing and could be cleaned up.//// If fUseTagArray is false: we use nImages and not iTagArrayStart and nTagArrayEnd// true: we use iTagArrayStart and nTagArrayEnd and not nImagesvoid WriteAppendedImageFile1 (char sPath[], Image aImages[], int nImages, bool fUseTagArray, int iTagArrayStart, int nTagArrayEnd){if (fgUserInt) return;FILE *pFile = Fopen(sPath, "wb");char s[3]; // 2 bytes of "ap"s[0] = 'a';s[1] = 'p';Fwrite(&s, 1, 2, pFile, sPath);s[0] = 0; // 2 bytes of version 0s[1] = 0;Fwrite(&s, 1, 2, pFile, sPath);Fwrite(&aImages[0].width, 1, 2, pFile, sPath); // 2 bytes of widthFwrite(&aImages[0].height, 1, 2, pFile, sPath); // 2 bytes of heightif (fUseTagArray) // n bytes of images { for (int iImage = iTagArrayStart; iImage < nTagArrayEnd; iImage++) if (!fUseTagArray || fImageTagged(iImage)) { byte *p; p = aImages[iImage - iTagArrayStart].buf; Fwrite(p, 1, aImages[iImage].width * aImages[iImage].height, pFile, sPath); } }else for (int iImage = 0; iImage < nImages; iImage++) Fwrite(aImages[iImage].buf, 1, aImages[iImage].width * aImages[iImage].height, pFile, sPath);s[0] = 'a'; // 2 bytes of "ap"s[1] = 'p';Fwrite(&s, 1, 2, pFile, sPath);fclose(pFile);}//-----------------------------------------------------------------------------void WriteAppendedImageFile (char sPath[], Image aImages[], int nImages){lprintf("Writing %s\n", sPath);WriteAppendedImageFile1(sPath, aImages, nImages, false, 0, 0);}//-----------------------------------------------------------------------------FILE *pStartApFile (bool fVerbose, char sPath[], int width, int height){if (fVerbose) lprintf("Writing %s\n", sPath);FILE *pFile = Fopen(sPath, "wb");char s[3]; // 2 bytes of "ap"s[0] = 'a';s[1] = 'p';Fwrite(&s, 1, 2, pFile, sPath);s[0] = 0; // 2 bytes of version 0s[1] = 0;Fwrite(&s, 1, 2, pFile, sPath);Fwrite(&width, 1, 2, pFile, sPath); // 2 bytes of widthFwrite(&height, 1, 2, pFile, sPath); // 2 bytes of heightreturn pFile;}//-----------------------------------------------------------------------------void ContinueApFile (char sPath[], FILE *pFile, Image &Img){Fwrite(Img.buf, 1, Img.width * Img.height, pFile, sPath);}//-----------------------------------------------------------------------------void EndApFile (char sPath[], FILE *pFile){char s[3];s[0] = 'a'; // 2 bytes of "ap"s[1] = 'p';Fwrite(&s, 1, 2, pFile, sPath);fclose(pFile);}//-----------------------------------------------------------------------------static long iFileSize (const char sPath[]){struct stat statbuf;if (stat(sPath,&statbuf) == -1) return -1;else return statbuf.st_size;}//-----------------------------------------------------------------------------int GetNbrImagesInAppendedImageFile (const char sPath[], int width, int height){int nBytesImageData = iFileSize(sPath);if (nBytesImageData < 0) Err("Can't access %s", sPath);nBytesImageData -= 10; // minus 'ap' + version + width + height + 'ap'int nImages = nBytesImageData / (width * height);if (nImages < 1) Err("%s is too small to be a genuine .ap file", sPath);return nImages;}//-----------------------------------------------------------------------------void ReadAppendedImageFile (const char sPath[], Image *aImages, int nImages, int nExpectedWidth, int nExpectedHeight){char s[10];lprintf("Reading %s", sPath);FILE *pFile = Fopen(sPath, "rb");long nBytesImageData = _filelength(_fileno(pFile));nBytesImageData -= 10; // minus 'ap' + version + width + height + 'ap'Fread(&s, 1, 2, pFile, sPath); // header "ap"if (s[0] != 'a' || s[1] != 'p') Err("%s has a bad header (first two bytes are not \"ap\")", sPath);Fread(&s, 1, 2, pFile, sPath); // versionif (s[0] != 0 || s[1] != 0) Err("%s has a bad header (bad version)", sPath);WORD width; // widthFread(&width, 1, 2, pFile, sPath);WORD height; // heightFread(&height, 1, 2, pFile, sPath);double NbrImagesInFile = (double)nBytesImageData / (width * height);lprintf(" %g %dx%d images ", NbrImagesInFile, width, height);if (nExpectedWidth && width != nExpectedWidth) Err("%s width is %d, expected %d", sPath, width, nExpectedWidth);if (nExpectedHeight && height != nExpectedHeight) Err("%s height is %d, expected %d", sPath, height, nExpectedHeight);if (floor(NbrImagesInFile) != NbrImagesInFile) Err("Corrupt %s (it doesn't contain an integral number of images)", sPath);if ((int)NbrImagesInFile != nImages) lprintf("(only reading %d of %g images)", nImages, NbrImagesInFile);for (int iImage = 0; iImage < nImages; iImage++) { aImages[iImage].dim(width, height); if (fread(aImages[iImage].buf, 1, width * height, pFile) != (unsigned)width * height) Err("Can't read %s (it's shorter than its header says it should be?)", sPath); }if (NbrImagesInFile == nImages) { // footer if (fread(&s, 1, 2, pFile) != 2) Err("Can't read %s (it's shorter than its header says it should be?)", sPath); if (s[0] != 'a' || s[1] != 'p') Err("%s has a bad footer (last two bytes are not \"ap\")", sPath); }fclose(pFile);lprintf("\n");}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -