From f1b22e07982337233ee4c1ad4cfbee0334ad93df Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 26 Mar 2001 17:19:57 +0000 Subject: Reorganized the Image I/O functions, created a new Image class. git-svn-id: http://svn.leocad.org/trunk@263 c7d43263-9d01-0410-8a33-9dba5d9f93d6 --- common/image.cpp | 319 +++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 216 insertions(+), 103 deletions(-) (limited to 'common/image.cpp') diff --git a/common/image.cpp b/common/image.cpp index eae2594..7f2e5c8 100644 --- a/common/image.cpp +++ b/common/image.cpp @@ -1,6 +1,7 @@ // Image I/O routines // +#include "opengl.h" #ifdef LC_WINDOWS #include #include @@ -16,178 +17,290 @@ #include "file.h" // ============================================================================= -// Function declarations (functions from the im_xxx.cpp files) +// Image functions -LC_IMAGE* OpenJPG (char* filename); -LC_IMAGE* OpenBMP (char* filename); -LC_IMAGE* OpenPNG (char* filename); -LC_IMAGE* OpenGIF (File* file); +Image::Image () +{ + m_nWidth = 0; + m_nHeight = 0; + m_bAlpha = false; + m_pData = NULL; +} -bool SaveJPG (char* filename, LC_IMAGE* image, int quality, bool progressive); -bool SaveBMP (char* filename, LC_IMAGE* image, bool quantize); -bool SavePNG (char* filename, LC_IMAGE* image, bool transparent, bool interlaced, unsigned char* background); -bool SaveGIF (File* file, LC_IMAGE* image, bool transparent, bool interlaced, unsigned char* background); +Image::~Image () +{ + free (m_pData); +} -// ============================================================================= -// Static functions +void Image::FreeData () +{ + m_nWidth = 0; + m_nHeight = 0; + m_bAlpha = false; + free (m_pData); + m_pData = NULL; +} -static LC_IMAGE* ResizeImage(LC_IMAGE* image) +void Image::ResizePow2 () { - int i, j; - long shifted_x, shifted_y; - if (image == NULL) - return NULL; + int i, shifted_x, shifted_y; - shifted_x = image->width; + shifted_x = m_nWidth; for (i = 0; ((i < 16) && (shifted_x != 0)); i++) shifted_x = shifted_x >> 1; shifted_x = (i != 0) ? 1 << (i-1) : 1; - shifted_y = image->height; + shifted_y = m_nHeight; for (i = 0; ((i < 16) && (shifted_y != 0)); i++) shifted_y = shifted_y >> 1; shifted_y = (i != 0) ? 1 << (i-1) : 1; - if ((shifted_x == image->width) && (shifted_y == image->height)) - return image; - - LC_IMAGE* newimage = (LC_IMAGE*)malloc(shifted_x*shifted_y*3+sizeof(LC_IMAGE)); - newimage->width = (unsigned short)shifted_x; - newimage->height = (unsigned short)shifted_y; - newimage->bits = (unsigned char*)newimage + sizeof(LC_IMAGE); - memset(newimage->bits, 0, shifted_x*shifted_y*3); + if ((shifted_x != m_nWidth) || (shifted_y != m_nHeight)) + Resize (shifted_x, shifted_y); +} +void Image::Resize (int width, int height) +{ + int i, j, k, components, stx, sty; float accumx, accumy; - int stx, sty; - unsigned char *oldbits = (unsigned char*)image->bits, - *newbits = (unsigned char*)newimage->bits; + unsigned char* bits; + + if (m_bAlpha) + components = 4; + else + components = 3; - for (j = 0; j < image->height; j++) + bits = (unsigned char*)malloc (width * height * components); + + for (j = 0; j < m_nHeight; j++) { - accumy = (float)newimage->height*j/(float)image->height; + accumy = (float)height*j/(float)m_nHeight; sty = (int)floor(accumy); - for (i = 0; i < image->width; i++) + for (i = 0; i < m_nWidth; i++) { - accumx = (float)newimage->width*i/(float)image->width; + accumx = (float)width*i/(float)m_nWidth; stx = (int)floor(accumx); - newbits[(stx+sty*newimage->width)*3] = oldbits[(i+j*image->width)*3]; - newbits[(stx+sty*newimage->width)*3+1] = oldbits[(i+j*image->width)*3+1]; - newbits[(stx+sty*newimage->width)*3+2] = oldbits[(i+j*image->width)*3+2]; + for (k = 0; k < components; k++) + bits[(stx+sty*width)*components+k] = m_pData[(i+j*m_nWidth)*components+k]; } } - free(image); - return newimage; + free (m_pData); + m_pData = bits; + m_nWidth = width; + m_nHeight = height; } -// ============================================================================= -// Global functions +void Image::FromOpenGL (int width, int height) +{ + unsigned char *buf; + buf = (unsigned char*)malloc (width*height*3); + + FreeData (); + + m_pData = (unsigned char*)malloc (width*height*3); + m_nWidth = width; + m_nHeight = height; + m_bAlpha = false; + + glPixelStorei (GL_PACK_ALIGNMENT, 1); + glReadPixels (0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, buf); + + for (int row = 0; row < height; row++) + memcpy (m_pData + (row*width*3), buf + ((height-row-1)*width*3), width*3); + + free (buf); +} -// Reads a file from disk -LC_IMAGE* OpenImage(char* filename) +bool Image::FileLoad (File& file) { - char ext[5]; - if (strlen(filename) != 0) + unsigned char buf[8]; + + // Read a few bytes + if (file.Read (buf, 8) != 8) + return false; + file.Seek (-8, SEEK_CUR); + + // Check for the BMP header + if ((buf[0] == 'B') && (buf[1] == 'M')) { - char *p = strrchr(filename, '.'); - if (p != NULL) - strcpy (ext, p+1); + if (!LoadBMP (file)) + return false; + + ResizePow2 (); + return true; } - strlwr(ext); #ifdef LC_HAVE_JPEGLIB - if ((strcmp(ext, "jpg") == 0) || (strcmp (ext, "jpeg") == 0)) - return ResizeImage(OpenJPG(filename)); -#endif + if ((buf[0] == 0xFF) && (buf[1] == 0xD8)) + { + if (!LoadJPG (file)) + return false; - if (strcmp(ext, "bmp") == 0) - return ResizeImage(OpenBMP(filename)); + ResizePow2 (); + return true; + } +#endif #ifdef LC_HAVE_PNGLIB - if (strcmp(ext, "png") == 0) - return ResizeImage(OpenPNG(filename)); + const unsigned char png_signature[8] = { 137, 80, 78, 71, 13, 10, 26, 10 }; + + // Check for the PNG header + if (memcmp (buf, png_signature, 8) == 0) + { + if (!LoadPNG (file)) + return false; + + ResizePow2 (); + return true; + } #endif - if ((strcmp (ext, "gif") == 0) || (strcmp (ext, "tmp") == 0)) + // Check for the GIF header + if ((buf[0] == 'G') && (buf[1] == 'I') && (buf[2] == 'F') && + (buf[3] == '8') && ((buf[4] != '7') || (buf[4] == '9')) && + (buf[5] == 'a')) { - FileDisk file; - if (!file.Open(filename, "rb")) - return NULL; - LC_IMAGE* image = ResizeImage(OpenGIF(&file)); - file.Close(); - return image; + if (!LoadGIF (file)) + return false; + + ResizePow2 (); + return true; } // MessageBox (NULL, "Unknown File Format", "Error", MB_ICONSTOP); - - return NULL; + return false; } -LC_IMAGE* OpenImage(File* file, unsigned char format) +bool Image::FileLoad (const char* filename) { - if (format != LC_IMAGE_GIF) - return NULL; - return OpenGIF(file); + FileDisk file; + + if (!file.Open (filename, "rb")) + return false; + + return FileLoad (file); } -bool SaveImage(char* filename, LC_IMAGE* image, LC_IMAGE_OPTS* opts) +bool Image::FileSave (File& file, LC_IMAGE_OPTS* opts) const { - char ext[5]; - if (strlen(filename) != 0) + switch (opts->format) { - char *p = strrchr(filename, '.'); - if (p != NULL) - strcpy(ext, p+1); - } - strlwr(ext); - #ifdef LC_HAVE_JPEGLIB - if ((strcmp (ext, "jpg") == 0) || (strcmp (ext, "jpeg") == 0)) - return SaveJPG(filename, image, opts->quality, opts->interlaced); + case LC_IMAGE_JPG: + return SaveJPG (file, opts->quality, opts->interlaced); #endif - if (strcmp (ext, "gif") == 0) - { - FileDisk file; - if (!file.Open(filename, "wb")) - return false; - - bool ret = SaveGIF(&file, image, opts->transparent, opts->interlaced, opts->background); - file.Close(); - return ret; - } + case LC_IMAGE_GIF: + return SaveGIF (file, opts->transparent, opts->interlaced, opts->background); - if (strcmp (ext, "bmp") == 0) - return SaveBMP(filename, image, opts->truecolor == false); + case LC_IMAGE_BMP: + return SaveBMP (file, opts->truecolor == false); #ifdef LC_HAVE_PNGLIB - if (strcmp (ext, "png") == 0) - return SavePNG(filename, image, opts->transparent, opts->interlaced, opts->background); + case LC_IMAGE_PNG: + return SavePNG (file, opts->transparent, opts->interlaced, opts->background); #endif + default: + break; + } + // MessageBox (NULL, "Could not save file", "Error", MB_ICONSTOP); return false; } -bool SaveImage(File* file, LC_IMAGE* image, LC_IMAGE_OPTS* opts) +bool Image::FileSave (const char* filename, LC_IMAGE_OPTS* opts) const { - if (opts->format != LC_IMAGE_GIF) + char name[LC_MAXPATH], ext[5], *p; + FileDisk file; + bool needext = false; + + strcpy (name, filename); + p = name + strlen (name) - 1; + + while ((p > name) && (*p != '/') && (*p != '\\') && (*p != '.')) + p--; + + if (*p != '.') + needext = true; + else + { + if (strlen (p) > 5) + needext = true; + else + { + strcpy (ext, p+1); + strlwr (ext); + + if (strcmp (ext, "bmp") == 0) + opts->format = LC_IMAGE_BMP; + else if (strcmp (ext, "gif") == 0) + opts->format = LC_IMAGE_GIF; +#ifdef LC_HAVE_JPEGLIB + else if (strcmp (ext, "jpg") == 0) + opts->format = LC_IMAGE_JPG; + else if (strcmp (ext, "jpeg") == 0) + opts->format = LC_IMAGE_JPG; +#endif +#ifdef LC_HAVE_PNGLIB + else if (strcmp (ext, "png") == 0) + opts->format = LC_IMAGE_PNG; +#endif + else + needext = true; + } + } + + if (needext) + { + // no extension, add from the options + switch (opts->format) + { + case LC_IMAGE_BMP: + strcat (name, ".bmp"); + break; + case LC_IMAGE_GIF: + strcat (name, ".gif"); + break; +#ifdef LC_HAVE_JPEGLIB + case LC_IMAGE_JPG: + strcat (name, ".jpg"); + break; +#endif +#ifdef LC_HAVE_PNGLIB + case LC_IMAGE_PNG: + strcat (name, ".png"); + break; +#endif + default: + return false; + } + } + + if (!file.Open (name, "wb")) return false; - return SaveGIF(file, image, opts->transparent, opts->interlaced, opts->background); + + return FileSave (file, opts); } + + +// ============================================================================= +// Global functions + #ifdef LC_WINDOWS #include "system.h" #define AVIIF_KEYFRAME 0x00000010L // this frame is a key frame. #define LPLPBI LPBITMAPINFOHEADER * -static HANDLE MakeDib (HBITMAP hbitmap, LC_IMAGE *image) +static HANDLE MakeDib (HBITMAP hbitmap, Image& image) { HANDLE hdib ; HDC hdc ; @@ -238,7 +351,7 @@ static HANDLE MakeDib (HBITMAP hbitmap, LC_IMAGE *image) for (i = 0; i < lpbi->biHeight; i++) { - unsigned char *src = (unsigned char*)image->bits + i * image->width * 3; + unsigned char *src = image.GetData() + i * image.Width() * 3; unsigned char *dst = lpBits + (lpbi->biHeight - i - 1) * wLineLen; for (j = 0; j < lpbi->biWidth; j++) @@ -279,7 +392,7 @@ static void FreeFrames(LPLPBI alpbi, int frames) } // Fill an array of LPBI's with the frames for this movie -static void MakeFrames (LPLPBI alpbi, LC_IMAGE **images, int frames) +static void MakeFrames (LPLPBI alpbi, Image *images, int frames) { HBITMAP hbitmap, hbitmapOld; HDC hdc, hdcMem; @@ -289,7 +402,7 @@ static void MakeFrames (LPLPBI alpbi, LC_IMAGE **images, int frames) hdc = GetDC (NULL); hdcMem = CreateCompatibleDC (NULL); - hbitmap = CreateCompatibleBitmap (hdc, images[0]->width, images[0]->height); + hbitmap = CreateCompatibleBitmap (hdc, images[0].Width (), images[0].Height ()); // Now walk through and make all the frames for ( i=0; i < frames; i++ ) @@ -297,7 +410,7 @@ static void MakeFrames (LPLPBI alpbi, LC_IMAGE **images, int frames) hbitmapOld = SelectBitmap(hdcMem, hbitmap); // Fill the whole frame with white - SetRect(&rc,0,0,images[0]->width,images[0]->height) ; + SetRect(&rc,0,0,images[0].Width (), images[0].Height ()); FillRect(hdcMem,&rc,GetStockBrush(WHITE_BRUSH)); SelectBitmap(hdcMem, hbitmapOld); @@ -316,7 +429,7 @@ static void MakeFrames (LPLPBI alpbi, LC_IMAGE **images, int frames) ReleaseDC(NULL,hdc) ; } -void SaveVideo(char* filename, LC_IMAGE** images, int count, float fps) +void SaveVideo(char* filename, Image *images, int count, float fps) { AVISTREAMINFO strhdr; PAVIFILE pfile = NULL; @@ -382,7 +495,7 @@ void SaveVideo(char* filename, LC_IMAGE** images, int count, float fps) AVIFileExit(); } #else -void SaveVideo(char* filename, LC_IMAGE** images, int count, float fps) +void SaveVideo(char* filename, Image *images, int count, float fps) { // SystemDoMessageBox("Format not supported under this platform.", LC_MB_OK|LC_MB_ERROR); } -- cgit v1.2.3