summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorleo2001-03-26 17:19:57 +0000
committerleo2001-03-26 17:19:57 +0000
commitf1b22e07982337233ee4c1ad4cfbee0334ad93df (patch)
tree4a1c6acb65fd7cf4916f10cbd18e221a0386c126 /common
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')
-rwxr-xr-xcommon/im_bmp.cpp330
-rw-r--r--common/im_gif.cpp244
-rw-r--r--common/im_jpg.cpp275
-rwxr-xr-xcommon/im_png.cpp221
-rw-r--r--common/image.cpp319
-rw-r--r--common/image.h49
-rw-r--r--common/project.cpp95
-rw-r--r--common/project.h3
-rw-r--r--common/texture.cpp26
-rw-r--r--common/typedefs.h8
10 files changed, 933 insertions, 637 deletions
diff --git a/common/im_bmp.cpp b/common/im_bmp.cpp
index 4156701..f850fa7 100755
--- a/common/im_bmp.cpp
+++ b/common/im_bmp.cpp
@@ -1,98 +1,86 @@
#include <stdio.h>
#include <stdlib.h>
-#include "typedefs.h"
+#include "config.h"
#include "quant.h"
+#include "image.h"
+#include "file.h"
// ========================================================
-LC_IMAGE* OpenBMP (char* filename)
+bool Image::LoadBMP (File& file)
{
- int bmWidth;
- int bmHeight;
- unsigned char bmPlanes;
- unsigned char bmBitsPixel;
- typedef struct {
- unsigned char rgbBlue;
- unsigned char rgbGreen;
- unsigned char rgbRed;
- unsigned char rgbReserved;
- } RGBQUAD;
- unsigned char m1,m2;
- unsigned long sizeimage;
- short res1,res2;
- long filesize, pixoff;
- long bmisize, compression;
- long xscale, yscale;
- long colors, impcol;
- LC_IMAGE* image;
- unsigned long m_bytesRead = 0;
- FILE *fp;
-
- fp = fopen(filename,"rb");
- if (fp == NULL)
- return NULL;
-
- long rc;
- rc = fread(&m1, 1, 1, fp);
+ lcint32 bmWidth, bmHeight;
+ lcuint8 bmPlanes, bmBitsPixel, m1, m2;
+ typedef struct {
+ unsigned char rgbBlue;
+ unsigned char rgbGreen;
+ unsigned char rgbRed;
+ unsigned char rgbReserved;
+ } RGBQUAD;
+ lcint16 res1,res2;
+ lcint32 filesize, pixoff;
+ lcint32 bmisize, compression;
+ lcint32 xscale, yscale;
+ lcint32 colors, impcol, rc;
+ lcuint32 sizeimage, m_bytesRead = 0;
+
+ FreeData ();
+
+ if (file.Read (&m1, 1) != 1)
+ return false;
m_bytesRead++;
- if (rc == -1)
- {
- fclose(fp);
- return NULL;
- }
- rc = fread(&m2, 1, 1, fp);
+ if (file.Read (&m2, 1) != 1)
+ return false;
m_bytesRead++;
- if ((m1!='B') || (m2!='M'))
- {
- fclose(fp);
- return NULL;
- }
- rc = fread((long*)&(filesize),4,1,fp); m_bytesRead+=4;
- if (rc != 1) { fclose(fp); return NULL; }
+ if ((m1 != 'B') || (m2 != 'M'))
+ return false;
+
+ rc = file.ReadLong ((long*)&(filesize), 1); m_bytesRead+=4;
+ if (rc != 1) { return false; }
- rc = fread((int*)&(res1),2,1,fp); m_bytesRead+=2;
- if (rc != 1) { fclose(fp); return NULL; }
+ rc = file.ReadShort ((int*)&(res1), 1); m_bytesRead+=2;
+ if (rc != 1) { return false; }
- rc = fread((int*)&(res2),2,1,fp); m_bytesRead+=2;
- if (rc != 1) { fclose(fp); return NULL; }
+ rc = file.ReadShort ((int*)&(res2), 1); m_bytesRead+=2;
+ if (rc != 1) { return false; }
- rc = fread((long*)&(pixoff),4,1,fp); m_bytesRead+=4;
- if (rc != 1) { fclose(fp); return NULL; }
+ rc = file.ReadLong ((long*)&(pixoff), 1); m_bytesRead+=4;
+ if (rc != 1) { return false; }
- rc = fread((long*)&(bmisize),4,1,fp); m_bytesRead+=4;
- if (rc != 1) { fclose(fp); return NULL; }
+ rc = file.ReadLong ((long*)&(bmisize), 1); m_bytesRead+=4;
+ if (rc != 1) { return false; }
- rc = fread((long *)&(bmWidth),4,1,fp); m_bytesRead+=4;
- if (rc != 1) { fclose(fp); return NULL; }
+ rc = file.ReadLong ((long*)&(bmWidth), 1); m_bytesRead+=4;
+ if (rc != 1) { return false; }
- rc = fread((long*)&(bmHeight),4,1,fp); m_bytesRead+=4;
- if (rc != 1) { fclose(fp); return NULL; }
+ rc = file.ReadLong ((long*)&(bmHeight), 1); m_bytesRead+=4;
+ if (rc != 1) { return false; }
- rc = fread((int*)&(bmPlanes),2,1,fp); m_bytesRead+=2;
- if (rc != 1) { fclose(fp); return NULL; }
+ rc = file.ReadShort ((int*)&(bmPlanes), 1); m_bytesRead+=2;
+ if (rc != 1) { return false; }
- rc = fread((int*)&(bmBitsPixel),2,1,fp); m_bytesRead+=2;
- if (rc != 1) { fclose(fp); return NULL; }
+ rc = file.ReadShort ((int*)&(bmBitsPixel), 1); m_bytesRead+=2;
+ if (rc != 1) { return false; }
- rc = fread((long*)&(compression),4,1,fp); m_bytesRead+=4;
- if (rc != 1) { fclose(fp); return NULL; }
+ rc = file.ReadLong ((long*)&(compression), 1); m_bytesRead+=4;
+ if (rc != 1) { return false; }
- rc = fread((long*)&(sizeimage),4,1,fp); m_bytesRead+=4;
- if (rc != 1) {fclose(fp); return NULL; }
+ rc = file.ReadLong ((long*)&(sizeimage), 1); m_bytesRead+=4;
+ if (rc != 1) {return false; }
- rc = fread((long*)&(xscale),4,1,fp); m_bytesRead+=4;
- if (rc != 1) { fclose(fp); return NULL; }
+ rc = file.ReadLong ((long*)&(xscale), 1); m_bytesRead+=4;
+ if (rc != 1) { return false; }
- rc = fread((long*)&(yscale),4,1,fp); m_bytesRead+=4;
- if (rc != 1) { fclose(fp); return NULL; }
+ rc = file.ReadLong ((long*)&(yscale), 1); m_bytesRead+=4;
+ if (rc != 1) { return false; }
- rc = fread((long*)&(colors),4,1,fp); m_bytesRead+=4;
- if (rc != 1) { fclose(fp); return NULL; }
+ rc = file.ReadLong ((long*)&(colors), 1); m_bytesRead+=4;
+ if (rc != 1) { return false; }
- rc = fread((long*)&(impcol),4,1,fp); m_bytesRead+=4;
- if (rc != 1) { fclose(fp); return NULL; }
+ rc = file.ReadLong ((long*)&(impcol), 1); m_bytesRead+=4;
+ if (rc != 1) { return false; }
if (colors == 0)
colors = 1 << bmBitsPixel;
@@ -103,70 +91,61 @@ LC_IMAGE* OpenBMP (char* filename)
{
colormap = new RGBQUAD[colors];
if (colormap == NULL)
- {
- fclose(fp);
- return NULL;
- }
+ return false;
int i;
for (i = 0; i < colors; i++)
{
unsigned char r ,g, b, dummy;
- rc = fread(&b, 1, 1, fp);
+ rc = file.Read (&b, 1);
m_bytesRead++;
if (rc!=1)
{
delete [] colormap;
- fclose(fp);
- return NULL;
+ return false;
}
- rc = fread(&g, 1, 1, fp);
+ rc = file.Read (&g, 1);
m_bytesRead++;
if (rc!=1)
{
delete [] colormap;
- fclose(fp);
- return NULL;
+ return false;
}
- rc = fread(&r, 1, 1, fp);
+ rc = file.Read (&r, 1);
m_bytesRead++;
if (rc != 1)
{
delete [] colormap;
- fclose(fp);
- return NULL;
+ return false;
}
-
- rc = fread(&dummy, 1, 1, fp);
+ rc = file.Read (&dummy, 1);
m_bytesRead++;
if (rc != 1)
{
delete [] colormap;
- fclose(fp);
- return NULL;
+ return false;
}
- colormap[i].rgbRed=r;
- colormap[i].rgbGreen=g;
- colormap[i].rgbBlue=b;
+ colormap[i].rgbRed = r;
+ colormap[i].rgbGreen = g;
+ colormap[i].rgbBlue = b;
}
}
if ((long)m_bytesRead > pixoff)
{
delete [] colormap;
- fclose(fp);
- return NULL;
+ return false;
}
while ((long)m_bytesRead < pixoff)
{
char dummy;
- fread(&dummy,1,1,fp);
+ file.Read (&dummy, 1);
m_bytesRead++;
}
@@ -174,15 +153,15 @@ LC_IMAGE* OpenBMP (char* filename)
int h = bmHeight;
// set the output params
- image = (LC_IMAGE*)malloc(w*h*3 + sizeof(LC_IMAGE));
+ m_pData = (unsigned char*)malloc (w*h*3);
long row_size = w * 3;
- if (image != NULL)
+ if (m_pData != NULL)
{
- image->width = w;
- image->height = h;
- image->bits = (char*)image + sizeof(LC_IMAGE);
- unsigned char* outbuf = (unsigned char*)image->bits;
+ m_nWidth = w;
+ m_nHeight = h;
+ m_bAlpha = false;
+ unsigned char* outbuf = m_pData;
long row = 0;
long rowOffset = 0;
@@ -201,12 +180,12 @@ LC_IMAGE* OpenBMP (char* filename)
long offset = col * 3;
char pixel[3];
- if (fread((void*)(pixel),1,3,fp)==3)
+ if (file.Read (pixel, 3) ==3)
{
// we swap red and blue here
- *(outbuf + rowOffset + offset + 0)=pixel[2]; // r
- *(outbuf + rowOffset + offset + 1)=pixel[1]; // g
- *(outbuf + rowOffset + offset + 2)=pixel[0]; // b
+ *(outbuf + rowOffset + offset + 0) = pixel[2]; // r
+ *(outbuf + rowOffset + offset + 1) = pixel[1]; // g
+ *(outbuf + rowOffset + offset + 2) = pixel[0]; // b
}
}
m_bytesRead += row_size;
@@ -215,11 +194,10 @@ LC_IMAGE* OpenBMP (char* filename)
while ((m_bytesRead-pixoff)&3)
{
char dummy;
- if (fread(&dummy,1,1,fp) != 1)
+ if (file.Read (&dummy, 1) != 1)
{
- free(image);
- fclose(fp);
- return NULL;
+ FreeData ();
+ return false;
}
m_bytesRead++;
}
@@ -239,12 +217,11 @@ LC_IMAGE* OpenBMP (char* filename)
if (bit_count <= 0)
{
bit_count = 8;
- if (fread(&inbyte,1,1,fp) != 1)
+ if (file.Read (&inbyte, 1) != 1)
{
- free(image);
+ FreeData ();
delete [] colormap;
- fclose(fp);
- return NULL;
+ return false;
}
m_bytesRead++;
}
@@ -264,13 +241,12 @@ LC_IMAGE* OpenBMP (char* filename)
while ((m_bytesRead-pixoff)&3)
{
char dummy;
- if (fread(&dummy,1,1,fp)!=1)
+ if (file.Read (&dummy, 1) != 1)
{
- free(image);
+ FreeData ();
if (colormap)
delete [] colormap;
- fclose(fp);
- return NULL;
+ return false;
}
m_bytesRead++;
}
@@ -288,12 +264,12 @@ LC_IMAGE* OpenBMP (char* filename)
{
while (row < bmHeight)
{
- c = getc(fp);
+ c = file.GetChar ();
if (c)
{
// encoded mode
- c1 = getc(fp);
+ c1 = file.GetChar ();
for (i = 0; i < c; x++, i++)
{
*pp = colormap[c1].rgbRed; pp++;
@@ -304,7 +280,7 @@ LC_IMAGE* OpenBMP (char* filename)
else
{
// c==0x00, escape codes
- c = getc(fp);
+ c = file.GetChar ();
if (c == 0x00) // end of line
{
@@ -316,9 +292,9 @@ LC_IMAGE* OpenBMP (char* filename)
break; // end of pic
else if (c == 0x02) // delta
{
- c = getc(fp);
+ c = file.GetChar ();
x += c;
- c = getc(fp);
+ c = file.GetChar ();
row += c;
pp = outbuf + x*3 + (bmHeight-row-1)*bmWidth*3;
}
@@ -326,14 +302,14 @@ LC_IMAGE* OpenBMP (char* filename)
{
for (i = 0; i < c; x++, i++)
{
- c1 = getc(fp);
+ c1 = file.GetChar ();
*pp = colormap[c1].rgbRed; pp++;
*pp = colormap[c1].rgbGreen; pp++;
*pp = colormap[c1].rgbBlue; pp++;
}
if (c & 1)
- getc(fp); // odd length run: read an extra pad byte
+ file.GetChar (); // odd length run: read an extra pad byte
}
}
}
@@ -342,12 +318,12 @@ LC_IMAGE* OpenBMP (char* filename)
{
while (row < bmHeight)
{
- c = getc(fp);
+ c = file.GetChar ();
if (c)
{
// encoded mode
- c1 = getc(fp);
+ c1 = file.GetChar ();
for (i = 0; i < c; x++, i++)
{
*pp = colormap[(i&1) ? (c1 & 0x0f) : ((c1>>4)&0x0f)].rgbRed; pp++;
@@ -358,7 +334,7 @@ LC_IMAGE* OpenBMP (char* filename)
else
{
// c==0x00, escape codes
- c = getc(fp);
+ c = file.GetChar ();
if (c == 0x00) // end of line
{
@@ -370,9 +346,9 @@ LC_IMAGE* OpenBMP (char* filename)
break; // end of pic
else if (c == 0x02) // delta
{
- c = getc(fp);
+ c = file.GetChar ();
x += c;
- c = getc(fp);
+ c = file.GetChar ();
row += c;
pp = outbuf + x*3 + (bmHeight-row-1)*bmWidth*3;
}
@@ -381,14 +357,14 @@ LC_IMAGE* OpenBMP (char* filename)
for (i = 0; i < c; x++, i++)
{
if ((i&1) == 0)
- c1 = getc(fp);
+ c1 = file.GetChar ();
*pp = colormap[(i&1) ? (c1 & 0x0f) : ((c1>>4)&0x0f)].rgbRed; pp++;
*pp = colormap[(i&1) ? (c1 & 0x0f) : ((c1>>4)&0x0f)].rgbGreen; pp++;
*pp = colormap[(i&1) ? (c1 & 0x0f) : ((c1>>4)&0x0f)].rgbBlue; pp++;
}
if (((c&3) == 1) || ((c&3) == 2))
- getc(fp); // odd length run: read an extra pad byte
+ file.GetChar (); // odd length run: read an extra pad byte
}
}
}
@@ -397,89 +373,82 @@ LC_IMAGE* OpenBMP (char* filename)
if (colormap)
delete [] colormap;
-
- fclose(fp);
}
- return image;
+ return true;
}
// ========================================================
-bool SaveBMP(char* filename, LC_IMAGE* image, bool quantize)
+bool Image::SaveBMP (File& file, bool quantize) const
{
- FILE *fp;
- fp = fopen(filename, "wb");
- if (fp == NULL)
- return false;
-
unsigned short bits;
unsigned long cmap, bfSize;
unsigned char pal[3][256], *colormappedbuffer = NULL;
if (quantize)
{
- colormappedbuffer = (unsigned char*)malloc(image->width*image->height);
- dl1quant((unsigned char*)image->bits, colormappedbuffer, image->width, image->height, 256, true, pal);
+ colormappedbuffer = (unsigned char*)malloc(m_nWidth*m_nHeight);
+ dl1quant (m_pData, colormappedbuffer, m_nWidth, m_nHeight, 256, true, pal);
bits = 8;
cmap = 256;
- bfSize = 1078 + image->width*image->height;
+ bfSize = 1078 + m_nWidth*m_nHeight;
}
else
{
bits = 24;
cmap = 0;
- bfSize = 54 + image->width*image->height*3;
+ bfSize = 54 + m_nWidth*m_nHeight*3;
}
long byteswritten = 0;
long pixoff = 54 + cmap*4;
short res = 0;
char m1 ='B', m2 ='M';
- fwrite(&m1, 1, 1, fp); byteswritten++; // B
- fwrite(&m2, 1, 1, fp); byteswritten++; // M
- fwrite(&bfSize, 4, 1, fp); byteswritten+=4;// bfSize
- fwrite(&res, 2, 1, fp); byteswritten+=2;// bfReserved1
- fwrite(&res, 2, 1, fp); byteswritten+=2;// bfReserved2
- fwrite(&pixoff, 4, 1, fp); byteswritten+=4;// bfOffBits
-
- unsigned long biSize = 40, compress = 0, size = 0;
- long width = image->width, height = image->height, pixels = 0;
- unsigned short planes = 1;
- fwrite(&biSize, 4, 1, fp); byteswritten+=4;// biSize
- fwrite(&width, 4, 1, fp); byteswritten+=4;// biWidth
- fwrite(&height, 4, 1, fp); byteswritten+=4;// biHeight
- fwrite(&planes, 2, 1, fp); byteswritten+=2;// biPlanes
- fwrite(&bits, 2, 1, fp); byteswritten+=2;// biBitCount
- fwrite(&compress, 4, 1, fp);byteswritten+=4;// biCompression
- fwrite(&size, 4, 1, fp); byteswritten+=4;// biSizeImage
- fwrite(&pixels, 4, 1, fp); byteswritten+=4;// biXPelsPerMeter
- fwrite(&pixels, 4, 1, fp); byteswritten+=4;// biYPelsPerMeter
- fwrite(&cmap, 4, 1, fp); byteswritten+=4;// biClrUsed
- fwrite(&cmap, 4, 1, fp); byteswritten+=4;// biClrImportant
+ file.WriteByte (&m1, 1); byteswritten++; // B
+ file.WriteByte (&m2, 1); byteswritten++; // M
+ file.WriteLong (&bfSize, 1); byteswritten+=4;// bfSize
+ file.WriteShort (&res, 1); byteswritten+=2;// bfReserved1
+ file.WriteShort (&res, 1); byteswritten+=2;// bfReserved2
+ file.WriteLong (&pixoff, 1); byteswritten+=4;// bfOffBits
+
+ lcuint32 biSize = 40, compress = 0, size = 0;
+ lcint32 width = m_nWidth, height = m_nHeight, pixels = 0;
+ lcuint16 planes = 1;
+ file.WriteLong (&biSize, 1); byteswritten+=4;// biSize
+ file.WriteLong (&width, 1); byteswritten+=4;// biWidth
+ file.WriteLong (&height, 1); byteswritten+=4;// biHeight
+ file.WriteShort (&planes, 1); byteswritten+=2;// biPlanes
+ file.WriteShort (&bits, 1); byteswritten+=2;// biBitCount
+ file.WriteLong (&compress, 1); byteswritten+=4;// biCompression
+ file.WriteLong (&size, 1); byteswritten+=4;// biSizeImage
+ file.WriteLong (&pixels, 1); byteswritten+=4;// biXPelsPerMeter
+ file.WriteLong (&pixels, 1); byteswritten+=4;// biYPelsPerMeter
+ file.WriteLong (&cmap, 1); byteswritten+=4;// biClrUsed
+ file.WriteLong (&cmap, 1); byteswritten+=4;// biClrImportant
if (quantize)
{
for (int i = 0; i < 256; i++)
{
- putc(pal[2][i], fp);
- putc(pal[1][i], fp);
- putc(pal[0][i], fp);
- putc(0, fp); // dummy
+ file.PutChar (pal[2][i]);
+ file.PutChar (pal[1][i]);
+ file.PutChar (pal[0][i]);
+ file.PutChar (0); // dummy
}
- for (int row = 0; row < image->height; row++)
+ for (int row = 0; row < m_nHeight; row++)
{
int pixbuf = 0;
- for (int col = 0; col < image->width; col++)
+ for (int col = 0; col < m_nWidth; col++)
{
- int offset = (image->height-row-1) * width + col; // offset into our color-mapped RGB buffer
+ int offset = (m_nHeight-row-1) * width + col; // offset into our color-mapped RGB buffer
unsigned char pval = *(colormappedbuffer + offset);
pixbuf = (pixbuf << 8) | pval;
- putc(pixbuf, fp);
+ file.PutChar (pixbuf);
pixbuf = 0;
byteswritten++;
}
@@ -487,7 +456,7 @@ bool SaveBMP(char* filename, LC_IMAGE* image, bool quantize)
// DWORD align
while ((byteswritten - pixoff) & 3)
{
- putc(0, fp);
+ file.PutChar (0);
byteswritten++;
}
}
@@ -496,29 +465,28 @@ bool SaveBMP(char* filename, LC_IMAGE* image, bool quantize)
}
else
{
- unsigned long widthDW = (((image->width*24) + 31) / 32 * 4);
- long row, row_size = image->width*3;
- for (row = 0; row < image->height; row++)
+ unsigned long widthDW = (((m_nWidth*24) + 31) / 32 * 4);
+ long row, row_size = m_nWidth*3;
+ for (row = 0; row < m_nHeight; row++)
{
- unsigned char* buf = (unsigned char*)image->bits+(image->height-row-1)*row_size;
+ unsigned char* buf = m_pData+(m_nHeight-row-1)*row_size;
// write a row
for (int col = 0; col < row_size; col += 3)
{
- putc(buf[col+2], fp);
- putc(buf[col+1], fp);
- putc(buf[col], fp);
+ file.PutChar (buf[col+2]);
+ file.PutChar (buf[col+1]);
+ file.PutChar (buf[col]);
}
byteswritten += row_size;
for (unsigned long count = row_size; count < widthDW; count++)
{
- putc(0, fp); // dummy
+ file.PutChar (0); // dummy
byteswritten++;
}
}
}
- fclose(fp);
return true;
}
diff --git a/common/im_gif.cpp b/common/im_gif.cpp
index 2f1fbe4..65dc4f3 100644
--- a/common/im_gif.cpp
+++ b/common/im_gif.cpp
@@ -3,9 +3,7 @@
#include "image.h"
#include "quant.h"
#include "file.h"
-extern "C" {
-#include <jpeglib.h>
-}
+#include "config.h"
// =============================================================================
@@ -33,19 +31,19 @@ typedef struct
int firstcode; // first byte of oldcode's expansion
// LZW symbol table and expansion stack
- UINT16 FAR *symbol_head; // => table of prefix symbols
- UINT8 FAR *symbol_tail; // => table of suffix bytes
- UINT8 FAR *symbol_stack; // => stack for symbol expansions
- UINT8 FAR *sp; // stack pointer
+ lcuint16 *symbol_head; // => table of prefix symbols
+ lcuint8 *symbol_tail; // => table of suffix bytes
+ lcuint8 *symbol_stack; // => stack for symbol expansions
+ lcuint8 *sp; // stack pointer
// State for interlaced image processing
bool is_interlaced; // true if have interlaced image
// jvirt_sarray_ptr interlaced_image; // full image in interlaced order
unsigned char* interlaced_image;
- JDIMENSION cur_row_number; // need to know actual row number
- JDIMENSION pass2_offset; // # of pixel rows in pass 1
- JDIMENSION pass3_offset; // # of pixel rows in passes 1&2
- JDIMENSION pass4_offset; // # of pixel rows in passes 1,2,3
+ lcuint32 cur_row_number; // need to know actual row number
+ lcuint32 pass2_offset; // # of pixel rows in pass 1
+ lcuint32 pass3_offset; // # of pixel rows in passes 1&2
+ lcuint32 pass4_offset; // # of pixel rows in passes 1,2,3
File* input_file;
bool first_interlace;
@@ -75,7 +73,7 @@ static int GetDataBlock (gif_source_ptr sinfo, char *buf)
static int GetCode (gif_source_ptr sinfo)
{
- register INT32 accum;
+ register lcint32 accum;
int offs, ret, count;
while ((sinfo->cur_bit + sinfo->code_size) > sinfo->last_bit)
@@ -167,7 +165,7 @@ static int LZWReadByte (gif_source_ptr sinfo)
if (code > sinfo->max_code)
incode = 0; // prevent creation of loops in symbol table
// this symbol will be defined as oldcode/firstcode
- *(sinfo->sp++) = (UINT8) sinfo->firstcode;
+ *(sinfo->sp++) = (lcuint8) sinfo->firstcode;
code = sinfo->oldcode;
}
@@ -181,7 +179,7 @@ static int LZWReadByte (gif_source_ptr sinfo)
if ((code = sinfo->max_code) < LZW_TABLE_SIZE)
{
sinfo->symbol_head[code] = sinfo->oldcode;
- sinfo->symbol_tail[code] = (UINT8) sinfo->firstcode;
+ sinfo->symbol_tail[code] = (lcuint8) sinfo->firstcode;
sinfo->max_code++;
if ((sinfo->max_code >= sinfo->limit_code) &&
(sinfo->code_size < MAX_LZW_BITS))
@@ -195,17 +193,19 @@ static int LZWReadByte (gif_source_ptr sinfo)
return sinfo->firstcode; // return first byte of symbol's expansion
}
-LC_IMAGE* OpenGIF(File* file)
+bool Image::LoadGIF (File& file)
{
gif_source_ptr source;
source = (gif_source_ptr)malloc (sizeof(gif_source_struct));
- source->input_file = file;
+ source->input_file = &file;
char hdrbuf[10];
unsigned int width, height;
int colormaplen, aspectRatio;
int c;
+ FreeData ();
+
source->input_file->Read(hdrbuf, 6);
if ((hdrbuf[0] != 'G' || hdrbuf[1] != 'I' || hdrbuf[2] != 'F') ||
((hdrbuf[3] != '8' || hdrbuf[4] != '7' || hdrbuf[5] != 'a') &&
@@ -242,7 +242,7 @@ LC_IMAGE* OpenGIF(File* file)
extlabel = source->input_file->GetChar();
while (GetDataBlock(source, buf) > 0)
- ; // skip
+ ; // skip
continue;
}
@@ -259,9 +259,9 @@ LC_IMAGE* OpenGIF(File* file)
colormaplen = 2 << (hdrbuf[8] & 0x07);
for (int i = 0; i < colormaplen; i++)
{
- source->colormap[0][i] = source->input_file->GetChar();
- source->colormap[1][i] = source->input_file->GetChar();
- source->colormap[2][i] = source->input_file->GetChar();
+ source->colormap[0][i] = source->input_file->GetChar();
+ source->colormap[1][i] = source->input_file->GetChar();
+ source->colormap[2][i] = source->input_file->GetChar();
}
}
@@ -272,9 +272,9 @@ LC_IMAGE* OpenGIF(File* file)
break;
}
- source->symbol_head = (UINT16 FAR *) malloc(LZW_TABLE_SIZE * sizeof(UINT16));
- source->symbol_tail = (UINT8 FAR *) malloc (LZW_TABLE_SIZE * sizeof(UINT8));
- source->symbol_stack = (UINT8 FAR *) malloc (LZW_TABLE_SIZE * sizeof(UINT8));
+ source->symbol_head = (lcuint16*) malloc(LZW_TABLE_SIZE * sizeof(lcuint16));
+ source->symbol_tail = (lcuint8*) malloc (LZW_TABLE_SIZE * sizeof(lcuint8));
+ source->symbol_stack = (lcuint8*) malloc (LZW_TABLE_SIZE * sizeof(lcuint8));
source->last_byte = 2; // make safe to "recopy last two bytes"
source->last_bit = 0; // nothing in the buffer
source->cur_bit = 0; // force buffer load on first call
@@ -296,11 +296,11 @@ LC_IMAGE* OpenGIF(File* file)
source->first_interlace = false;
source->buffer = (unsigned char*)malloc(width*3);
- LC_IMAGE* image = (LC_IMAGE*)malloc(width*height*3 + sizeof(LC_IMAGE));
- image->width = width;
- image->height = height;
- image->bits = (char*)image + sizeof(LC_IMAGE);
- unsigned char* buf = (unsigned char*)image->bits;
+ m_pData = (unsigned char*)malloc(width*height*3);
+ m_nWidth = width;
+ m_nHeight = height;
+ m_bAlpha = false; // FIXME: create the alpha channel for transparent files
+ unsigned char* buf = m_pData;
for (unsigned long scanline = 0; scanline < height; scanline++)
{
@@ -308,70 +308,70 @@ LC_IMAGE* OpenGIF(File* file)
{
if (source->first_interlace)
{
- register JSAMPROW sptr;
- register JDIMENSION col;
- JDIMENSION row;
-
- for (row = 0; row < source->height; row++)
- {
- sptr = &source->interlaced_image[row*source->width];
- for (col = source->width; col > 0; col--)
- *sptr++ = (JSAMPLE) LZWReadByte(source);
- }
-
- source->first_interlace = false;
- source->cur_row_number = 0;
- source->pass2_offset = (source->height + 7) / 8;
- source->pass3_offset = source->pass2_offset + (source->height + 3) / 8;
- source->pass4_offset = source->pass3_offset + (source->height + 1) / 4;
+ register lcuint8 *sptr;
+ register lcuint32 col;
+ lcuint32 row;
+
+ for (row = 0; row < source->height; row++)
+ {
+ sptr = &source->interlaced_image[row*source->width];
+ for (col = source->width; col > 0; col--)
+ *sptr++ = (lcuint8) LZWReadByte(source);
+ }
+
+ source->first_interlace = false;
+ source->cur_row_number = 0;
+ source->pass2_offset = (source->height + 7) / 8;
+ source->pass3_offset = source->pass2_offset + (source->height + 3) / 8;
+ source->pass4_offset = source->pass3_offset + (source->height + 1) / 4;
}
register int c;
- register JSAMPROW sptr, ptr;
- register JDIMENSION col;
- JDIMENSION irow;
+ register lcuint8 *sptr, *ptr;
+ register lcuint32 col;
+ lcuint32 irow;
// Figure out which row of interlaced image is needed, and access it.
switch ((int) (source->cur_row_number & 7))
{
case 0: // first-pass row
- irow = source->cur_row_number >> 3;
- break;
+ irow = source->cur_row_number >> 3;
+ break;
case 4: // second-pass row
- irow = (source->cur_row_number >> 3) + source->pass2_offset;
- break;
+ irow = (source->cur_row_number >> 3) + source->pass2_offset;
+ break;
case 2: // third-pass row
case 6:
- irow = (source->cur_row_number >> 2) + source->pass3_offset;
- break;
+ irow = (source->cur_row_number >> 2) + source->pass3_offset;
+ break;
default: // fourth-pass row
- irow = (source->cur_row_number >> 1) + source->pass4_offset;
- break;
+ irow = (source->cur_row_number >> 1) + source->pass4_offset;
+ break;
}
sptr = &source->interlaced_image[irow*source->width];
ptr = source->buffer;
for (col = source->width; col > 0; col--)
{
- c = GETJSAMPLE(*sptr++);
- *ptr++ = source->colormap[0][c];
- *ptr++ = source->colormap[1][c];
- *ptr++ = source->colormap[2][c];
+ c = *sptr++;
+ *ptr++ = source->colormap[0][c];
+ *ptr++ = source->colormap[1][c];
+ *ptr++ = source->colormap[2][c];
}
source->cur_row_number++; // for next time
}
else
{
register int c;
- register JSAMPROW ptr;
- register JDIMENSION col;
+ register lcuint8 *ptr;
+ register lcuint32 col;
ptr = source->buffer;
for (col = source->width; col > 0; col--)
{
- c = LZWReadByte(source);
- *ptr++ = source->colormap[0][c];
- *ptr++ = source->colormap[1][c];
- *ptr++ = source->colormap[2][c];
+ c = LZWReadByte(source);
+ *ptr++ = source->colormap[0][c];
+ *ptr++ = source->colormap[1][c];
+ *ptr++ = source->colormap[2][c];
}
}
@@ -386,19 +386,19 @@ LC_IMAGE* OpenGIF(File* file)
free(source->symbol_stack);
free(source);
- return image;
+ return true;
}
// =============================================================================
#undef LZW_TABLE_SIZE
#define MAX_LZW_BITS 12
-typedef INT16 code_int;
+typedef lcint16 code_int;
#define LZW_TABLE_SIZE ((code_int) 1 << MAX_LZW_BITS)
#define HSIZE 5003
typedef int hash_int;
#define MAXCODE(n_bits) (((code_int) 1 << (n_bits)) - 1)
-typedef INT32 hash_entry;
+typedef lcint32 hash_entry;
#define HASH_ENTRY(prefix,suffix) ((((hash_entry) (prefix)) << 8) | (suffix))
typedef struct
@@ -406,7 +406,7 @@ typedef struct
int n_bits;
code_int maxcode;
int init_bits;
- INT32 cur_accum;
+ lcint32 cur_accum;
int cur_bits;
code_int waiting_code;
bool first_byte;
@@ -414,7 +414,7 @@ typedef struct
code_int EOFCode;
code_int free_code;
code_int *hash_code;
- hash_entry FAR *hash_value;
+ hash_entry *hash_value;
int bytesinpkt;
char packetbuf[256];
File* output_file;
@@ -424,10 +424,10 @@ typedef struct
typedef gif_dest_struct* gif_dest_ptr;
// Emit a 16-bit word, LSB first
-static void put_word(File* output_file, unsigned int w)
+static void put_word(File& output_file, unsigned int w)
{
- output_file->PutChar(w & 0xFF);
- output_file->PutChar((w >> 8) & 0xFF);
+ output_file.PutChar(w & 0xFF);
+ output_file.PutChar((w >> 8) & 0xFF);
}
static void flush_packet(gif_dest_ptr dinfo)
@@ -442,7 +442,7 @@ static void flush_packet(gif_dest_ptr dinfo)
static void output(gif_dest_ptr dinfo, code_int code)
{
- dinfo->cur_accum |= ((INT32) code) << dinfo->cur_bits;
+ dinfo->cur_accum |= ((lcint32) code) << dinfo->cur_bits;
dinfo->cur_bits += dinfo->n_bits;
while (dinfo->cur_bits >= 8)
@@ -475,7 +475,7 @@ static void compress_byte (gif_dest_ptr dinfo, int c)
if (dinfo->first_byte)
{
dinfo->waiting_code = c;
- dinfo->first_byte = FALSE;
+ dinfo->first_byte = false;
return;
}
@@ -528,43 +528,43 @@ static void compress_byte (gif_dest_ptr dinfo, int c)
dinfo->waiting_code = c;
}
-bool SaveGIF(File* file, LC_IMAGE* image, bool transparent, bool interlaced, unsigned char* background)
+bool Image::SaveGIF (File& file, bool transparent, bool interlaced, unsigned char* background) const
{
int InitCodeSize, FlagByte, i;
unsigned char pal[3][256];
- unsigned char* colormappedbuffer = (unsigned char*)malloc(image->width*image->height);
- dl1quant((unsigned char*)image->bits, colormappedbuffer, image->width, image->height, 256, true, pal);
+ unsigned char* colormappedbuffer = (unsigned char*)malloc (m_nWidth*m_nHeight);
+ dl1quant (m_pData, colormappedbuffer, m_nWidth, m_nHeight, 256, true, pal);
gif_dest_ptr dinfo;
dinfo = (gif_dest_ptr) malloc (sizeof(gif_dest_struct));
- dinfo->output_file = file;
- dinfo->buffer = malloc(image->width*sizeof(JDIMENSION));
+ dinfo->output_file = &file;
+ dinfo->buffer = malloc(m_nWidth*sizeof(lcuint32));
dinfo->hash_code = (code_int*) malloc(HSIZE * sizeof(code_int));
- dinfo->hash_value = (hash_entry FAR*)malloc(HSIZE*sizeof(hash_entry));
+ dinfo->hash_value = (hash_entry*)malloc(HSIZE*sizeof(hash_entry));
InitCodeSize = 8;
// Write the GIF header.
- file->PutChar('G');
- file->PutChar('I');
- file->PutChar('F');
- file->PutChar('8');
- file->PutChar(transparent ? '9' : '7');
- file->PutChar('a');
+ file.PutChar('G');
+ file.PutChar('I');
+ file.PutChar('F');
+ file.PutChar('8');
+ file.PutChar(transparent ? '9' : '7');
+ file.PutChar('a');
// Write the Logical Screen Descriptor
- put_word(file, (unsigned int)image->width);
- put_word(file, (unsigned int)image->height);
+ put_word(file, (unsigned int)m_nWidth);
+ put_word(file, (unsigned int)m_nHeight);
FlagByte = 0x80;
FlagByte |= (7) << 4; // color resolution
FlagByte |= (7); // size of global color table
- file->PutChar(FlagByte);
- file->PutChar(0); // Background color index
- file->PutChar(0); // Reserved (aspect ratio in GIF89)
+ file.PutChar(FlagByte);
+ file.PutChar(0); // Background color index
+ file.PutChar(0); // Reserved (aspect ratio in GIF89)
// Write the Global Color Map
for (i = 0; i < 256; i++)
{
- file->PutChar(pal[0][i]);
- file->PutChar(pal[1][i]);
- file->PutChar(pal[2][i]);
+ file.PutChar(pal[0][i]);
+ file.PutChar(pal[1][i]);
+ file.PutChar(pal[2][i]);
}
// Write out extension for transparent colour index, if necessary.
@@ -581,28 +581,28 @@ bool SaveGIF(File* file, LC_IMAGE* image, bool transparent, bool interlaced, uns
break;
}
- file->PutChar('!');
- file->PutChar(0xf9);
- file->PutChar(4);
- file->PutChar(1);
- file->PutChar(0);
- file->PutChar(0);
- file->PutChar(index);
- file->PutChar(0);
+ file.PutChar('!');
+ file.PutChar(0xf9);
+ file.PutChar(4);
+ file.PutChar(1);
+ file.PutChar(0);
+ file.PutChar(0);
+ file.PutChar(index);
+ file.PutChar(0);
}
// Write image separator and Image Descriptor
- file->PutChar(',');
+ file.PutChar(',');
put_word(file, 0);
put_word(file, 0);
- put_word(file, (unsigned int)image->width);
- put_word(file, (unsigned int)image->height);
+ put_word(file, (unsigned int)m_nWidth);
+ put_word(file, (unsigned int)m_nHeight);
// flag byte: interlaced
if (interlaced)
- file->PutChar(0x40);
+ file.PutChar(0x40);
else
- file->PutChar(0x00);
- file->PutChar(InitCodeSize);// Write Initial Code Size byte
+ file.PutChar(0x00);
+ file.PutChar(InitCodeSize);// Write Initial Code Size byte
// Initialize for LZW compression of image data
dinfo->n_bits = dinfo->init_bits = InitCodeSize+1;
@@ -610,7 +610,7 @@ bool SaveGIF(File* file, LC_IMAGE* image, bool transparent, bool interlaced, uns
dinfo->ClearCode = ((code_int) 1 << (InitCodeSize));
dinfo->EOFCode = dinfo->ClearCode + 1;
dinfo->free_code = dinfo->ClearCode + 2;
- dinfo->first_byte = TRUE;
+ dinfo->first_byte = true;
dinfo->bytesinpkt = 0;
dinfo->cur_accum = 0;
dinfo->cur_bits = 0;
@@ -619,16 +619,16 @@ bool SaveGIF(File* file, LC_IMAGE* image, bool transparent, bool interlaced, uns
int scanline = 0;
int pass = 0;
- while (scanline < image->height)
+ while (scanline < m_nHeight)
{
- memcpy(dinfo->buffer, colormappedbuffer+(scanline*image->width), image->width);
+ memcpy(dinfo->buffer, colormappedbuffer+(scanline*m_nWidth), m_nWidth);
- register JSAMPROW ptr;
- register JDIMENSION col;
+ register lcuint8 *ptr;
+ register lcuint32 col;
ptr = (unsigned char*)dinfo->buffer;
- for (col = image->width; col > 0; col--)
- compress_byte(dinfo, GETJSAMPLE(*ptr++));
+ for (col = m_nWidth; col > 0; col--)
+ compress_byte(dinfo, *ptr++);
if (interlaced)
{
@@ -637,7 +637,7 @@ bool SaveGIF(File* file, LC_IMAGE* image, bool transparent, bool interlaced, uns
case 0:
{
scanline += 8;
- if (scanline >= image->height)
+ if (scanline >= m_nHeight)
{
pass++;
scanline = 4;
@@ -647,7 +647,7 @@ bool SaveGIF(File* file, LC_IMAGE* image, bool transparent, bool interlaced, uns
case 1:
{
scanline += 8;
- if (scanline >= image->height)
+ if (scanline >= m_nHeight)
{
pass++;
scanline = 2;
@@ -657,7 +657,7 @@ bool SaveGIF(File* file, LC_IMAGE* image, bool transparent, bool interlaced, uns
case 2:
{
scanline += 4;
- if (scanline >= image->height)
+ if (scanline >= m_nHeight)
{
pass++;
scanline = 1;
@@ -686,9 +686,9 @@ bool SaveGIF(File* file, LC_IMAGE* image, bool transparent, bool interlaced, uns
}
flush_packet(dinfo);
- file->PutChar(0);
- file->PutChar(';');
- file->Flush();
+ file.PutChar(0);
+ file.PutChar(';');
+ file.Flush();
free(dinfo->buffer);
free(dinfo->hash_code);
diff --git a/common/im_jpg.cpp b/common/im_jpg.cpp
index 2f9936c..9da64b6 100644
--- a/common/im_jpg.cpp
+++ b/common/im_jpg.cpp
@@ -1,8 +1,8 @@
#include <setjmp.h>
-#include <stdio.h>
#include <stdlib.h>
#include "config.h"
#include "image.h"
+#include "file.h"
#ifdef LC_HAVE_JPEGLIB
@@ -73,17 +73,136 @@ static void j_putGrayScanlineToRGB(unsigned char* jpegline, int widthPix, unsign
}
// =============================================================================
+// JPEG data source
-LC_IMAGE* OpenJPG (char* filename)
+// Expanded data source object for input using the File class
+typedef struct
+{
+ struct jpeg_source_mgr pub; // public fields
+
+ File * infile; // source stream
+ JOCTET * buffer; // start of buffer
+ boolean start_of_file; // have we gotten any data yet?
+} my_source_mgr;
+
+typedef my_source_mgr * my_src_ptr;
+
+#define INPUT_BUF_SIZE 4096 // choose an efficiently fread'able size
+
+// Initialize source --- called by jpeg_read_header
+// before any data is actually read.
+static void init_source (j_decompress_ptr cinfo)
+{
+ my_src_ptr src = (my_src_ptr) cinfo->src;
+
+ // We reset the empty-input-file flag for each image,
+ // but we don't clear the input buffer.
+ // This is correct behavior for reading a series of images from one source.
+ src->start_of_file = TRUE;
+}
+
+// Fill the input buffer --- called whenever buffer is emptied.
+static boolean fill_input_buffer (j_decompress_ptr cinfo)
+{
+ my_src_ptr src = (my_src_ptr) cinfo->src;
+ size_t nbytes;
+
+ nbytes = src->infile->Read (src->buffer, INPUT_BUF_SIZE);
+
+ if (nbytes <= 0)
+ {
+// if (src->start_of_file) // Treat empty input file as fatal error
+// ERREXIT(cinfo, JERR_INPUT_EMPTY);
+// WARNMS(cinfo, JWRN_JPEG_EOF);
+
+ // Insert a fake EOI marker
+ src->buffer[0] = (JOCTET) 0xFF;
+ src->buffer[1] = (JOCTET) JPEG_EOI;
+ nbytes = 2;
+ }
+
+ src->pub.next_input_byte = src->buffer;
+ src->pub.bytes_in_buffer = nbytes;
+ src->start_of_file = FALSE;
+
+ return TRUE;
+}
+
+// Skip data --- used to skip over a potentially large amount of
+// uninteresting data (such as an APPn marker).
+
+static void skip_input_data (j_decompress_ptr cinfo, long num_bytes)
+{
+ my_src_ptr src = (my_src_ptr) cinfo->src;
+
+ // Just a dumb implementation for now. Could use Seek() except
+ // it doesn't work on pipes. Not clear that being smart is worth
+ // any trouble anyway --- large skips are infrequent.
+ if (num_bytes > 0)
+ {
+ while (num_bytes > (long) src->pub.bytes_in_buffer)
+ {
+ num_bytes -= (long) src->pub.bytes_in_buffer;
+ (void) fill_input_buffer(cinfo);
+ // note we assume that fill_input_buffer will never return FALSE,
+ // so suspension need not be handled.
+ }
+ src->pub.next_input_byte += (size_t) num_bytes;
+ src->pub.bytes_in_buffer -= (size_t) num_bytes;
+ }
+}
+
+// Terminate source --- called by jpeg_finish_decompress
+// after all data has been read. Often a no-op.
+static void term_source (j_decompress_ptr cinfo)
+{
+ // no work necessary here
+}
+
+// Prepare for input from a File object.
+static void jpeg_file_src (j_decompress_ptr cinfo, File& infile)
+{
+ my_src_ptr src;
+
+ // The source object and input buffer are made permanent so that a series
+ // of JPEG images can be read from the same file by calling jpeg_stdio_src
+ // only before the first one. (If we discarded the buffer at the end of
+ // one image, we'd likely lose the start of the next one.)
+ // This makes it unsafe to use this manager and a different source
+ // manager serially with the same JPEG object. Caveat programmer.
+ if (cinfo->src == NULL)
+ {
+ // first time for this JPEG object?
+ cinfo->src = (struct jpeg_source_mgr *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ sizeof (my_source_mgr));
+ src = (my_src_ptr) cinfo->src;
+ src->buffer = (JOCTET *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ INPUT_BUF_SIZE * sizeof(JOCTET));
+ }
+
+ src = (my_src_ptr) cinfo->src;
+ src->pub.init_source = init_source;
+ src->pub.fill_input_buffer = fill_input_buffer;
+ src->pub.skip_input_data = skip_input_data;
+ src->pub.resync_to_restart = jpeg_resync_to_restart; // use default method
+ src->pub.term_source = term_source;
+ src->infile = &infile;
+ src->pub.bytes_in_buffer = 0; // forces fill_input_buffer on first read
+ src->pub.next_input_byte = NULL; // until buffer loaded
+}
+
+// =============================================================================
+
+bool Image::LoadJPG (File& file)
{
struct jpeg_decompress_struct cinfo;
struct bt_jpeg_error_mgr jerr;
- FILE* infile = NULL;
JSAMPARRAY buffer; // Output row buffer
int row_stride; // physical row width in output buffer
- if ((infile = fopen(filename, "rb")) == NULL)
- return NULL;
+ FreeData ();
cinfo.err = jpeg_std_error(&jerr.pub);
jerr.pub.error_exit = bt_jpeg_error_exit;
@@ -91,31 +210,27 @@ LC_IMAGE* OpenJPG (char* filename)
if (setjmp(jerr.setjmp_buffer))
{
jpeg_destroy_decompress(&cinfo);
-
- if (infile != NULL)
- fclose(infile);
- return NULL;
+ return false;
}
jpeg_create_decompress(&cinfo);
- jpeg_stdio_src(&cinfo, infile);
+ jpeg_file_src(&cinfo, file);
jpeg_read_header(&cinfo, TRUE);
jpeg_start_decompress(&cinfo);
// get our buffer set to hold data
- LC_IMAGE* image = (LC_IMAGE*)malloc(cinfo.output_width*cinfo.output_height*3 + sizeof(LC_IMAGE));
+ m_pData = (unsigned char*)malloc(cinfo.output_width*cinfo.output_height*3);
- if (image == NULL)
+ if (m_pData == NULL)
{
// MessageBox(NULL, "Error", "Cannot allocate memory", MB_ICONSTOP);
jpeg_destroy_decompress(&cinfo);
- fclose(infile);
- return NULL;
+ return false;
}
- image->width = cinfo.output_width;
- image->height = cinfo.output_height;
- image->bits = (char*)image + sizeof(LC_IMAGE);
+ m_nWidth = cinfo.output_width;
+ m_nHeight = cinfo.output_height;
+ m_bAlpha = false;
row_stride = cinfo.output_width * cinfo.output_components;
buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
@@ -125,26 +240,121 @@ LC_IMAGE* OpenJPG (char* filename)
jpeg_read_scanlines(&cinfo, buffer, 1);
if (cinfo.out_color_components == 3)
- j_putRGBScanline(buffer[0], image->width, (unsigned char*)image->bits, cinfo.output_scanline-1);
+ j_putRGBScanline(buffer[0], m_nWidth, m_pData, cinfo.output_scanline-1);
else if (cinfo.out_color_components == 1)
- j_putGrayScanlineToRGB(buffer[0], image->width, (unsigned char*)image->bits, cinfo.output_scanline-1);
+ j_putGrayScanlineToRGB(buffer[0], m_nWidth, m_pData, cinfo.output_scanline-1);
}
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
- fclose(infile);
- return image;
+ return true;
+}
+
+// =============================================================================
+// JPEG data destination
+
+// Expanded data destination object for output using the File class
+typedef struct
+{
+ struct jpeg_destination_mgr pub; // public fields
+
+ File * outfile; // target stream
+ JOCTET * buffer; // start of buffer
+} my_destination_mgr;
+
+typedef my_destination_mgr * my_dest_ptr;
+
+#define OUTPUT_BUF_SIZE 4096 // choose an efficiently fwrite'able size
+
+// Initialize destination --- called by jpeg_start_compress
+// before any data is actually written.
+static void init_destination (j_compress_ptr cinfo)
+{
+ my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
+
+ /* Allocate the output buffer --- it will be released when done with image */
+ dest->buffer = (JOCTET *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ OUTPUT_BUF_SIZE * sizeof(JOCTET));
+
+ dest->pub.next_output_byte = dest->buffer;
+ dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
+}
+
+// Empty the output buffer --- called whenever buffer fills up.
+//
+// In typical applications, this should write the entire output buffer
+// (ignoring the current state of next_output_byte & free_in_buffer),
+// reset the pointer & count to the start of the buffer, and return TRUE
+// indicating that the buffer has been dumped.
+static boolean empty_output_buffer (j_compress_ptr cinfo)
+{
+ my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
+
+ dest->outfile->Write (dest->buffer, OUTPUT_BUF_SIZE);
+// if (dest->outfile.Write (dest->buffer, OUTPUT_BUF_SIZE) != (size_t) OUTPUT_BUF_SIZE)
+// ERREXIT(cinfo, JERR_FILE_WRITE);
+
+ dest->pub.next_output_byte = dest->buffer;
+ dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
+
+ return TRUE;
+}
+
+// Terminate destination --- called by jpeg_finish_compress
+// after all data has been written. Usually needs to flush buffer.
+static void term_destination (j_compress_ptr cinfo)
+{
+ my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
+ size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;
+
+ // Write any data remaining in the buffer
+ if (datacount > 0)
+ {
+ dest->outfile->Write (dest->buffer, datacount);
+// if (dest->outfile.Write (dest->buffer, datacount) != datacount)
+// ERREXIT(cinfo, JERR_FILE_WRITE);
+ }
+ dest->outfile->Flush ();
+
+ // Make sure we wrote the output file OK
+// if (ferror(dest->outfile))
+// ERREXIT(cinfo, JERR_FILE_WRITE);
+}
+
+// Prepare for output to a File object.
+static void jpeg_file_dest (j_compress_ptr cinfo, File& outfile)
+{
+ my_dest_ptr dest;
+
+ // The destination object is made permanent so that multiple JPEG images
+ // can be written to the same file without re-executing jpeg_stdio_dest.
+ // This makes it dangerous to use this manager and a different destination
+ // manager serially with the same JPEG object, because their private object
+ // sizes may be different. Caveat programmer.
+ if (cinfo->dest == NULL)
+ {
+ // first time for this JPEG object?
+ cinfo->dest = (struct jpeg_destination_mgr *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ sizeof (my_destination_mgr));
+ }
+
+ dest = (my_dest_ptr) cinfo->dest;
+ dest->pub.init_destination = init_destination;
+ dest->pub.empty_output_buffer = empty_output_buffer;
+ dest->pub.term_destination = term_destination;
+ dest->outfile = &outfile;
}
// =============================================================================
-bool SaveJPG (char* filename, LC_IMAGE* image, int quality, bool progressive)
+bool Image::SaveJPG (File& file, int quality, bool progressive) const
{
struct jpeg_compress_struct cinfo;
struct bt_jpeg_error_mgr jerr;
int row_stride; // physical row widthPix in image buffer
- FILE* outfile;
// allocate and initialize JPEG compression object
cinfo.err = jpeg_std_error(&jerr.pub);
@@ -159,33 +369,30 @@ bool SaveJPG (char* filename, LC_IMAGE* image, int quality, bool progressive)
}
jpeg_create_compress(&cinfo);
- if ((outfile = fopen(filename, "wb")) == NULL)
- return false;
- jpeg_stdio_dest(&cinfo, outfile);
+ jpeg_file_dest(&cinfo, file);
- cinfo.image_width = image->width;
- cinfo.image_height = image->height;
+ cinfo.image_width = m_nWidth;
+ cinfo.image_height = m_nHeight;
cinfo.input_components = 3;
cinfo.in_color_space = JCS_RGB;
- jpeg_set_defaults(&cinfo);
- jpeg_set_quality(&cinfo, quality, TRUE);
+ jpeg_set_defaults (&cinfo);
+ jpeg_set_quality (&cinfo, quality, TRUE);
if (progressive)
jpeg_simple_progression(&cinfo);
- jpeg_start_compress(&cinfo, TRUE);
- row_stride = image->width * 3;
+ jpeg_start_compress (&cinfo, TRUE);
+ row_stride = m_nWidth * 3;
while (cinfo.next_scanline < cinfo.image_height)
{
- unsigned char* outRow = (unsigned char*)image->bits + (cinfo.next_scanline * image->width * 3);
+ unsigned char* outRow = m_pData + (cinfo.next_scanline * m_nWidth * 3);
jpeg_write_scanlines(&cinfo, &outRow, 1);
}
jpeg_finish_compress(&cinfo);
- fclose(outfile);
jpeg_destroy_compress(&cinfo);
return true;
diff --git a/common/im_png.cpp b/common/im_png.cpp
index f86e230..b4c9369 100755
--- a/common/im_png.cpp
+++ b/common/im_png.cpp
@@ -1,11 +1,12 @@
-#include <stdio.h>
#include <stdlib.h>
-#include <png.h>
#include "config.h"
-#include "typedefs.h"
+#include "image.h"
+#include "file.h"
#ifdef LC_HAVE_PNGLIB
+#include <png.h>
+
#define alpha_composite(composite, fg, alpha, bg) { \
unsigned short temp = ((unsigned short)(fg)*(unsigned short)(alpha) + \
(unsigned short)(bg)*(unsigned short)(255 - (unsigned short)(alpha)) + (unsigned short)128); \
@@ -14,7 +15,19 @@
// =============================================================================
-LC_IMAGE* OpenPNG(char* filename)
+static void user_read_fn (png_structp png_ptr, png_bytep data, png_size_t length)
+{
+ png_size_t check;
+
+ // Read() returns 0 on error, so it is OK to store this in a png_size_t
+ // instead of an int, which is what Read() actually returns.
+ check = (png_size_t)((File*)png_ptr->io_ptr)->Read (data, length);
+
+ if (check != length)
+ png_error(png_ptr, "Read Error");
+}
+
+bool Image::LoadPNG (File& file)
{
unsigned char sig[8], red, green, blue;
unsigned char *image_data = NULL;
@@ -30,42 +43,32 @@ LC_IMAGE* OpenPNG(char* filename)
int bit_depth, color_type;
int image_channels;
double gamma;
- FILE* f;
- f = fopen(filename, "rb");
- if (f == NULL)
- return NULL;
+ FreeData ();
- fread(sig, 1, 8, f);
+ file.Read (sig, 8);
if (!png_check_sig(sig, 8))
- {
- fclose(f);
- return NULL; // bad signature
- }
+ return false; // bad signature
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr)
- {
- fclose(f);
- return NULL; // out of memory
- }
-
+ return false; // out of memory
+
info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr)
{
png_destroy_read_struct(&png_ptr, NULL, NULL);
- fclose(f);
- return NULL; // out of memory
+ return false; // out of memory
}
if (setjmp(png_ptr->jmpbuf))
{
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
- fclose(f);
- return NULL;
+ return false;
}
- png_init_io(png_ptr, f);
+ png_set_read_fn(png_ptr, (void *)&file, user_read_fn);
+// png_init_io(png_ptr, f);
png_set_sig_bytes(png_ptr, 8); // we already read the 8 signature bytes
png_read_info(png_ptr, info_ptr); // read all PNG info up to image data
@@ -75,8 +78,7 @@ LC_IMAGE* OpenPNG(char* filename)
if (setjmp(png_ptr->jmpbuf))
{
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
- fclose(f);
- return NULL;
+ return false;
}
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_bKGD))
@@ -86,8 +88,7 @@ LC_IMAGE* OpenPNG(char* filename)
if (setjmp (png_ptr->jmpbuf))
{
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
- fclose(f);
- return NULL;
+ return false;
}
// however, it always returns the raw bKGD data, regardless of any
@@ -101,11 +102,11 @@ LC_IMAGE* OpenPNG(char* filename)
else if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
{
if (bit_depth == 1)
- red = green = blue = pBackground->gray? 255 : 0;
+ red = green = blue = pBackground->gray? 255 : 0;
else if (bit_depth == 2)
- red = green = blue = (255/3) * pBackground->gray;
+ red = green = blue = (255/3) * pBackground->gray;
else // bit_depth == 4
- red = green = blue = (255/15) * pBackground->gray;
+ red = green = blue = (255/15) * pBackground->gray;
}
else
{
@@ -119,8 +120,7 @@ LC_IMAGE* OpenPNG(char* filename)
if (setjmp (png_ptr->jmpbuf))
{
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
- fclose(f);
- return NULL;
+ return false;
}
red = green = blue = 0;
@@ -154,16 +154,14 @@ LC_IMAGE* OpenPNG(char* filename)
if ((image_data = (unsigned char*)malloc(image_rowbytes*height)) == NULL)
{
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
- fclose(f);
- return NULL;
+ return false;
}
if ((row_pointers = (png_bytepp)malloc(height*sizeof(png_bytep))) == NULL)
{
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
free(image_data);
- fclose(f);
- return NULL;
+ return false;
}
// set the individual row_pointers to point at the correct offsets
@@ -182,84 +180,103 @@ LC_IMAGE* OpenPNG(char* filename)
// done with PNG file, so clean up to minimize memory usage
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
- fclose(f);
if (!image_data)
- return NULL;
+ return false;
// get our buffer set to hold data
- LC_IMAGE* image = (LC_IMAGE*)malloc(width*height*3 + sizeof(LC_IMAGE));
+ m_pData = (unsigned char*)malloc(width*height*image_channels);
- if (image == NULL)
+ if (m_pData == NULL)
{
- free(image_data);
- return NULL;
+ free (image_data);
+ return false;
}
- image->width = (unsigned short)width;
- image->height = (unsigned short)height;
- image->bits = (char*)image + sizeof(LC_IMAGE);
+ m_nWidth = width;
+ m_nHeight = height;
+ if (image_channels == 3)
+ m_bAlpha = false;
+ else
+ m_bAlpha = true;
for (row = 0; row < height; row++)
{
src = image_data + row*image_rowbytes;
- dest = (unsigned char*)image->bits + row*image_rowbytes;
+ dest = m_pData + row*image_channels*width;
+
if (image_channels == 3)
{
for (i = width; i > 0; i--)
{
- r = *src++;
- g = *src++;
- b = *src++;
- *dest++ = r;
- *dest++ = g;
- *dest++ = b;
+ r = *src++;
+ g = *src++;
+ b = *src++;
+ *dest++ = r;
+ *dest++ = g;
+ *dest++ = b;
}
}
else // if (image_channels == 4)
{
for (i = width; i > 0; i--)
{
- r = *src++;
- g = *src++;
- b = *src++;
- a = *src++;
-
- if (a == 255)
- {
- *dest++ = r;
- *dest++ = g;
- *dest++ = b;
- }
- else if (a == 0)
- {
- *dest++ = red;
- *dest++ = green;
- *dest++ = blue;
- }
- else
- {
- // this macro (copied from png.h) composites the
- // foreground and background values and puts the
- // result into the first argument; there are no
- // side effects with the first argument
- alpha_composite(*dest++, r, a, red);
- alpha_composite(*dest++, g, a, green);
- alpha_composite(*dest++, b, a, blue);
- }
+ r = *src++;
+ g = *src++;
+ b = *src++;
+ a = *src++;
+
+ if (a == 255)
+ {
+ *dest++ = r;
+ *dest++ = g;
+ *dest++ = b;
+ }
+ else if (a == 0)
+ {
+ *dest++ = red;
+ *dest++ = green;
+ *dest++ = blue;
+ }
+ else
+ {
+ // this macro (copied from png.h) composites the
+ // foreground and background values and puts the
+ // result into the first argument; there are no
+ // side effects with the first argument
+ alpha_composite(*dest++, r, a, red);
+ alpha_composite(*dest++, g, a, green);
+ alpha_composite(*dest++, b, a, blue);
+ }
+ *dest++ = a;
}
}
}
free(image_data);
- return image;
+ return true;
}
// =============================================================================
-bool SavePNG(char* filename, LC_IMAGE* image, bool transparent, bool interlaced, unsigned char* background)
+static void user_write_fn (png_structp png_ptr, png_bytep data, png_size_t length)
+{
+ png_uint_32 check;
+
+ check = ((File*)png_ptr->io_ptr)->Write (data, length);
+ if (check != length)
+ {
+ png_error(png_ptr, "Write Error");
+ }
+}
+
+static void user_flush_fn (png_structp png_ptr)
+{
+ ((File*)png_ptr->io_ptr)->Flush ();
+}
+
+bool Image::SavePNG (File& file, bool transparent, bool interlaced, unsigned char* background) const
{
- FILE *fp;
png_structp png_ptr;
png_infop info_ptr;
png_bytepp row_pointers = NULL;
@@ -267,35 +284,27 @@ bool SavePNG(char* filename, LC_IMAGE* image, bool transparent, bool interlaced,
png_color_16 bg;
int i;
- fp = fopen(filename, "wb");
- if (!fp)
- return false;
-
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr)
- {
- fclose(fp);
return false;
- }
info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr)
{
png_destroy_write_struct(&png_ptr, NULL);
- fclose(fp);
return false;
}
if (setjmp(png_ptr->jmpbuf))
{
png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
- fclose(fp);
return false;
}
- png_init_io(png_ptr, fp);
+// png_init_io(png_ptr, fp);
+ png_set_write_fn (png_ptr, &file, user_write_fn, user_flush_fn);
- png_set_IHDR (png_ptr, info_ptr, image->width, image->height, 8,
+ png_set_IHDR (png_ptr, info_ptr, m_nWidth, m_nHeight, 8,
transparent ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB,
interlaced ? PNG_INTERLACE_ADAM7 : PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
@@ -315,10 +324,9 @@ bool SavePNG(char* filename, LC_IMAGE* image, bool transparent, bool interlaced,
png_set_sBIT(png_ptr, info_ptr, &sig_bit);
- if ((row_pointers = (png_bytepp)malloc(image->height*sizeof(png_bytep))) == NULL)
+ if ((row_pointers = (png_bytepp)malloc(m_nHeight*sizeof(png_bytep))) == NULL)
{
png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
- fclose(fp);
return false;
}
@@ -326,33 +334,33 @@ bool SavePNG(char* filename, LC_IMAGE* image, bool transparent, bool interlaced,
if (transparent)
{
unsigned char *buf, *src, *dst, alpha;
- dst = buf = (unsigned char*)malloc(image->width*image->height*4);
- src = (unsigned char*)image->bits;
+ dst = buf = (unsigned char*)malloc (m_nWidth*m_nHeight*4);
+ src = m_pData;
- for (i = 0; i < image->width*image->height; i++)
+ for (i = 0; i < m_nWidth*m_nHeight; i++)
{
if ((src[0] == background[0]) &&
- (src[1] == background[1]) &&
- (src[2] == background[2]))
- alpha = 0;
+ (src[1] == background[1]) &&
+ (src[2] == background[2]))
+ alpha = 0;
else
- alpha = 255;
+ alpha = 255;
*dst++ = *src++;
*dst++ = *src++;
*dst++ = *src++;
*dst++ = alpha;
}
- for (i = 0; i < image->height; i++)
- row_pointers[i] = buf + i*image->width*4;
+ for (i = 0; i < m_nHeight; i++)
+ row_pointers[i] = buf + i*m_nWidth*4;
png_write_image(png_ptr, row_pointers);
free(buf);
}
else
{
- for (i = 0; i < image->height; i++)
- row_pointers[i] = (unsigned char*)image->bits + i*image->width*3;
+ for (i = 0; i < m_nHeight; i++)
+ row_pointers[i] = m_pData + i*m_nWidth*3;
png_write_image(png_ptr, row_pointers);
}
@@ -360,7 +368,6 @@ bool SavePNG(char* filename, LC_IMAGE* image, bool transparent, bool interlaced,
png_write_end(png_ptr, info_ptr);
png_destroy_write_struct(&png_ptr, &info_ptr);
- fclose(fp);
return true;
}
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);
}
diff --git a/common/image.h b/common/image.h
index 32a76de..ae7fb9e 100644
--- a/common/image.h
+++ b/common/image.h
@@ -5,10 +5,49 @@ class File;
#include "typedefs.h"
-LC_IMAGE* OpenImage(char* filename);
-LC_IMAGE* OpenImage(File* file, unsigned char format);
-bool SaveImage(File* file, LC_IMAGE* image, LC_IMAGE_OPTS* opts);
-bool SaveImage(char* filename, LC_IMAGE* image, LC_IMAGE_OPTS* opts);
-void SaveVideo(char* filename, LC_IMAGE** images, int count, float fps);
+class Image
+{
+public:
+ Image ();
+ virtual ~Image ();
+
+ bool FileSave (File& file, LC_IMAGE_OPTS* opts) const;
+ bool FileSave (const char* filename, LC_IMAGE_OPTS* opts) const;
+ bool FileLoad (File& file);
+ bool FileLoad (const char* filename);
+
+ void Resize (int width, int height);
+ void ResizePow2 ();
+ void FromOpenGL (int width, int height);
+
+ int Width () const
+ { return m_nWidth; }
+ int Height () const
+ { return m_nHeight; }
+ int Alpha () const
+ { return m_bAlpha; }
+ unsigned char* GetData () const
+ { return m_pData; }
+
+protected:
+ void FreeData ();
+
+ bool LoadJPG (File& file);
+ bool LoadBMP (File& file);
+ bool LoadPNG (File& file);
+ bool LoadGIF (File& file);
+
+ bool SaveJPG (File& file, int quality, bool progressive) const;
+ bool SaveBMP (File& file, bool quantize) const;
+ bool SavePNG (File& file, bool transparent, bool interlaced, unsigned char* background) const;
+ bool SaveGIF (File& file, bool transparent, bool interlaced, unsigned char* background) const;
+
+ int m_nWidth;
+ int m_nHeight;
+ bool m_bAlpha;
+ unsigned char* m_pData;
+};
+
+void SaveVideo(char* filename, Image *images, int count, float fps);
#endif // _IMAGE_H_ \ No newline at end of file
diff --git a/common/project.cpp b/common/project.cpp
index 692a6cc..525b7a8 100644
--- a/common/project.cpp
+++ b/common/project.cpp
@@ -435,28 +435,26 @@ bool Project::Initialize(int argc, char *argv[], char* binpath, char* libpath)
to = 255;
}
- LC_IMAGE** images;
- images = (LC_IMAGE**)malloc (sizeof (LC_IMAGE*) * (to - from + 1));
+ Image* images = new Image[to - from + 1];
CreateImages (images, width, height, from, to, highlight);
for (i = 0; i <= to - from; i++)
{
- char filename[LC_MAXPATH];
+ char filename[LC_MAXPATH];
- if (from != to)
- {
- char* ext = strrchr (picture, '.');
- *ext = 0;
- sprintf (filename, "%s%02d.%s", picture, i+1, ext+1);
- *ext = '.';
- }
- else
- strcpy (filename, picture);
+ if (from != to)
+ {
+ char* ext = strrchr (picture, '.');
+ *ext = 0;
+ sprintf (filename, "%s%02d.%s", picture, i+1, ext+1);
+ *ext = '.';
+ }
+ else
+ strcpy (filename, picture);
- SaveImage (filename, images[i], &imopts);
- free (images[i]);
+ images[i].FileSave (filename, &imopts);
}
- free (images);
+ delete []images;
return false;
}
@@ -1343,16 +1341,16 @@ void Project::FileSave(File* file, bool bUndo)
{
pos = file->GetPosition();
- LC_IMAGE* image;
+ Image* image = new Image[1];
LC_IMAGE_OPTS opts;
opts.interlaced = false;
opts.transparent = false;
opts.format = LC_IMAGE_GIF;
i = m_bAnimation ? m_nCurFrame : m_nCurStep;
- CreateImages(&image, 120, 100, i, i, false);
- SaveImage(file, image, &opts);
- free(image);
+ CreateImages(image, 120, 100, i, i, false);
+ image[0].FileSave (*file, &opts);
+ delete []image;
}
file->WriteLong (&pos, 1);
@@ -2986,7 +2984,7 @@ unsigned char Project::GetLastStep()
}
// Create a series of pictures
-void Project::CreateImages(LC_IMAGE** images, int width, int height, unsigned short from, unsigned short to, bool hilite)
+void Project::CreateImages (Image* images, int width, int height, unsigned short from, unsigned short to, bool hilite)
{
int oldx, oldy;
unsigned short oldtime;
@@ -3026,19 +3024,7 @@ void Project::CreateImages(LC_IMAGE** images, int width, int height, unsigned sh
CalculateStep();
Render(true);
-
- LC_IMAGE* image = (LC_IMAGE*)malloc(width*height*3+sizeof(LC_IMAGE));
- image->width = width;
- image->height = height;
- image->bits = (unsigned char*)image + sizeof(LC_IMAGE);
-
- glPixelStorei (GL_PACK_ALIGNMENT, 1);
- glReadPixels (0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, buf);
-
- for (int row = 0; row < height; row++)
- memcpy ((unsigned char*)image->bits + (row*width*3), buf + ((height-row-1)*width*3), width*3);
-
- images[i-from] = image;
+ images[i-from].FromOpenGL (width, height);
}
// pDoc->m_ViewCameras[pDoc->m_nActiveViewport] = pOld;
m_nViewX = oldx;
@@ -3345,9 +3331,8 @@ void Project::HandleCommand(LC_COMMANDS id, unsigned long nParam)
else
opts.from = opts.to = m_bAnimation ? m_nCurFrame : m_nCurStep;
- LC_IMAGE** images;
- images = (LC_IMAGE**)malloc(sizeof(LC_IMAGE*)*(opts.to-opts.from+1));
- CreateImages(images, opts.width, opts.height, opts.from, opts.to, false);
+ Image* images = new Image[opts.to-opts.from+1];
+ CreateImages (images, opts.width, opts.height, opts.from, opts.to, false);
char *ptr, ext[4];
ptr = strrchr(opts.filename, '.');
@@ -3360,10 +3345,7 @@ void Project::HandleCommand(LC_COMMANDS id, unsigned long nParam)
if (strcmp(ext, "avi") == 0)
{
SaveVideo(opts.filename, images, opts.to-opts.from+1, m_bAnimation ? m_nFPS : 60.0f/opts.imopts.pause);
-
- for (int i = 0; i <= opts.to-opts.from; i++)
- free(images[i]);
- }
+ }
else
{
for (int i = 0; i <= opts.to-opts.from; i++)
@@ -3374,16 +3356,15 @@ void Project::HandleCommand(LC_COMMANDS id, unsigned long nParam)
char* ext = strrchr(opts.filename, '.');
*ext = 0;
sprintf(filename, "%s%02d.%s", opts.filename, i+1, ext+1);
- *ext = '.';
+ *ext = '.';
}
else
strcpy(filename, opts.filename);
- SaveImage(filename, images[i], &opts.imopts);
- free(images[i]);
+ images[i].FileSave (filename, &opts.imopts);
}
}
- free(images);
+ delete []images;
}
} break;
@@ -3612,23 +3593,20 @@ void Project::HandleCommand(LC_COMMANDS id, unsigned long nParam)
}
// Save step pictures
- LC_IMAGE** images;
- images = (LC_IMAGE**)malloc(sizeof(LC_IMAGE*)*last);
- CreateImages(images, opts.imdlg.width, opts.imdlg.height, 1, last, opts.highlight);
+ Image* images = new Image[last];
+ CreateImages (images, opts.imdlg.width, opts.imdlg.height, 1, last, opts.highlight);
for (i = 0; i < last; i++)
{
sprintf(fn, "%s%s-%02d%s", opts.path, m_strTitle, i+1, ext);
- SaveImage(fn, images[i], &opts.imdlg.imopts);
- free(images[i]);
+ images[i].FileSave (fn, &opts.imdlg.imopts);
}
- free(images);
+ delete []images;
if (opts.images)
{
int cx = 120, cy = 100;
void* render = Sys_StartMemoryRender (cx, cy);
- unsigned char* buf = (unsigned char*)malloc (cx*cy*3);
float aspect = (float)cx/(float)cy;
glViewport(0, 0, cx, cy);
@@ -3677,22 +3655,13 @@ void Project::HandleCommand(LC_COMMANDS id, unsigned long nParam)
pInfo->RenderPiece(m_nCurColor);
glFinish();
- LC_IMAGE* image = (LC_IMAGE*)malloc(cx*cy*3+sizeof(LC_IMAGE));
- image->width = cx;
- image->height = cy;
- image->bits = (unsigned char*)image + sizeof(LC_IMAGE);
- glPixelStorei (GL_PACK_ALIGNMENT, 1);
- glReadPixels (0, 0, cx, cy, GL_RGB,GL_UNSIGNED_BYTE, buf);
-
- for (int row = 0; row < cy; row++)
- memcpy ((unsigned char*)image->bits + (row*cx*3), buf + ((cy-row-1)*cx*3), cx*3);
+ Image image;
+ image.FromOpenGL (cx, cy);
sprintf(fn, "%s%s%s", opts.path, pInfo->m_strName, ext);
- SaveImage(fn, image, &opts.imdlg.imopts);
- free(image);
+ image.FileSave (fn, &opts.imdlg.imopts);
}
Sys_FinishMemoryRender (render);
- free (buf);
}
main_window->EndWait ();
}
diff --git a/common/project.h b/common/project.h
index 882077c..0097bb1 100644
--- a/common/project.h
+++ b/common/project.h
@@ -22,6 +22,7 @@ class Terrain;
class PieceInfo;
class Matrix;
class View;
+class Image;
// Undo support
@@ -159,7 +160,7 @@ protected:
void RenderViewports(bool bBackground, bool bLines);
void RenderBoxes(bool bHilite);
void RenderInitialize();
- void CreateImages(LC_IMAGE** images, int width, int height, unsigned short from, unsigned short to, bool hilite);
+ void CreateImages(Image* images, int width, int height, unsigned short from, unsigned short to, bool hilite);
void CreateHTMLPieceList(FILE* f, int nStep, bool bImages, char* ext);
inline bool IsDrawing()
diff --git a/common/texture.cpp b/common/texture.cpp
index 4b9997b..a4d34f2 100644
--- a/common/texture.cpp
+++ b/common/texture.cpp
@@ -149,23 +149,22 @@ void Texture::Load(bool bFilter)
free(bits);
}
-bool Texture::LoadFromFile(char* strFilename, bool bFilter)
+bool Texture::LoadFromFile (char* strFilename, bool bFilter)
{
- LC_IMAGE* image = OpenImage(strFilename);
-
- if (image != NULL)
+ Image image;
+
+ if (image.FileLoad (strFilename))
{
- m_nWidth = image->width;
- m_nHeight = image->height;
- m_nFileSize = m_nWidth*m_nHeight*3;
- m_nFormat = GL_RGB;
+ m_nWidth = image.Width ();
+ m_nHeight = image.Height ();
- if (FinishLoadImage (bFilter, image->bits) == true)
- {
- free (image);
+ if (image.Alpha ())
+ m_nFormat = GL_RGBA;
+ else
+ m_nFormat = GL_RGB;
+
+ if (FinishLoadImage (bFilter, image.GetData ()) == true)
return true;
- }
- free(image);
}
if (m_nID != 0)
@@ -173,6 +172,7 @@ bool Texture::LoadFromFile(char* strFilename, bool bFilter)
glDeleteTextures(1, &m_nID);
m_nID = 0;
}
+
m_nWidth = 0;
m_nHeight = 0;
m_nFileSize = 0;
diff --git a/common/typedefs.h b/common/typedefs.h
index c595756..234a4e3 100644
--- a/common/typedefs.h
+++ b/common/typedefs.h
@@ -181,14 +181,6 @@ typedef enum {
LC_IMAGE_AVI
} LC_IMAGE_FORMATS;
-
-typedef struct
-{
- unsigned short width;
- unsigned short height;
- void* bits;
-} LC_IMAGE;
-
typedef struct
{
unsigned char quality;