summaryrefslogtreecommitdiff
path: root/common/image.cpp
diff options
context:
space:
mode:
authorleo2001-03-26 17:19:57 +0000
committerleo2001-03-26 17:19:57 +0000
commitf1b22e07982337233ee4c1ad4cfbee0334ad93df (patch)
tree4a1c6acb65fd7cf4916f10cbd18e221a0386c126 /common/image.cpp
parente8c9abea837366ee7dd5f4668ee459a26be32e9c (diff)
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
Diffstat (limited to 'common/image.cpp')
-rw-r--r--common/image.cpp319
1 files changed, 216 insertions, 103 deletions
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 <windows.h>
#include <windowsx.h>
@@ -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);
}