From 1f898264dd2ff3d4b96b9b64a7dd328b38626da4 Mon Sep 17 00:00:00 2001 From: Julien Malik <julien.malik@c-s.fr> Date: Tue, 22 Jun 2010 11:26:22 +0200 Subject: [PATCH] BUG: correct jpeg bug when compiling OTB with VC9 versus OSGeo dependencies --- .../include/ossim/imaging/ossimJpegStdIOSrc.h | 29 ++ .../src/ossim/imaging/ossimJpegStdIOSrc.cpp | 248 ++++++++++++++++++ .../src/ossim/imaging/ossimJpegTileSource.cpp | 12 +- 3 files changed, 288 insertions(+), 1 deletion(-) create mode 100644 Utilities/otbossim/include/ossim/imaging/ossimJpegStdIOSrc.h create mode 100644 Utilities/otbossim/src/ossim/imaging/ossimJpegStdIOSrc.cpp diff --git a/Utilities/otbossim/include/ossim/imaging/ossimJpegStdIOSrc.h b/Utilities/otbossim/include/ossim/imaging/ossimJpegStdIOSrc.h new file mode 100644 index 0000000000..40f15eb75f --- /dev/null +++ b/Utilities/otbossim/include/ossim/imaging/ossimJpegStdIOSrc.h @@ -0,0 +1,29 @@ +//---------------------------------------------------------------------------- +// License: See top level LICENSE.txt file. +// +// Author: David Burken, original code from Thomas G. Lane +// +// Description: +// Code interfaces to use with jpeg-6b library to read a jpeg image from +// memory. +//---------------------------------------------------------------------------- +// $Id$ +#ifndef ossimJpegStdIOSrc_HEADER +#define ossimJpegStdIOSrc_HEADER + +#include <ossim/base/ossimConstants.h> /** for OSSIM_DLL export macro */ +extern "C" +{ +#include <cstdio> /** for size_t */ +#include <csetjmp> /** for jmp_buf */ +#include <jpeglib.h> /** for jpeg stuff */ +//#include <jinclude.h> +//#include <jerror.h> +/** + * @brief Method which uses memory instead of a FILE* to read from. + * @note Used in place of "jpeg_stdio_src(&cinfo, infile)". + */ +OSSIM_DLL void ossimJpegStdIOSrc ( j_decompress_ptr cinfo, + FILE* infile); +} +#endif /* #ifndef ossimJpegMemSrc_HEADER */ diff --git a/Utilities/otbossim/src/ossim/imaging/ossimJpegStdIOSrc.cpp b/Utilities/otbossim/src/ossim/imaging/ossimJpegStdIOSrc.cpp new file mode 100644 index 0000000000..598cacee46 --- /dev/null +++ b/Utilities/otbossim/src/ossim/imaging/ossimJpegStdIOSrc.cpp @@ -0,0 +1,248 @@ +/*========================================================================= + + Program: ORFEO Toolbox + Language: C++ + Date: $Date$ + Version: $Revision$ + + + Copyright (c) Centre National d'Etudes Spatiales. All rights reserved. + See OTBCopyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +/* + * jdatasrc.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains decompression data source routines for the case of + * reading JPEG data from a file (or any stdio stream). While these routines + * are sufficient for most applications, some will want to use a different + * source manager. + * IMPORTANT: we assume that fread() will correctly transcribe an array of + * JOCTETs from 8-bit-wide elements on external storage. If char is wider + * than 8 bits on your machine, you may need to do some tweaking. + */ + +/* this is not a core library module, so it doesn't define JPEG_INTERNALS */ + +#include <ossim/imaging/ossimJpegStdIOSrc.h> +#include <jerror.h> + + +#define INPUT_BUF_SIZE 4096 /* choose an efficiently fread'able size */ + +#define JFREAD(file,buf,sizeofbuf) \ + ((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) + +/* + * In ANSI C, and indeed any rational implementation, size_t is also the + * type returned by sizeof(). However, it seems there are some irrational + * implementations out there, in which sizeof() returns an int even though + * size_t is defined as long or unsigned long. To ensure consistent results + * we always use this SIZEOF() macro in place of using sizeof() directly. + */ + +#define SIZEOF(object) ((size_t) sizeof(object)) + +extern "C" +{ + +/* Expanded data source object for stdio input */ + +typedef struct { + struct jpeg_source_mgr pub; /* public fields */ + + FILE * infile; /* source stream */ + JOCTET * buffer; /* start of buffer */ + boolean start_of_file; /* have we gotten any data yet? */ +} ossimJpegStdIOSourceMgr; + +typedef ossimJpegStdIOSourceMgr * ossimJpegStdIOSourceMgrPtr; + + + +/* + * Initialize source --- called by jpeg_read_header + * before any data is actually read. + */ + +void +ossimJpegStdIOSrc_init_source (j_decompress_ptr cinfo) +{ + ossimJpegStdIOSourceMgrPtr src = (ossimJpegStdIOSourceMgrPtr) cinfo->src; + + /* We reset the empty-input-file flag for each image, + * but we don't clear the input buffer. + * This is correct behavior for reading a series of images from one source. + */ + src->start_of_file = TRUE; +} + + +/* + * Fill the input buffer --- called whenever buffer is emptied. + * + * In typical applications, this should read fresh data into the buffer + * (ignoring the current state of next_input_byte & bytes_in_buffer), + * reset the pointer & count to the start of the buffer, and return TRUE + * indicating that the buffer has been reloaded. It is not necessary to + * fill the buffer entirely, only to obtain at least one more byte. + * + * There is no such thing as an EOF return. If the end of the file has been + * reached, the routine has a choice of ERREXIT() or inserting fake data into + * the buffer. In most cases, generating a warning message and inserting a + * fake EOI marker is the best course of action --- this will allow the + * decompressor to output however much of the image is there. However, + * the resulting error message is misleading if the real problem is an empty + * input file, so we handle that case specially. + * + * In applications that need to be able to suspend compression due to input + * not being available yet, a FALSE return indicates that no more data can be + * obtained right now, but more may be forthcoming later. In this situation, + * the decompressor will return to its caller (with an indication of the + * number of scanlines it has read, if any). The application should resume + * decompression after it has loaded more data into the input buffer. Note + * that there are substantial restrictions on the use of suspension --- see + * the documentation. + * + * When suspending, the decompressor will back up to a convenient restart point + * (typically the start of the current MCU). next_input_byte & bytes_in_buffer + * indicate where the restart point will be if the current call returns FALSE. + * Data beyond this point must be rescanned after resumption, so move it to + * the front of the buffer rather than discarding it. + */ + +boolean +ossimJpegStdIOSrc_fill_input_buffer (j_decompress_ptr cinfo) +{ + ossimJpegStdIOSourceMgrPtr src = (ossimJpegStdIOSourceMgrPtr) cinfo->src; + size_t nbytes; + + nbytes = JFREAD(src->infile, src->buffer, INPUT_BUF_SIZE); + + if (nbytes <= 0) { + if (src->start_of_file) /* Treat empty input file as fatal error */ + ERREXIT(cinfo, JERR_INPUT_EMPTY); + WARNMS(cinfo, JWRN_JPEG_EOF); + /* Insert a fake EOI marker */ + src->buffer[0] = (JOCTET) 0xFF; + src->buffer[1] = (JOCTET) JPEG_EOI; + nbytes = 2; + } + + src->pub.next_input_byte = src->buffer; + src->pub.bytes_in_buffer = nbytes; + src->start_of_file = FALSE; + + return TRUE; +} + + +/* + * Skip data --- used to skip over a potentially large amount of + * uninteresting data (such as an APPn marker). + * + * Writers of suspendable-input applications must note that skip_input_data + * is not granted the right to give a suspension return. If the skip extends + * beyond the data currently in the buffer, the buffer can be marked empty so + * that the next read will cause a fill_input_buffer call that can suspend. + * Arranging for additional bytes to be discarded before reloading the input + * buffer is the application writer's problem. + */ + +void +ossimJpegStdIOSrc_skip_input_data (j_decompress_ptr cinfo, long num_bytes) +{ + ossimJpegStdIOSourceMgrPtr src = (ossimJpegStdIOSourceMgrPtr) cinfo->src; + + /* Just a dumb implementation for now. Could use fseek() except + * it doesn't work on pipes. Not clear that being smart is worth + * any trouble anyway --- large skips are infrequent. + */ + if (num_bytes > 0) { + while (num_bytes > (long) src->pub.bytes_in_buffer) { + num_bytes -= (long) src->pub.bytes_in_buffer; + (void) ossimJpegStdIOSrc_fill_input_buffer(cinfo); + /* note we assume that fill_input_buffer will never return FALSE, + * so suspension need not be handled. + */ + } + src->pub.next_input_byte += (size_t) num_bytes; + src->pub.bytes_in_buffer -= (size_t) num_bytes; + } +} + + +/* + * An additional method that can be provided by data source modules is the + * resync_to_restart method for error recovery in the presence of RST markers. + * For the moment, this source module just uses the default resync method + * provided by the JPEG library. That method assumes that no backtracking + * is possible. + */ + + +/* + * Terminate source --- called by jpeg_finish_decompress + * after all data has been read. Often a no-op. + * + * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding + * application must deal with any cleanup that should happen even + * for error exit. + */ + +void +ossimJpegStdIOSrc_term_source (j_decompress_ptr cinfo) +{ + (void)cinfo; + /* no work necessary here */ +} + + +/* + * Prepare for input from a stdio stream. + * The caller must have already opened the stream, and is responsible + * for closing it after finishing decompression. + */ + +void +ossimJpegStdIOSrc (j_decompress_ptr cinfo, FILE * infile) +{ + ossimJpegStdIOSourceMgrPtr src; + + /* The source object and input buffer are made permanent so that a series + * of JPEG images can be read from the same file by calling jpeg_stdio_src + * only before the first one. (If we discarded the buffer at the end of + * one image, we'd likely lose the start of the next one.) + * This makes it unsafe to use this manager and a different source + * manager serially with the same JPEG object. Caveat programmer. + */ + if (cinfo->src == NULL) { /* first time for this JPEG object? */ + cinfo->src = (struct jpeg_source_mgr *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(ossimJpegStdIOSourceMgr)); + src = (ossimJpegStdIOSourceMgrPtr) cinfo->src; + src->buffer = (JOCTET *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + INPUT_BUF_SIZE * SIZEOF(JOCTET)); + } + + src = (ossimJpegStdIOSourceMgrPtr) cinfo->src; + src->pub.init_source = ossimJpegStdIOSrc_init_source; + src->pub.fill_input_buffer = ossimJpegStdIOSrc_fill_input_buffer; + src->pub.skip_input_data = ossimJpegStdIOSrc_skip_input_data; + src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */ + src->pub.term_source = ossimJpegStdIOSrc_term_source; + src->infile = infile; + src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */ + src->pub.next_input_byte = NULL; /* until buffer loaded */ +} +} diff --git a/Utilities/otbossim/src/ossim/imaging/ossimJpegTileSource.cpp b/Utilities/otbossim/src/ossim/imaging/ossimJpegTileSource.cpp index 48f1639fba..31fe7366e2 100644 --- a/Utilities/otbossim/src/ossim/imaging/ossimJpegTileSource.cpp +++ b/Utilities/otbossim/src/ossim/imaging/ossimJpegTileSource.cpp @@ -23,6 +23,7 @@ extern "C" } #include <ossim/imaging/ossimJpegTileSource.h> +#include <ossim/imaging/ossimJpegStdIOSrc.h> #include <ossim/imaging/ossimTiffTileSource.h> #include <ossim/imaging/ossimImageDataFactory.h> #include <ossim/base/ossimConstants.h> @@ -505,6 +506,14 @@ bool ossimJpegTileSource::open() thePrivateData = new PrivateData(); rewind(theFilePtr); +/* + std::ifstream file("file.bin", std::ios_base::binary | std::ios_base::ate | std::ios_base::in); + int filesize = file.tellg(); + char* buffer = new char[filesize]; + file.seekg(0, std::ios_base::beg); + file.read(buffer, filesize); + file.close(); +*/ //--- // Step 1: allocate and initialize JPEG decompression object // We set up the normal JPEG error routines, then override error_exit. @@ -515,7 +524,8 @@ bool ossimJpegTileSource::open() jpeg_create_decompress(&thePrivateData->theCinfo); // Specify data source. - jpeg_stdio_src(&thePrivateData->theCinfo, theFilePtr); + //jpeg_stdio_src(&thePrivateData->theCinfo, theFilePtr); + ossimJpegStdIOSrc(&thePrivateData->theCinfo, theFilePtr); // Read the file parameters with jpeg_read_header. jpeg_read_header(&thePrivateData->theCinfo, TRUE); -- GitLab