[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
reading jpegs faster
From: |
David Grundberg |
Subject: |
reading jpegs faster |
Date: |
Fri, 22 Jan 2010 11:08:06 +0100 |
User-agent: |
Thunderbird 2.0.0.23 (X11/20090812) |
Hi maintainers list,
I'm reading 10 megapixel jpeg files alot. Unfortunately it me takes 9
seconds to load such files with imread on the tip. I think that is too
long time. Is someone experiencing the same problem as me? Or does it
have to do with my configuration?
I've written a function file in C++ that loads the same file in about 1
second.
Best regards,
David
/*
Copyright (C) 2010 David Grundberg
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
Based on code from http://wiki.octave.org/wiki.pl?OctaveJPEG
This code links octave to the IJB jpeg libraries (provided with most
linux distributions, cygwin, and many other Unixes)
It is compiled using
mkoctfile jpgread.cc -ljpeg
*/
#include <octave/oct.h>
#include <errno.h>
extern "C" {
#include "jpeglib.h"
} //extern "C"
#if BITS_IN_JSAMPLE != 8
#error This only works with 8-bit libjpeg.
#endif
struct jpgread_error_mgr {
struct jpeg_error_mgr pub; // "public" fields
jmp_buf setjmp_buffer; // for return to caller
};
typedef struct jpgread_error_mgr * jpgread_error_ptr;
// Callback for fatal errors. Cannot return to caller.
void
jpgread_error_exit (j_common_ptr cinfo)
{
// cinfo->err really points to a jpgread_error_mgr struct, so coerce pointer
jpgread_error_ptr err_mgr = reinterpret_cast<jpgread_error_ptr>
(cinfo->err);
char buffer[JMSG_LENGTH_MAX];
// Create the message
(*cinfo->err->format_message) (cinfo, buffer);
error("jpgread: %s", buffer);
// Return control to the setjmp point
longjmp (err_mgr->setjmp_buffer, 1);
}
// Callback for messages that are not fatal. Overridden to call warning.
void
jpgread_output_message (j_common_ptr cinfo)
{
char buffer[JMSG_LENGTH_MAX];
// Create the message
(*cinfo->err->format_message) (cinfo, buffer);
warning("jpgread: %s", buffer);
}
DEFUN_DLD (jpgread, args, nargout,
"-*- texinfo -*-\n\
@deftypefn {Function File} address@hidden =} jpgread (@var{filename})\n\
Read image from a JPEG file.\n\
\n\
The size and numeric class of the output depends on the\n\
format of the image. A color image is returned as an MxNx3\n\
matrix. Grey-level images are of size MxN. The numeric\n\
class of the output is always \"uint8\".\n\
@seealso{imread, imfinfo}\n\
@end deftypefn")
{
octave_value_list retval;
int nargin = args.length ();
if (sizeof (JSAMPLE) != sizeof (unsigned char))
{
error ("jpgread: configuration error");
return retval;
}
if (nargin != 1 || ! args(0).is_string ())
{
print_usage ();
return retval;
}
std::string filename = args(0).string_value ();
FILE *infile = fopen (filename.c_str (), "rb");
if (infile == NULL)
{
error ("jpgread: %s: %s", filename.c_str (), strerror (errno));
return retval;
}
// We set up the normal JPEG error routines, then override
// error_exit and output_message.
struct jpeg_decompress_struct cinfo;
struct jpgread_error_mgr jerr;
cinfo.err = jpeg_std_error (&jerr.pub);
jerr.pub.error_exit = jpgread_error_exit;
jerr.pub.output_message = jpgread_output_message;
// Establish the setjmp return context for jpgread_error_exit to use.
if (setjmp (jerr.setjmp_buffer))
{
// If we get here, the JPEG code has signaled an error. We need
// to clean up the JPEG object, close the input file, and
// return.
jpeg_destroy_decompress (&cinfo);
fclose (infile);
return retval;
}
jpeg_create_decompress (&cinfo);
// Start decompression
jpeg_stdio_src (&cinfo, infile);
jpeg_read_header (&cinfo, TRUE);
jpeg_start_decompress (&cinfo);
// Allocate Octave array.
uint8NDArray imgdata (dim_vector (cinfo.output_components,
cinfo.output_width,
cinfo.output_height));
JSAMPLE *vec = reinterpret_cast<JSAMPLE *> (imgdata.fortran_vec ());
// Reads results in row-major order
while (cinfo.output_scanline < cinfo.output_height)
{
jpeg_read_scanlines (&cinfo, &vec, 1);
vec += cinfo.output_components * cinfo.output_width;
}
// The image convention in Octave is HxWx3. imgdata contains the
// image stored as RGB-tuples in row-major order, i.e. 3xWxH (or
// 1xWxH for grayscale). Permute imgdata to arrive at the Octave
// convention. img = permute(imgdata, [3 2 1])
Matrix m(1,3);
m(0) = 2;
m(1) = 1;
m(2) = 0;
retval(0) = imgdata.permute (m);
jpeg_finish_decompress (&cinfo);
jpeg_destroy_decompress (&cinfo);
fclose (infile);
return retval;
}
- reading jpegs faster,
David Grundberg <=