27 # ifdef BIAS_HAVE_WXWIDGETS
28 # include <wx/msw/winundef.h>
31 #include "CompressJpeg.hh"
32 #include <Base/Image/MetaData.hh>
54 #pragma warning(disable:4611)
56 #pragma warning(disable:4324)
75 #include <sys/types.h>
81 JSAMPLE * image_buffer;
94 struct jpeg_error_mgr pub;
95 jmp_buf setjmp_buffer;
98 typedef struct my_error_mgr * my_error_ptr;
105 my_error_exit (j_common_ptr cinfo)
108 my_error_ptr myerr = (my_error_ptr) cinfo->err;
112 (*cinfo->err->output_message) (cinfo);
115 longjmp(myerr->setjmp_buffer, 1);
119 silent_error_exit (j_common_ptr cinfo)
122 my_error_ptr myerr = (my_error_ptr) cinfo->err;
125 longjmp(myerr->setjmp_buffer, 1);
132 init_source (j_decompress_ptr )
138 fill_input_buffer (j_decompress_ptr cinfo)
140 static JOCTET dummy[] = { (JOCTET) 0xFF, (JOCTET) JPEG_EOI };
146 cinfo->src->next_input_byte = dummy;
147 cinfo->src->bytes_in_buffer = 2;
153 skip_input_data (j_decompress_ptr cinfo,
long num_bytes)
156 while (num_bytes > (
long) cinfo->src->bytes_in_buffer) {
157 num_bytes -= (long) cinfo->src->bytes_in_buffer;
158 (
void) fill_input_buffer(cinfo);
160 cinfo->src->next_input_byte += (size_t) num_bytes;
161 cinfo->src->bytes_in_buffer -= (size_t) num_bytes;
167 term_source (j_decompress_ptr )
176 init_destination (j_compress_ptr )
182 empty_output_buffer (j_compress_ptr cinfo)
184 BIASERR(
"JPEG-buffer is too small!!!");
185 cinfo->dest->next_output_byte = NULL;
186 cinfo->dest->free_in_buffer = 0;
191 term_destination (j_compress_ptr )
200 int create_JPEG_file (
void * outfile,
long length,
int quality)
208 struct jpeg_compress_struct cinfo;
217 struct jpeg_error_mgr jerr;
218 struct jpeg_destination_mgr jdest;
220 JSAMPROW row_pointer[1];
230 cinfo.err = jpeg_std_error(&jerr);
232 jpeg_create_compress(&cinfo);
250 jdest.init_destination = init_destination;
251 jdest.empty_output_buffer = empty_output_buffer;
252 jdest.term_destination = term_destination;
253 jdest.free_in_buffer = length;
254 jdest.next_output_byte = (JOCTET *) outfile;
261 cinfo.image_width = image_width;
262 cinfo.image_height = image_height;
263 cinfo.input_components = image_channels;
264 if (image_channels == 1) {
265 cinfo.in_color_space = JCS_GRAYSCALE;
266 }
else if (image_channels == 3) {
267 cinfo.in_color_space = JCS_RGB;
269 BIASERR(
"Compression not implemented for images with channels != 1,3");
276 jpeg_set_defaults(&cinfo);
280 jpeg_set_quality(&cinfo, quality, TRUE );
287 jpeg_start_compress(&cinfo, TRUE);
297 row_stride = image_width * image_channels;
299 while (cinfo.next_scanline < cinfo.image_height) {
304 row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride];
305 (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
310 jpeg_finish_compress(&cinfo);
312 int res = int(length - cinfo.dest->free_in_buffer);
319 jpeg_destroy_compress(&cinfo);
326 int deflate_JPEG_file (
void * infile,
long length,
328 bool readComment,
bool verbose =
true)
333 struct jpeg_decompress_struct cinfo;
338 struct my_error_mgr jerr;
340 struct jpeg_source_mgr jsrc;
351 if (infile == NULL) {
352 BIASERR(
"No source JPEG given!");
359 cinfo.err = jpeg_std_error(&jerr.pub);
361 jerr.pub.error_exit = my_error_exit;
363 jerr.pub.error_exit = silent_error_exit;
366 if (setjmp(jerr.setjmp_buffer)) {
370 jpeg_destroy_decompress(&cinfo);
374 jpeg_create_decompress(&cinfo);
382 jpeg_destroy_decompress(&cinfo);
387 jsrc.init_source = init_source;
388 jsrc.fill_input_buffer = fill_input_buffer;
389 jsrc.skip_input_data = skip_input_data;
390 jsrc.resync_to_restart = jpeg_resync_to_restart;
391 jsrc.term_source = term_source;
392 jsrc.bytes_in_buffer = length;
393 jsrc.next_input_byte = (JOCTET *) infile;
397 jpeg_save_markers(&cinfo, JPEG_COM, 0xFFFF);
402 (void) jpeg_read_header(&cinfo, TRUE);
410 std::string comment(
"");
412 jpeg_marker_struct* marker_ptr = cinfo.marker_list;
414 if (marker_ptr->marker == JPEG_COM) {
415 unsigned char *c_ptr = marker_ptr->data;
416 unsigned int c_len = marker_ptr->data_length;
417 comment += std::string((
char*)c_ptr, c_len);
419 marker_ptr = marker_ptr->next;
431 (void) jpeg_start_decompress(&cinfo);
443 destImg.
Init(cinfo.output_width, cinfo.output_height,
444 cinfo.output_components);
447 if ((destImg.
GetWidth() != (
unsigned int) cinfo.output_width)||
448 (destImg.
GetHeight() != (
unsigned int) cinfo.output_height)||
449 (destImg.
GetChannelCount() != (
unsigned int) cinfo.output_components)) {
450 BIASWARN(
"Given image has wrong format (height, width, ...) but is now initialized correctly!");
452 destImg.
Init(cinfo.output_width, cinfo.output_height,
453 cinfo.output_components);
459 row_stride = cinfo.output_width * cinfo.output_components;
461 buffer = (*cinfo.mem->alloc_sarray)
462 ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
471 while (cinfo.output_scanline < cinfo.output_height) {
476 (void) jpeg_read_scanlines(&cinfo, buffer, 1);
481 memcpy(img_data[cinfo.output_scanline-1],buffer[0],row_stride);
486 (void) jpeg_finish_decompress(&cinfo);
494 jpeg_destroy_decompress(&cinfo);
508 if (readComment && comment !=
"") {
510 metadata.
Add(
"#[Comment]", comment);
518 int deflate_JPEG_file (
void * infile,
long length,
unsigned int &width,
519 unsigned int &height,
unsigned int &channels,
520 unsigned char* &data,
bool verbose =
true)
525 struct jpeg_decompress_struct cinfo;
530 struct my_error_mgr jerr;
532 struct jpeg_source_mgr jsrc;
543 if (infile == NULL) {
544 BIASERR(
"No source JPEG given!!!");
551 cinfo.err = jpeg_std_error(&jerr.pub);
553 jerr.pub.error_exit = my_error_exit;
555 jerr.pub.error_exit = silent_error_exit;
558 if (setjmp(jerr.setjmp_buffer)) {
562 jpeg_destroy_decompress(&cinfo);
566 jpeg_create_decompress(&cinfo);
574 jpeg_destroy_decompress(&cinfo);
579 jsrc.init_source = init_source;
580 jsrc.fill_input_buffer = fill_input_buffer;
581 jsrc.skip_input_data = skip_input_data;
582 jsrc.resync_to_restart = jpeg_resync_to_restart;
583 jsrc.term_source = term_source;
584 jsrc.bytes_in_buffer = length;
585 jsrc.next_input_byte = (JOCTET *) infile;
589 (void) jpeg_read_header(&cinfo, TRUE);
604 (void) jpeg_start_decompress(&cinfo);
615 width = cinfo.output_width;
616 height = cinfo.output_height;
617 channels = cinfo.output_components;
620 BIASWARN(
"Allocating " << width * height * channels <<
" bytes of mem for"
621 <<
" returned datafield!!!\n");
622 data =
new unsigned char[width * height * channels];
626 row_stride = cinfo.output_width * cinfo.output_components;
628 buffer = (*cinfo.mem->alloc_sarray)
629 ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
637 while (cinfo.output_scanline < cinfo.output_height) {
642 (void) jpeg_read_scanlines(&cinfo, buffer, 1);
647 memcpy(data + (cinfo.output_scanline-1)*width*channels, buffer[0], row_stride);
652 (void) jpeg_finish_decompress(&cinfo);
660 jpeg_destroy_decompress(&cinfo);
678 JpegHandler::JpegHandler()
686 JpegHandler::JpegHandler(
long size)
695 JpegHandler::~JpegHandler()
700 int JpegHandler::Init(
long size)
705 data_ = (
void *)
new unsigned char[size];
708 BIASERR(
"Could not create buffer!");
716 void JpegHandler::Release()
719 delete[] ((
unsigned char *) data_);
729 BIASERR(
"Data buffer has not been set up. Call Init() first!");
738 dataLength_ = create_JPEG_file(data_, bufferSize_, quality);
740 if (dataLength_ < 0) {
741 BIASERR(
"Error crunching JPEG image!");
750 Compress(
unsigned int width,
unsigned int height,
unsigned int channels,
751 unsigned char* data,
int quality)
754 BIASERR(
"Data buffer has not been set up. Call Init() first!");
758 image_height = height;
760 image_channels = channels;
763 dataLength_ = create_JPEG_file(data_, bufferSize_, quality);
765 if (dataLength_ < 0) {
766 BIASERR(
"Error crunching JPEG image!");
778 BIASERR(
"Data buffer has not been set up. Call Init() first!");
782 return deflate_JPEG_file(data_, dataLength_, destImg, readComment, verbose_);
786 Decompress(
unsigned int &width,
unsigned int &height,
787 unsigned int &channels,
unsigned char* &data)
790 BIASERR(
"Data buffer has not been set up. Call Init() first!");
794 return deflate_JPEG_file(data_, dataLength_, width, height,
795 channels, data, verbose_);
799 Compress(
unsigned int width,
unsigned int height,
unsigned int channels,
800 unsigned char* inData,
unsigned char *outData,
long &outBytes,
803 image_height = height;
805 image_channels = channels;
806 image_buffer = inData;
808 outBytes = create_JPEG_file(outData, width * height * channels, quality);
811 BIASERR(
"Error crunching JPEG image!");
819 Decompress(
unsigned int &width,
unsigned int &height,
unsigned int &channels,
820 unsigned char* inData,
long inBytes,
unsigned char* outData)
822 return deflate_JPEG_file(inData, inBytes, width, height, channels, outData, verbose_);
825 int JpegHandler::WriteJPEG(
const string &filename) {
828 BIASERR(
"Data buffer has not been set up. Call Init() first!");
834 fopen_s(&output, filename.c_str(),
"wb");
836 FILE * output = fopen(filename.c_str(),
"wb");
839 if (output == NULL) {
840 BIASERR(
"Could not open output file" << filename <<
"!");
844 if (
long(fwrite(data_, 1, dataLength_, output)) != dataLength_) {
845 BIASERR(
"Could not write data to file " << filename <<
" completely!");
854 int JpegHandler::ReadJPEG(
const string &filename) {
857 BIASERR(
"Data buffer has not been set up. Call Init() first!");
863 fopen_s(&input, filename.c_str(),
"rb");
865 FILE * input = fopen(filename.c_str(),
"rb");
869 BIASERR(
"Could not read file " << filename <<
"!");
874 fseek(input, 0L, SEEK_END);
875 dataLength_ = ftell(input);
878 if (data_ == NULL || bufferSize_ < dataLength_) {
879 BIASWARN(
"File (" << dataLength_ <<
" bytes) is too large for internal "
880 "buffer (" << bufferSize_ <<
" bytes), re-initialising buffer...");
881 if (Init(dataLength_) < 0)
885 if (
long(fread(data_, 1, dataLength_, input)) != dataLength_) {
886 BIASERR(
"Failed to load file " << filename <<
" completely!");
void Release()
reimplemented from ImageBase
bool IsEmpty() const
check if ImageData_ points to allocated image buffer or not
unsigned int GetWidth() const
unsigned int GetChannelCount() const
returns the number of Color channels, e.g.
unsigned int GetHeight() const
void Init(unsigned int Width, unsigned int Height, unsigned int channels=1, enum EStorageType storageType=ST_unsignedchar, const bool interleaved=true)
calls Init from ImageBase storageType is ignored, just dummy argument
const StorageType * GetImageData() const
overloaded GetImageData() from ImageBase
void SetMetaData(const MetaData &m)
const StorageType ** GetImageDataArray() const
overloaded GetImageDataArray() from ImageBase