Added jpeg loading from memory. Added jpeg Fl_Widget->image() support for Fluid - but linking to fltk_images is required if this feature is used!
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@7092 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
parent
b434df6061
commit
795b2c6356
2
CHANGES
2
CHANGES
@ -1,5 +1,7 @@
|
||||
CHANGES IN FLTK 1.3.0
|
||||
|
||||
- Added jpeg support to Fluid image() element
|
||||
- Added loading jpeg images from memory
|
||||
- Added binary data type to Fluid
|
||||
- File chosser preview would hang if a device was choosen
|
||||
- Replaced _WIN32 symbols that had come with UTF-8 and the
|
||||
|
||||
@ -40,9 +40,10 @@
|
||||
*/
|
||||
class FL_EXPORT Fl_JPEG_Image : public Fl_RGB_Image {
|
||||
|
||||
public:
|
||||
public:
|
||||
|
||||
Fl_JPEG_Image(const char* filename);
|
||||
Fl_JPEG_Image(const char *filename);
|
||||
Fl_JPEG_Image(const char *name, const unsigned char *data);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@ -49,6 +49,7 @@ void Fluid_Image::deimage(Fl_Widget *o) {
|
||||
static int pixmap_header_written = 0;
|
||||
static int bitmap_header_written = 0;
|
||||
static int image_header_written = 0;
|
||||
static int jpeg_header_written = 0;
|
||||
|
||||
void Fluid_Image::write_static() {
|
||||
if (!img) return;
|
||||
@ -100,6 +101,37 @@ void Fluid_Image::write_static() {
|
||||
unique_id(this, "image", fl_filename_name(name()), 0),
|
||||
unique_id(this, "idata", fl_filename_name(name()), 0),
|
||||
img->w(), img->h());
|
||||
} else if (strcmp(fl_filename_ext(name()), ".jpg")==0) {
|
||||
// Write jpeg image data...
|
||||
write_c("\n");
|
||||
if (jpeg_header_written != write_number) {
|
||||
write_c("#include <FL/Fl_JPEG_Image.H>\n");
|
||||
jpeg_header_written = write_number;
|
||||
}
|
||||
write_c("static unsigned char %s[] =\n",
|
||||
unique_id(this, "idata", fl_filename_name(name()), 0));
|
||||
|
||||
FILE *f = fopen(name(), "rb");
|
||||
if (!f) {
|
||||
// message = "Can't include binary file. Can't open";
|
||||
} else {
|
||||
fseek(f, 0, SEEK_END);
|
||||
size_t nData = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
if (nData) {
|
||||
char *data = (char*)calloc(nData, 1);
|
||||
fread(data, nData, 1, f);
|
||||
write_cdata(data, nData);
|
||||
free(data);
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
write_c(";\n");
|
||||
write_c("static Fl_JPEG_Image %s(\"%s\", %s);\n",
|
||||
unique_id(this, "image", fl_filename_name(name()), 0),
|
||||
fl_filename_name(name()),
|
||||
unique_id(this, "idata", fl_filename_name(name()), 0));
|
||||
} else {
|
||||
// Write image data...
|
||||
write_c("\n");
|
||||
|
||||
@ -89,40 +89,47 @@ extern "C" {
|
||||
|
||||
|
||||
/**
|
||||
The constructor loads the JPEG image from the given jpeg filename.
|
||||
<P>The inherited destructor free all memory and server resources that are used by the image.
|
||||
*/
|
||||
Fl_JPEG_Image::Fl_JPEG_Image(const char *jpeg) // I - File to load
|
||||
: Fl_RGB_Image(0,0,0) {
|
||||
\brief The constructor loads the JPEG image from the given jpeg filename.
|
||||
|
||||
The inherited destructor frees all memory and server resources that are used
|
||||
by the image.
|
||||
|
||||
There is no error function in this class. If the image has loaded correctly,
|
||||
w(), h(), and d() should return values greater zero.
|
||||
|
||||
\param filename a full path and name pointing to a valid jpeg file.
|
||||
*/
|
||||
Fl_JPEG_Image::Fl_JPEG_Image(const char *filename) // I - File to load
|
||||
: Fl_RGB_Image(0,0,0) {
|
||||
#ifdef HAVE_LIBJPEG
|
||||
FILE *fp; // File pointer
|
||||
jpeg_decompress_struct dinfo; // Decompressor info
|
||||
fl_jpeg_error_mgr jerr; // Error handler info
|
||||
JSAMPROW row; // Sample row pointer
|
||||
|
||||
|
||||
// the following variables are pointers allocating some private space that
|
||||
// is not reset by 'setjmp()'
|
||||
char* max_finish_decompress_err; // count errors and give up afer a while
|
||||
char* max_destroy_decompress_err; // to avoid recusion and deadlock
|
||||
|
||||
|
||||
// Clear data...
|
||||
alloc_array = 0;
|
||||
array = (uchar *)0;
|
||||
|
||||
|
||||
// Open the image file...
|
||||
if ((fp = fopen(jpeg, "rb")) == NULL) return;
|
||||
|
||||
if ((fp = fopen(filename, "rb")) == NULL) return;
|
||||
|
||||
// Setup the decompressor info and read the header...
|
||||
dinfo.err = jpeg_std_error((jpeg_error_mgr *)&jerr);
|
||||
jerr.pub_.error_exit = fl_jpeg_error_handler;
|
||||
jerr.pub_.output_message = fl_jpeg_output_handler;
|
||||
|
||||
|
||||
// Setup error loop variables
|
||||
max_finish_decompress_err = (char*)malloc(1); // allocate space on the frame for error counters
|
||||
max_destroy_decompress_err = (char*)malloc(1); // otherwise, the variables are reset on the longjmp
|
||||
*max_finish_decompress_err=10;
|
||||
*max_destroy_decompress_err=10;
|
||||
|
||||
|
||||
if (setjmp(jerr.errhand_))
|
||||
{
|
||||
// JPEG error handling...
|
||||
@ -132,62 +139,230 @@ Fl_JPEG_Image::Fl_JPEG_Image(const char *jpeg) // I - File to load
|
||||
jpeg_finish_decompress(&dinfo);
|
||||
if ( (*max_destroy_decompress_err)-- > 0)
|
||||
jpeg_destroy_decompress(&dinfo);
|
||||
|
||||
|
||||
fclose(fp);
|
||||
|
||||
|
||||
w(0);
|
||||
h(0);
|
||||
d(0);
|
||||
|
||||
|
||||
if (array) {
|
||||
delete[] (uchar *)array;
|
||||
array = 0;
|
||||
alloc_array = 0;
|
||||
}
|
||||
|
||||
|
||||
free(max_destroy_decompress_err);
|
||||
free(max_finish_decompress_err);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
jpeg_create_decompress(&dinfo);
|
||||
jpeg_stdio_src(&dinfo, fp);
|
||||
jpeg_read_header(&dinfo, 1);
|
||||
|
||||
|
||||
dinfo.quantize_colors = (boolean)FALSE;
|
||||
dinfo.out_color_space = JCS_RGB;
|
||||
dinfo.out_color_components = 3;
|
||||
dinfo.output_components = 3;
|
||||
|
||||
|
||||
jpeg_calc_output_dimensions(&dinfo);
|
||||
|
||||
|
||||
w(dinfo.output_width);
|
||||
h(dinfo.output_height);
|
||||
d(dinfo.output_components);
|
||||
|
||||
|
||||
array = new uchar[w() * h() * d()];
|
||||
alloc_array = 1;
|
||||
|
||||
|
||||
jpeg_start_decompress(&dinfo);
|
||||
|
||||
|
||||
while (dinfo.output_scanline < dinfo.output_height) {
|
||||
row = (JSAMPROW)(array +
|
||||
dinfo.output_scanline * dinfo.output_width *
|
||||
dinfo.output_components);
|
||||
jpeg_read_scanlines(&dinfo, &row, (JDIMENSION)1);
|
||||
}
|
||||
|
||||
|
||||
jpeg_finish_decompress(&dinfo);
|
||||
jpeg_destroy_decompress(&dinfo);
|
||||
|
||||
|
||||
free(max_destroy_decompress_err);
|
||||
free(max_finish_decompress_err);
|
||||
|
||||
|
||||
fclose(fp);
|
||||
#endif // HAVE_LIBJPEG
|
||||
}
|
||||
|
||||
|
||||
// data source manager for reading jpegs from memory
|
||||
// init_source (j_decompress_ptr cinfo)
|
||||
// fill_input_buffer (j_decompress_ptr cinfo)
|
||||
// skip_input_data (j_decompress_ptr cinfo, long num_bytes)
|
||||
// resync_to_restart (j_decompress_ptr cinfo, int desired)
|
||||
// term_source (j_decompress_ptr cinfo)
|
||||
// JOCTET * next_output_byte; /* => next byte to write in buffer */
|
||||
// size_t free_in_buffer; /* # of byte spaces remaining in buffer */
|
||||
|
||||
|
||||
typedef struct {
|
||||
struct jpeg_source_mgr pub;
|
||||
const unsigned char *data, *s;
|
||||
// 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;
|
||||
|
||||
|
||||
void init_source (j_decompress_ptr cinfo) {
|
||||
my_src_ptr src = (my_src_ptr)cinfo->src;
|
||||
src->s = src->data;
|
||||
}
|
||||
|
||||
boolean fill_input_buffer(j_decompress_ptr cinfo) {
|
||||
my_src_ptr src = (my_src_ptr)cinfo->src;
|
||||
size_t nbytes = 4096;
|
||||
src->pub.next_input_byte = src->s;
|
||||
src->pub.bytes_in_buffer = nbytes;
|
||||
src->s += nbytes;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void term_source(j_decompress_ptr cinfo)
|
||||
{
|
||||
}
|
||||
|
||||
void skip_input_data(j_decompress_ptr cinfo, long num_bytes) {
|
||||
my_src_ptr src = (my_src_ptr)cinfo->src;
|
||||
if (num_bytes > 0) {
|
||||
while (num_bytes > (long)src->pub.bytes_in_buffer) {
|
||||
num_bytes -= (long)src->pub.bytes_in_buffer;
|
||||
fill_input_buffer(cinfo);
|
||||
}
|
||||
src->pub.next_input_byte += (size_t) num_bytes;
|
||||
src->pub.bytes_in_buffer -= (size_t) num_bytes;
|
||||
}
|
||||
}
|
||||
|
||||
static void jpeg_mem_src(j_decompress_ptr cinfo, const unsigned char *data)
|
||||
{
|
||||
my_src_ptr src;
|
||||
cinfo->src = (struct jpeg_source_mgr *)malloc(sizeof(my_source_mgr));
|
||||
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;
|
||||
src->pub.term_source = term_source;
|
||||
src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
|
||||
src->pub.next_input_byte = NULL; /* until buffer loaded */
|
||||
src->data = data;
|
||||
src->s = data;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief The constructor loads the JPEG image from memory.
|
||||
|
||||
The inherited destructor frees all memory and server resources that are used
|
||||
by the image.
|
||||
|
||||
There is no error function in this class. If the image has loaded correctly,
|
||||
w(), h(), and d() should return values greater zero.
|
||||
|
||||
\param name developer shoud provide a unique name for this image
|
||||
\param data a pointer to the memorry location of the jpeg image
|
||||
*/
|
||||
Fl_JPEG_Image::Fl_JPEG_Image(const char *name, const unsigned char *data)
|
||||
: Fl_RGB_Image(0,0,0) {
|
||||
#ifdef HAVE_LIBJPEG
|
||||
jpeg_decompress_struct dinfo; // Decompressor info
|
||||
fl_jpeg_error_mgr jerr; // Error handler info
|
||||
JSAMPROW row; // Sample row pointer
|
||||
|
||||
// the following variables are pointers allocating some private space that
|
||||
// is not reset by 'setjmp()'
|
||||
char* max_finish_decompress_err; // count errors and give up afer a while
|
||||
char* max_destroy_decompress_err; // to avoid recusion and deadlock
|
||||
|
||||
// Clear data...
|
||||
alloc_array = 0;
|
||||
array = (uchar *)0;
|
||||
|
||||
// Setup the decompressor info and read the header...
|
||||
dinfo.err = jpeg_std_error((jpeg_error_mgr *)&jerr);
|
||||
jerr.pub_.error_exit = fl_jpeg_error_handler;
|
||||
jerr.pub_.output_message = fl_jpeg_output_handler;
|
||||
|
||||
// Setup error loop variables
|
||||
max_finish_decompress_err = (char*)malloc(1); // allocate space on the frame for error counters
|
||||
max_destroy_decompress_err = (char*)malloc(1); // otherwise, the variables are reset on the longjmp
|
||||
*max_finish_decompress_err=10;
|
||||
*max_destroy_decompress_err=10;
|
||||
|
||||
if (setjmp(jerr.errhand_))
|
||||
{
|
||||
// JPEG error handling...
|
||||
// if any of the cleanup routines hits another error, we would end up
|
||||
// in a loop. So instead, we decrement max_err for some upper cleanup limit.
|
||||
if ( ((*max_finish_decompress_err)-- > 0) && array)
|
||||
jpeg_finish_decompress(&dinfo);
|
||||
if ( (*max_destroy_decompress_err)-- > 0)
|
||||
jpeg_destroy_decompress(&dinfo);
|
||||
|
||||
w(0);
|
||||
h(0);
|
||||
d(0);
|
||||
|
||||
if (array) {
|
||||
delete[] (uchar *)array;
|
||||
array = 0;
|
||||
alloc_array = 0;
|
||||
}
|
||||
|
||||
free(max_destroy_decompress_err);
|
||||
free(max_finish_decompress_err);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
jpeg_create_decompress(&dinfo);
|
||||
jpeg_mem_src(&dinfo, data);
|
||||
jpeg_read_header(&dinfo, 1);
|
||||
|
||||
dinfo.quantize_colors = (boolean)FALSE;
|
||||
dinfo.out_color_space = JCS_RGB;
|
||||
dinfo.out_color_components = 3;
|
||||
dinfo.output_components = 3;
|
||||
|
||||
jpeg_calc_output_dimensions(&dinfo);
|
||||
|
||||
w(dinfo.output_width);
|
||||
h(dinfo.output_height);
|
||||
d(dinfo.output_components);
|
||||
|
||||
array = new uchar[w() * h() * d()];
|
||||
alloc_array = 1;
|
||||
|
||||
jpeg_start_decompress(&dinfo);
|
||||
|
||||
while (dinfo.output_scanline < dinfo.output_height) {
|
||||
row = (JSAMPROW)(array +
|
||||
dinfo.output_scanline * dinfo.output_width *
|
||||
dinfo.output_components);
|
||||
jpeg_read_scanlines(&dinfo, &row, (JDIMENSION)1);
|
||||
}
|
||||
|
||||
jpeg_finish_decompress(&dinfo);
|
||||
jpeg_destroy_decompress(&dinfo);
|
||||
|
||||
free(max_destroy_decompress_err);
|
||||
free(max_finish_decompress_err);
|
||||
#endif // HAVE_LIBJPEG
|
||||
}
|
||||
|
||||
//
|
||||
// End of "$Id$".
|
||||
//
|
||||
|
||||
Loading…
Reference in New Issue
Block a user