octave-maintainers
[Top][All Lists]
Advanced

[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;
}

reply via email to

[Prev in Thread] Current Thread [Next in Thread]