Initial revision of the C++ helper files.
These files are wrapped in ifdef __cplusplus clauses, so do not affect 'C' use of the library. gd_io_stream contains a specialization of gdIOCtx for standard library streams, and can be used independently of gdpp.h. gdpp.h contains C++ classes which wrap the C API for the convenience of C++ use. All classes in gdpp are prefixed by GD:: Checked in by Kevin Shepherd <kshepherd@php.net> Please see issue 131 in the libgd bug-tracking system for details: http://bugs.libgd.org/?do=details&task_id=131master
parent
b4db533552
commit
5583a4194a
|
@ -0,0 +1,140 @@
|
|||
/* *****************************************************************************
|
||||
** $Id$
|
||||
** Initial file written and documented by:
|
||||
** Kevin Shepherd <kshepherd@php.net> December 2007
|
||||
** of Scarlet Line http://www.scarletline.com/
|
||||
*******************************************************************************/
|
||||
/** \file gd_io_stream.cxx
|
||||
\brief Implementation of the methods of the gdIOCtx std stream specialization.
|
||||
|
||||
Implements the derived specializations of gdIOCtx.
|
||||
These methods are not called by users of libgd, they
|
||||
are internal implementation.
|
||||
Note that half of the below methods are trivial stubs,
|
||||
as an input stream has no need of output methods, and vice-versa.
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
#include "gd_io_stream.h"
|
||||
|
||||
/** Read into buffer from stream
|
||||
Return the number of bytes successfully read.
|
||||
If an error occurs, or the end-of-file is reached, the return value
|
||||
is a short byte count (or zero).
|
||||
*/
|
||||
int istreamIOCtx::Getbuf (struct gdIOCtx * ctx, void * buf, int size)
|
||||
{
|
||||
stream_type * _str = ( (istreamIOCtx * ) ctx )->_M_stream;
|
||||
_str->read((char * )buf, size);
|
||||
return _str->gcount();
|
||||
}
|
||||
/** Write from buffer to stream
|
||||
Return the number of bytes successfully written.
|
||||
If an error occurs, or the end-of-file is reached, the return value
|
||||
is a short byte count (or zero).
|
||||
*/
|
||||
int istreamIOCtx::Putbuf (struct gdIOCtx * , const void * , int )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Reads the next character from stream and returns it as an
|
||||
unsigned char cast to an int, or EOF on end of file or error.
|
||||
*/
|
||||
int istreamIOCtx::Getchar (struct gdIOCtx * ctx)
|
||||
{
|
||||
stream_type * _str = ( (istreamIOCtx * ) ctx )->_M_stream;
|
||||
return _str->get();
|
||||
}
|
||||
/** Write the character to stream
|
||||
Character is cast to unsigned char before writing
|
||||
*/
|
||||
void istreamIOCtx::Putchar (struct gdIOCtx * , int )
|
||||
{
|
||||
}
|
||||
|
||||
/** Seek to position offset from the beginning of the stream
|
||||
must return 1 on SUCCESS, 0 on FAILURE. Unlike fseek!
|
||||
*/
|
||||
int istreamIOCtx::Seek (struct gdIOCtx * ctx, const int pos)
|
||||
{
|
||||
stream_type * _str = ( (istreamIOCtx * ) ctx )->_M_stream;
|
||||
_str->seekg(pos);
|
||||
return !_str->fail();
|
||||
}
|
||||
/** Obtains the current value of the stream position.
|
||||
Returns -1 on error.
|
||||
*/
|
||||
long istreamIOCtx::Tell (struct gdIOCtx * ctx)
|
||||
{
|
||||
stream_type * _str = ( (istreamIOCtx * ) ctx )->_M_stream;
|
||||
return _str->tellg();
|
||||
}
|
||||
/** Deallocate the context
|
||||
*/
|
||||
void istreamIOCtx::FreeCtx (struct gdIOCtx * ctx)
|
||||
{
|
||||
delete (istreamIOCtx * )ctx;
|
||||
}
|
||||
|
||||
/** Read into buffer from stream
|
||||
Return the number of bytes successfully read.
|
||||
If an error occurs, or the end-of-file is reached, the return value
|
||||
is a short byte count (or zero).
|
||||
*/
|
||||
int ostreamIOCtx::Getbuf (struct gdIOCtx * , void * , int )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
/** Write from buffer to stream
|
||||
Return the number of bytes successfully written.
|
||||
If an error occurs, or the end-of-file is reached, the return value
|
||||
is a short byte count (or zero).
|
||||
*/
|
||||
int ostreamIOCtx::Putbuf (struct gdIOCtx * ctx, const void * buf, int size)
|
||||
{
|
||||
stream_type * _str = ( (ostreamIOCtx * ) ctx )->_M_stream;
|
||||
_str->write((const char * )buf, size);
|
||||
return _str->bad()?0:size;
|
||||
}
|
||||
|
||||
/** Reads the next character from stream and returns it as an
|
||||
unsigned char cast to an int, or EOF on end of file or error.
|
||||
*/
|
||||
int ostreamIOCtx::Getchar (struct gdIOCtx * )
|
||||
{
|
||||
return EOF;
|
||||
}
|
||||
/** Write the character to stream
|
||||
Character is cast to unsigned char before writing
|
||||
*/
|
||||
void ostreamIOCtx::Putchar (struct gdIOCtx * ctx, int c)
|
||||
{
|
||||
stream_type * _str = ( (ostreamIOCtx * ) ctx )->_M_stream;
|
||||
_str->put((char)c);
|
||||
}
|
||||
|
||||
/** Seek to position offset from the beginning of the stream
|
||||
must return 1 on SUCCESS, 0 on FAILURE. Unlike fseek!
|
||||
*/
|
||||
int ostreamIOCtx::Seek (struct gdIOCtx * ctx, const int pos)
|
||||
{
|
||||
stream_type * _str = ( (ostreamIOCtx * ) ctx )->_M_stream;
|
||||
_str->seekp(pos);
|
||||
return !_str->fail();
|
||||
}
|
||||
/** Obtains the current value of the stream position.
|
||||
Returns -1 on error.
|
||||
*/
|
||||
long ostreamIOCtx::Tell (struct gdIOCtx * ctx)
|
||||
{
|
||||
stream_type * _str = ( (ostreamIOCtx * ) ctx )->_M_stream;
|
||||
return _str->tellp();
|
||||
}
|
||||
/** Deallocate the context
|
||||
*/
|
||||
void ostreamIOCtx::FreeCtx (struct gdIOCtx * ctx)
|
||||
{
|
||||
delete (ostreamIOCtx * )ctx;
|
||||
}
|
||||
|
||||
#endif /* __cplusplus */
|
|
@ -0,0 +1,126 @@
|
|||
/* *****************************************************************************
|
||||
** $Id$
|
||||
** Initial file written and documented by:
|
||||
** Kevin Shepherd <kshepherd@php.net> December 2007
|
||||
** of Scarlet Line http://www.scarletline.com/
|
||||
*******************************************************************************/
|
||||
/** \file gd_io_stream.h
|
||||
\brief C++ standard library iostream specializations of gdIOCtx.
|
||||
|
||||
Note that all of the methods defined in this header are internal to the
|
||||
libgd library, except for the constructors.
|
||||
Only the constructors are needed by a user of the libgd API.
|
||||
This file does not use or need gdpp.h, but if GD::Image is
|
||||
used, then C++ coding becomes even simpler, and the classes below
|
||||
become entirely hidden implementation details.
|
||||
Example usage, convert png to gif:
|
||||
#include <fstream>
|
||||
#include "gd_io_stream.h"
|
||||
std::ifstream in("image.png", std::ios_base::in | std::ios_base::binary );
|
||||
if (in.good())
|
||||
{
|
||||
istreamIOCtx _in_ctx(in);
|
||||
gdImagePtr im_in = gdImageCreateFromPngCtx ( & _in_ctx);
|
||||
std::ofstream out("image.gif", std::ios_base::out | std::ios_base::binary );
|
||||
ostreamIOCtx _out_ctx(out);
|
||||
gdImageGifCtx(im_in, & _out_ctx);
|
||||
}
|
||||
gdImageDestroy(im_in);
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
#ifndef _gd_io_stream_h
|
||||
#define _gd_io_stream_h
|
||||
|
||||
#include "gd.h"
|
||||
#include <iostream>
|
||||
|
||||
/** Standard library input stream specialization of gdIOCtx
|
||||
*/
|
||||
class BGD_EXPORT_DATA_IMPL istreamIOCtx : public gdIOCtx
|
||||
{
|
||||
public:
|
||||
typedef std::istream stream_type;
|
||||
/** Construct an instance of this input stream specialization,
|
||||
given an input stream.
|
||||
For example:
|
||||
std::ifstream in("image.png", std::ios_base::in | std::ios_base::binary );
|
||||
istreamIOCtx in_ctx(in);
|
||||
*/
|
||||
istreamIOCtx(stream_type & __stream)
|
||||
{ init( & __stream); }
|
||||
|
||||
static int Getbuf (struct gdIOCtx * ctx, void * buf, int size);
|
||||
static int Putbuf (struct gdIOCtx * , const void * , int );
|
||||
static void Putchar (struct gdIOCtx * , int );
|
||||
static int Getchar (struct gdIOCtx * ctx);
|
||||
static int Seek (struct gdIOCtx * ctx, const int pos);
|
||||
static long Tell (struct gdIOCtx * ctx);
|
||||
static void FreeCtx (struct gdIOCtx * ctx);
|
||||
|
||||
void init(stream_type * __stream)
|
||||
{
|
||||
getC = Getchar;
|
||||
putC = Putchar;
|
||||
getBuf = Getbuf;
|
||||
putBuf = Putbuf;
|
||||
tell = Tell;
|
||||
seek = Seek;
|
||||
gd_free = FreeCtx;
|
||||
_M_stream = __stream;
|
||||
}
|
||||
private:
|
||||
stream_type * _M_stream;
|
||||
};
|
||||
/** Allocate a new instance of the class
|
||||
*/
|
||||
inline gdIOCtx * gdNewIstreamCtx (std::istream * __stream)
|
||||
{
|
||||
return new istreamIOCtx(* __stream);
|
||||
}
|
||||
|
||||
/** Standard library output stream specialization of gdIOCtx
|
||||
*/
|
||||
class BGD_EXPORT_DATA_IMPL ostreamIOCtx : public gdIOCtx
|
||||
{
|
||||
public:
|
||||
typedef std::ostream stream_type;
|
||||
/** Construct an instance of this output stream specialization,
|
||||
given an output stream.
|
||||
For example:
|
||||
std::ofstream out("image.gif", std::ios_base::out | std::ios_base::binary );
|
||||
ostreamIOCtx out_ctx(out);
|
||||
*/
|
||||
ostreamIOCtx(stream_type & __stream)
|
||||
{ init( & __stream); }
|
||||
|
||||
static int Getbuf (struct gdIOCtx * , void * , int );
|
||||
static int Putbuf (struct gdIOCtx * ctx, const void * buf, int size);
|
||||
static int Getchar (struct gdIOCtx * );
|
||||
static void Putchar (struct gdIOCtx * ctx, int a);
|
||||
static int Seek (struct gdIOCtx * ctx, const int pos);
|
||||
static long Tell (struct gdIOCtx * ctx);
|
||||
static void FreeCtx (struct gdIOCtx * ctx);
|
||||
|
||||
void init(stream_type * __stream)
|
||||
{
|
||||
getC = Getchar;
|
||||
putC = Putchar;
|
||||
getBuf = Getbuf;
|
||||
putBuf = Putbuf;
|
||||
tell = Tell;
|
||||
seek = Seek;
|
||||
gd_free = FreeCtx;
|
||||
_M_stream = __stream;
|
||||
}
|
||||
private:
|
||||
stream_type * _M_stream;
|
||||
};
|
||||
/** Allocate a new instance of the class
|
||||
*/
|
||||
inline gdIOCtx * gdNewOstreamCtx (std::ostream * __stream)
|
||||
{
|
||||
return new ostreamIOCtx(* __stream);
|
||||
}
|
||||
|
||||
#endif /* _gd_io_stream_h */
|
||||
#endif /* __cplusplus */
|
|
@ -0,0 +1,254 @@
|
|||
/* *****************************************************************************
|
||||
** $Id$
|
||||
** Initial file written and documented by:
|
||||
** Kevin Shepherd <kshepherd@php.net> December 2007
|
||||
** of Scarlet Line http://www.scarletline.com/
|
||||
*******************************************************************************/
|
||||
/** \file gdpp.cxx
|
||||
\brief Implements the non-trivial methods of GD::Image.
|
||||
|
||||
Implementation of the more complex methods defined
|
||||
in gdpp.h.
|
||||
Notably includes the methods which determine the image file
|
||||
format of a file before reading it into memory.
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
#include "gdpp.h"
|
||||
|
||||
namespace GD
|
||||
{
|
||||
/**
|
||||
Load an image from a file, after attempting to
|
||||
determine it's image file format.
|
||||
Invoke CreateFrom with an already opened
|
||||
pointer to a file containing the desired image.
|
||||
CreateFrom does not close the file.
|
||||
\param[in] in An opened FILE * pointer.
|
||||
\return true for success, or false if unable to load the image (most often because the
|
||||
file is corrupt or does not contain a recognized image format).
|
||||
You can call Width() and Height() member functions of the image to determine its size.
|
||||
*/
|
||||
bool Image::CreateFrom(FILE * in)
|
||||
{
|
||||
bool rtn;
|
||||
int c = fgetc(in);
|
||||
ungetc(c, in);
|
||||
switch (c)
|
||||
{
|
||||
/* PNG
|
||||
The first eight bytes of a PNG file always contain the following (decimal) values:
|
||||
0x89 0x50 0x4E 0x47 0x0D 0x0A 0x1A 0x0A
|
||||
== .PNG\r\n.\n
|
||||
*/
|
||||
case 0x89: // PNG
|
||||
rtn = CreateFromPng(in);
|
||||
break;
|
||||
/* GIF
|
||||
0x47 0x49 0x46
|
||||
*/
|
||||
case 0x47: // GIF
|
||||
rtn = CreateFromGif(in);
|
||||
break;
|
||||
/* JPEG
|
||||
A JFIF-standard file will start with the four bytes (hex) FF D8 FF E0,
|
||||
followed by two variable bytes (often hex 00 10), followed by 'JFIF'.
|
||||
*/
|
||||
case 0xFF: // JPEG
|
||||
rtn = CreateFromJpeg(in);
|
||||
break;
|
||||
/* WBMP
|
||||
WBMP Type 0: B/W, Uncompressed bitmap is the only gd supported type
|
||||
*/
|
||||
case 0x00: // WBMP
|
||||
rtn = CreateFromWBMP(in);
|
||||
break;
|
||||
/* GD2
|
||||
0x67 0x64 0x32 0x00
|
||||
== GD2\0
|
||||
Starts with gd2
|
||||
*/
|
||||
case 0x67: // GD2
|
||||
rtn = CreateFromGd2(in);
|
||||
break;
|
||||
/* GD
|
||||
0xFF 0xFE
|
||||
or
|
||||
0xFF 0xFF
|
||||
Conflicts with Jpeg
|
||||
*/
|
||||
/* XBM
|
||||
#define test_width 16
|
||||
#define test_height 7
|
||||
*/
|
||||
case 0x23: // XBM
|
||||
rtn = CreateFromXbm(in);
|
||||
break;
|
||||
default:
|
||||
rtn = false;
|
||||
break;
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
|
||||
/**
|
||||
Load an image from a standard input stream, after attempting to
|
||||
determine it's image file format.
|
||||
Invoke CreateFrom with an already opened stream
|
||||
containing the desired image.
|
||||
CreateFrom does not close the stream.
|
||||
\param[in] in An opened standard library input stream.
|
||||
\return true for success, or false if unable to load the image (most often because the
|
||||
file is corrupt or does not contain a recognized image format).
|
||||
You can call Width() and Height() member functions of the image to determine its size.
|
||||
Example usage, convert anything to gif:
|
||||
#include <fstream>
|
||||
#include <gdpp.h>
|
||||
|
||||
std::ifstream in("image.xxx", std::ios_base::in | std::ios_base::binary );
|
||||
GD::Image im;
|
||||
im.CreateFrom(in);
|
||||
if (im.good())
|
||||
{
|
||||
std::ofstream out("image.gif", std::ios_base::out | std::ios_base::binary );
|
||||
im.Gif(out);
|
||||
}
|
||||
*/
|
||||
bool Image::CreateFrom(std::istream & in)
|
||||
{
|
||||
bool rtn;
|
||||
switch (in.peek())
|
||||
{
|
||||
/* PNG
|
||||
The first eight bytes of a PNG file always contain the following (decimal) values:
|
||||
0x89 0x50 0x4E 0x47 0x0D 0x0A 0x1A 0x0A
|
||||
== .PNG\r\n.\n
|
||||
*/
|
||||
case 0x89: // PNG
|
||||
rtn = CreateFromPng(in);
|
||||
break;
|
||||
/* GIF
|
||||
0x47 0x49 0x46
|
||||
*/
|
||||
case 0x47: // GIF
|
||||
rtn = CreateFromGif(in);
|
||||
break;
|
||||
/* JPEG
|
||||
A JFIF-standard file will start with the four bytes (hex) FF D8 FF E0,
|
||||
followed by two variable bytes (often hex 00 10), followed by 'JFIF'.
|
||||
*/
|
||||
case 0xFF: // JPEG
|
||||
rtn = CreateFromJpeg(in);
|
||||
break;
|
||||
/* WBMP
|
||||
WBMP Type 0: B/W, Uncompressed bitmap is the only gd supported type
|
||||
*/
|
||||
case 0x00: // WBMP
|
||||
rtn = CreateFromWBMP(in);
|
||||
break;
|
||||
/* GD2
|
||||
0x67 0x64 0x32 0x00
|
||||
== GD2\0
|
||||
Starts with gd2
|
||||
*/
|
||||
case 0x67: // GD2
|
||||
rtn = CreateFromGd2(in);
|
||||
break;
|
||||
/* GD
|
||||
0xFF 0xFE
|
||||
or
|
||||
0xFF 0xFF
|
||||
Conflicts with Jpeg
|
||||
*/
|
||||
default:
|
||||
rtn = false;
|
||||
break;
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
|
||||
/**
|
||||
Load an image from an in-RAM memory block, after attempting to
|
||||
determine it's image format.
|
||||
CreateFrom does not de-allocate the memory.
|
||||
\param[in] size The byte count of the memory block.
|
||||
\param[in] data A pointer to the memory block.
|
||||
\return true for success, or false if unable to load the image (most often because the
|
||||
formatting is corrupt or does not contain a recognized image format).
|
||||
You can call Width() and Height() member functions of the image to determine its size.
|
||||
*/
|
||||
bool Image::CreateFrom(int size, void * data)
|
||||
{
|
||||
bool rtn;
|
||||
switch (((unsigned char * )data)[0])
|
||||
{
|
||||
/* PNG
|
||||
The first eight bytes of a PNG file always contain the following (decimal) values:
|
||||
0x89 0x50 0x4E 0x47 0x0D 0x0A 0x1A 0x0A
|
||||
== .PNG\r\n.\n
|
||||
*/
|
||||
case 0x89: // PNG
|
||||
rtn = CreateFromPng(size, data);
|
||||
break;
|
||||
/* GIF
|
||||
0x47 0x49 0x46
|
||||
*/
|
||||
case 0x47: // GIF
|
||||
rtn = CreateFromGif(size, data);
|
||||
break;
|
||||
/* JPEG
|
||||
A JFIF-standard file will start with the four bytes (hex) FF D8 FF E0,
|
||||
followed by two variable bytes (often hex 00 10), followed by 'JFIF'.
|
||||
*/
|
||||
case 0xFF: // JPEG
|
||||
rtn = CreateFromJpeg(size, data);
|
||||
break;
|
||||
/* WBMP
|
||||
WBMP Type 0: B/W, Uncompressed bitmap is the only gd supported type
|
||||
*/
|
||||
case 0x00: // WBMP
|
||||
rtn = CreateFromWBMP(size, data);
|
||||
break;
|
||||
/* GD2
|
||||
0x67 0x64 0x32 0x00
|
||||
== GD2\0
|
||||
Starts with gd2
|
||||
*/
|
||||
case 0x67: // GD2
|
||||
rtn = CreateFromGd2(size, data);
|
||||
break;
|
||||
/* GD
|
||||
0xFF 0xFE
|
||||
or
|
||||
0xFF 0xFF
|
||||
Conflicts with Jpeg
|
||||
*/
|
||||
default:
|
||||
rtn = false;
|
||||
break;
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
} // namespace GD
|
||||
/**
|
||||
Load an image from a standard input stream, regardless of it's image file format.
|
||||
You can call Width() and Height() member functions of the image to determine its size.
|
||||
Example usage, convert anything to gif:
|
||||
#include <fstream>
|
||||
#include <gdpp.h>
|
||||
|
||||
std::ifstream in("image.xxx", std::ios_base::in | std::ios_base::binary );
|
||||
GD::Image im;
|
||||
in >> im;
|
||||
if (im.good())
|
||||
{
|
||||
std::ofstream out("image.gif", std::ios_base::out | std::ios_base::binary );
|
||||
im.Gif(out);
|
||||
}
|
||||
*/
|
||||
std::istream & operator>> (std::istream & in, GD::Image & img)
|
||||
{
|
||||
img.CreateFrom(in);
|
||||
return in;
|
||||
}
|
||||
|
||||
#endif /* __cplusplus */
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue