Blame lib/ljpegdecompressor.cpp

rpm-build d2b433
/*
rpm-build d2b433
 * libopenraw - ljpegdecompressor.cpp
rpm-build d2b433
 *
rpm-build d2b433
 * Copyright (C) 2007-2016 Hubert Figuiere
rpm-build d2b433
 *
rpm-build d2b433
 * This library is free software: you can redistribute it and/or
rpm-build d2b433
 * modify it under the terms of the GNU Lesser General Public License
rpm-build d2b433
 * as published by the Free Software Foundation, either version 3 of
rpm-build d2b433
 * the License, or (at your option) any later version.
rpm-build d2b433
 *
rpm-build d2b433
 * This library is distributed in the hope that it will be useful,
rpm-build d2b433
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
rpm-build d2b433
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
rpm-build d2b433
 * Lesser General Public License for more details.
rpm-build d2b433
 *
rpm-build d2b433
 * You should have received a copy of the GNU Lesser General Public
rpm-build d2b433
 * License along with this library.  If not, see
rpm-build d2b433
 * <http://www.gnu.org/licenses/>.
rpm-build d2b433
 */
rpm-build d2b433
/*
rpm-build d2b433
 * Code for JPEG lossless decoding.  Large parts are grabbed from the IJG
rpm-build d2b433
 * software, so:
rpm-build d2b433
 *
rpm-build d2b433
 * Copyright (C) 1991, 1992, Thomas G. Lane.
rpm-build d2b433
 * Part of the Independent JPEG Group's software.
rpm-build d2b433
 * See the file Copyright for more details.
rpm-build d2b433
 *
rpm-build d2b433
 * Copyright (c) 1993 Brian C. Smith, The Regents of the University
rpm-build d2b433
 * of California
rpm-build d2b433
 * All rights reserved.
rpm-build d2b433
 * 
rpm-build d2b433
 * Copyright (c) 1994 Kongji Huang and Brian C. Smith.
rpm-build d2b433
 * Cornell University
rpm-build d2b433
 * All rights reserved.
rpm-build d2b433
 * 
rpm-build d2b433
 * Permission to use, copy, modify, and distribute this software and its
rpm-build d2b433
 * documentation for any purpose, without fee, and without written agreement is
rpm-build d2b433
 * hereby granted, provided that the above copyright notice and the following
rpm-build d2b433
 * two paragraphs appear in all copies of this software.
rpm-build d2b433
 * 
rpm-build d2b433
 * IN NO EVENT SHALL CORNELL UNIVERSITY BE LIABLE TO ANY PARTY FOR
rpm-build d2b433
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
rpm-build d2b433
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF CORNELL
rpm-build d2b433
 * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
rpm-build d2b433
 * 
rpm-build d2b433
 * CORNELL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
rpm-build d2b433
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
rpm-build d2b433
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
rpm-build d2b433
 * ON AN "AS IS" BASIS, AND CORNELL UNIVERSITY HAS NO OBLIGATION TO
rpm-build d2b433
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
rpm-build d2b433
 */
rpm-build d2b433
rpm-build d2b433
rpm-build d2b433
#include <stdlib.h>
rpm-build d2b433
#include <string.h>
rpm-build d2b433
rpm-build d2b433
#include <fcntl.h>
rpm-build d2b433
#include <algorithm>
rpm-build d2b433
#include <cstdint>
rpm-build d2b433
rpm-build d2b433
#include <boost/format.hpp>
rpm-build d2b433
rpm-build d2b433
#include <libopenraw/consts.h>
rpm-build d2b433
#include <libopenraw/debug.h>
rpm-build d2b433
rpm-build d2b433
#include "rawdata.hpp"
rpm-build d2b433
#include "exception.hpp"
rpm-build d2b433
#include "io/stream.hpp"
rpm-build d2b433
#include "trace.hpp"
rpm-build d2b433
#include "ljpegdecompressor.hpp"
rpm-build d2b433
#include "ljpegdecompressor_priv.hpp"
rpm-build d2b433
rpm-build d2b433
namespace OpenRaw {
rpm-build d2b433
rpm-build d2b433
using namespace Debug;
rpm-build d2b433
rpm-build d2b433
namespace Internals {
rpm-build d2b433
rpm-build d2b433
rpm-build d2b433
static void SkipVariable(IO::Stream *s);
rpm-build d2b433
static uint16_t Get2bytes (IO::Stream * s);
rpm-build d2b433
static int32_t  NextMarker(IO::Stream * );
rpm-build d2b433
static void GetSoi(DecompressInfo *dcPtr);
rpm-build d2b433
static void GetApp0(IO::Stream *);
rpm-build d2b433
rpm-build d2b433
LJpegDecompressor::LJpegDecompressor(IO::Stream *stream,
rpm-build d2b433
                                     RawContainer *container)
rpm-build d2b433
    : Decompressor(stream, container),
rpm-build d2b433
      m_slices(),
rpm-build d2b433
      m_mcuROW1(NULL), m_mcuROW2(NULL),
rpm-build d2b433
      m_buf1(NULL), m_buf2(NULL),
rpm-build d2b433
      m_bitsLeft(0),
rpm-build d2b433
      m_getBuffer(0)
rpm-build d2b433
{
rpm-build d2b433
}
rpm-build d2b433
rpm-build d2b433
rpm-build d2b433
LJpegDecompressor::~LJpegDecompressor()
rpm-build d2b433
{
rpm-build d2b433
    if(m_mcuROW1) {
rpm-build d2b433
        free(m_mcuROW1);
rpm-build d2b433
    }
rpm-build d2b433
    if(m_mcuROW2) {
rpm-build d2b433
        free(m_mcuROW2);
rpm-build d2b433
    }
rpm-build d2b433
    if(m_buf1) {
rpm-build d2b433
        free(m_buf1);
rpm-build d2b433
    }
rpm-build d2b433
    if(m_buf2) {
rpm-build d2b433
        free(m_buf2);
rpm-build d2b433
    }
rpm-build d2b433
}
rpm-build d2b433
		
rpm-build d2b433
rpm-build d2b433
void LJpegDecompressor::setSlices(const std::vector<uint16_t> & slices)
rpm-build d2b433
{
rpm-build d2b433
    uint16_t n = slices[0];
rpm-build d2b433
    m_slices.resize(n + 1);
rpm-build d2b433
    for(uint16_t i = 0; i < n; i++) {
rpm-build d2b433
        m_slices[i] = slices[1];
rpm-build d2b433
    }
rpm-build d2b433
    m_slices[n] = slices[2];
rpm-build d2b433
}
rpm-build d2b433
		
rpm-build d2b433
rpm-build d2b433
rpm-build d2b433
		
rpm-build d2b433
static uint32_t bitMask[] = {  0xffffffff, 0x7fffffff, 
rpm-build d2b433
                               0x3fffffff, 0x1fffffff,
rpm-build d2b433
                               0x0fffffff, 0x07ffffff, 
rpm-build d2b433
                               0x03ffffff, 0x01ffffff,
rpm-build d2b433
                               0x00ffffff, 0x007fffff, 
rpm-build d2b433
                               0x003fffff, 0x001fffff,
rpm-build d2b433
                               0x000fffff, 0x0007ffff, 
rpm-build d2b433
                               0x0003ffff, 0x0001ffff,
rpm-build d2b433
                               0x0000ffff, 0x00007fff, 
rpm-build d2b433
                               0x00003fff, 0x00001fff,
rpm-build d2b433
                               0x00000fff, 0x000007ff, 
rpm-build d2b433
                               0x000003ff, 0x000001ff,
rpm-build d2b433
                               0x000000ff, 0x0000007f, 
rpm-build d2b433
                               0x0000003f, 0x0000001f,
rpm-build d2b433
                               0x0000000f, 0x00000007, 
rpm-build d2b433
                               0x00000003, 0x00000001};
rpm-build d2b433
rpm-build d2b433
void FixHuffTbl (HuffmanTable *htbl);
rpm-build d2b433
rpm-build d2b433
rpm-build d2b433
/*
rpm-build d2b433
 *--------------------------------------------------------------
rpm-build d2b433
 *
rpm-build d2b433
 * FixHuffTbl --
rpm-build d2b433
 *
rpm-build d2b433
 *      Compute derived values for a Huffman table one the DHT marker
rpm-build d2b433
 *      has been processed.  This generates both the encoding and
rpm-build d2b433
 *      decoding tables.
rpm-build d2b433
 *
rpm-build d2b433
 * Results:
rpm-build d2b433
 *      None.
rpm-build d2b433
 *
rpm-build d2b433
 * Side effects:
rpm-build d2b433
 *      None.
rpm-build d2b433
 *
rpm-build d2b433
 *--------------------------------------------------------------
rpm-build d2b433
 */
rpm-build d2b433
void
rpm-build d2b433
FixHuffTbl (HuffmanTable *htbl)
rpm-build d2b433
{
rpm-build d2b433
    int32_t p, i, l, lastp, si;
rpm-build d2b433
    char huffsize[257];
rpm-build d2b433
    uint16_t huffcode[257];
rpm-build d2b433
    uint16_t code;
rpm-build d2b433
    int32_t size;
rpm-build d2b433
    int32_t value, ll, ul;
rpm-build d2b433
			
rpm-build d2b433
    /*
rpm-build d2b433
     * Figure C.1: make table of Huffman code length for each symbol
rpm-build d2b433
     * Note that this is in code-length order.
rpm-build d2b433
     */
rpm-build d2b433
    p = 0;
rpm-build d2b433
    for (l = 1; l <= 16; l++) {
rpm-build d2b433
        for (i = 1; i <= (int)htbl->bits[l]; i++)
rpm-build d2b433
            huffsize[p++] = (char)l;
rpm-build d2b433
    }
rpm-build d2b433
    huffsize[p] = 0;
rpm-build d2b433
    lastp = p;
rpm-build d2b433
			
rpm-build d2b433
			
rpm-build d2b433
    /*
rpm-build d2b433
     * Figure C.2: generate the codes themselves
rpm-build d2b433
     * Note that this is in code-length order.
rpm-build d2b433
     */
rpm-build d2b433
    code = 0;
rpm-build d2b433
    si = huffsize[0];
rpm-build d2b433
    p = 0;
rpm-build d2b433
    while (huffsize[p]) {
rpm-build d2b433
        while (((int)huffsize[p]) == si) {
rpm-build d2b433
            huffcode[p++] = code;
rpm-build d2b433
            code++;
rpm-build d2b433
        }
rpm-build d2b433
        code <<= 1;
rpm-build d2b433
        si++;
rpm-build d2b433
    }
rpm-build d2b433
			
rpm-build d2b433
    /*
rpm-build d2b433
     * Figure C.3: generate encoding tables
rpm-build d2b433
     * These are code and size indexed by symbol value
rpm-build d2b433
     * Set any codeless symbols to have code length 0; this allows
rpm-build d2b433
     * EmitBits to detect any attempt to emit such symbols.
rpm-build d2b433
     */
rpm-build d2b433
    memset(htbl->ehufsi, 0, sizeof(htbl->ehufsi));
rpm-build d2b433
			
rpm-build d2b433
    for (p = 0; p < lastp; p++) {
rpm-build d2b433
        htbl->ehufco[htbl->huffval[p]] = huffcode[p];
rpm-build d2b433
        htbl->ehufsi[htbl->huffval[p]] = huffsize[p];
rpm-build d2b433
    }
rpm-build d2b433
			
rpm-build d2b433
    /*
rpm-build d2b433
     * Figure F.15: generate decoding tables
rpm-build d2b433
     */
rpm-build d2b433
    p = 0;
rpm-build d2b433
    for (l = 1; l <= 16; l++) {
rpm-build d2b433
        if (htbl->bits[l]) {
rpm-build d2b433
            htbl->valptr[l] = p;
rpm-build d2b433
            htbl->mincode[l] = huffcode[p];
rpm-build d2b433
            p += htbl->bits[l];
rpm-build d2b433
            htbl->maxcode[l] = huffcode[p - 1];
rpm-build d2b433
        } else {
rpm-build d2b433
            htbl->maxcode[l] = -1;
rpm-build d2b433
        }
rpm-build d2b433
    }
rpm-build d2b433
			
rpm-build d2b433
    /*
rpm-build d2b433
     * We put in this value to ensure HuffDecode terminates.
rpm-build d2b433
     */
rpm-build d2b433
    htbl->maxcode[17] = 0xFFFFFL;
rpm-build d2b433
			
rpm-build d2b433
    /*
rpm-build d2b433
     * Build the numbits, value lookup tables.
rpm-build d2b433
     * These table allow us to gather 8 bits from the bits stream,
rpm-build d2b433
     * and immediately lookup the size and value of the huffman codes.
rpm-build d2b433
     * If size is zero, it means that more than 8 bits are in the huffman
rpm-build d2b433
     * code (this happens about 3-4% of the time).
rpm-build d2b433
     */
rpm-build d2b433
    bzero (htbl->numbits, sizeof(htbl->numbits));
rpm-build d2b433
    for (p=0; p
rpm-build d2b433
        size = huffsize[p];
rpm-build d2b433
        if (size <= 8) {
rpm-build d2b433
            value = htbl->huffval[p];
rpm-build d2b433
            code = huffcode[p];
rpm-build d2b433
            ll = code << (8-size);
rpm-build d2b433
            if (size < 8) {
rpm-build d2b433
                ul = ll | bitMask[24+size];
rpm-build d2b433
            } else {
rpm-build d2b433
                ul = ll;
rpm-build d2b433
            }
rpm-build d2b433
            for (i=ll; i<=ul; i++) {
rpm-build d2b433
                htbl->numbits[i] = size;
rpm-build d2b433
                htbl->value[i] = value;
rpm-build d2b433
            }
rpm-build d2b433
        }
rpm-build d2b433
    }
rpm-build d2b433
}
rpm-build d2b433
rpm-build d2b433
rpm-build d2b433
#define RST0    0xD0	/* RST0 marker code */
rpm-build d2b433
rpm-build d2b433
rpm-build d2b433
#if 0
rpm-build d2b433
/*
rpm-build d2b433
 * The following variables keep track of the input buffer
rpm-build d2b433
 * for the JPEG data, which is read by ReadJpegData.
rpm-build d2b433
 */
rpm-build d2b433
uint8_t inputBuffer[JPEG_BUF_SIZE]; /* Input buffer for JPEG data */
rpm-build d2b433
int numInputBytes;		/* The total number of bytes in inputBuffer */
rpm-build d2b433
int maxInputBytes;		/* Size of inputBuffer */
rpm-build d2b433
int inputBufferOffset;		/* Offset of current byte */
rpm-build d2b433
#endif
rpm-build d2b433
rpm-build d2b433
rpm-build d2b433
/*
rpm-build d2b433
 * Code for extracting the next N bits from the input stream.
rpm-build d2b433
 * (N never exceeds 15 for JPEG data.)
rpm-build d2b433
 * This needs to go as fast as possible!
rpm-build d2b433
 *
rpm-build d2b433
 * We read source bytes into getBuffer and dole out bits as needed.
rpm-build d2b433
 * If getBuffer already contains enough bits, they are fetched in-line
rpm-build d2b433
 * by the macros get_bits() and get_bit().  When there aren't enough bits,
rpm-build d2b433
 * fillBitBuffer is called; it will attempt to fill getBuffer to the
rpm-build d2b433
 * "high water mark", then extract the desired number of bits.  The idea,
rpm-build d2b433
 * of course, is to minimize the function-call overhead cost of entering
rpm-build d2b433
 * fillBitBuffer.
rpm-build d2b433
 * On most machines MIN_GET_BITS should be 25 to allow the full 32-bit width
rpm-build d2b433
 * of getBuffer to be used.  (On machines with wider words, an even larger
rpm-build d2b433
 * buffer could be used.)  
rpm-build d2b433
 */
rpm-build d2b433
rpm-build d2b433
#define BITS_PER_LONG	(8*sizeof(int32_t))
rpm-build d2b433
#define MIN_GET_BITS  (BITS_PER_LONG-7)	   /* max value for long getBuffer */
rpm-build d2b433
		
rpm-build d2b433
/*
rpm-build d2b433
 * bmask[n] is mask for n rightmost bits
rpm-build d2b433
 */
rpm-build d2b433
static int32_t bmask[] = {0x0000,
rpm-build d2b433
                          0x0001, 0x0003, 0x0007, 0x000F,
rpm-build d2b433
                          0x001F, 0x003F, 0x007F, 0x00FF,
rpm-build d2b433
                          0x01FF, 0x03FF, 0x07FF, 0x0FFF,
rpm-build d2b433
                          0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF};
rpm-build d2b433
		
rpm-build d2b433
rpm-build d2b433
/*
rpm-build d2b433
 * Lossless JPEG specifies data precision to be from 2 to 16 bits/sample.
rpm-build d2b433
 */ 
rpm-build d2b433
#define MinPrecisionBits 2
rpm-build d2b433
#define MaxPrecisionBits 16
rpm-build d2b433
rpm-build d2b433
rpm-build d2b433
/*
rpm-build d2b433
 *--------------------------------------------------------------
rpm-build d2b433
 *
rpm-build d2b433
 * DecoderStructInit --
rpm-build d2b433
 *
rpm-build d2b433
 *	Initalize the rest of the fields in the decompression
rpm-build d2b433
 *	structure.
rpm-build d2b433
 *
rpm-build d2b433
 * Results:
rpm-build d2b433
 *	None.
rpm-build d2b433
 *
rpm-build d2b433
 * Side effects:
rpm-build d2b433
 *	None.
rpm-build d2b433
 *
rpm-build d2b433
 *--------------------------------------------------------------
rpm-build d2b433
 */
rpm-build d2b433
void
rpm-build d2b433
LJpegDecompressor::DecoderStructInit (DecompressInfo *dcPtr)
rpm-build d2b433
    noexcept(false)
rpm-build d2b433
{
rpm-build d2b433
    int16_t ci,i;
rpm-build d2b433
    JpegComponentInfo *compPtr;
rpm-build d2b433
    int32_t mcuSize;
rpm-build d2b433
rpm-build d2b433
    /*
rpm-build d2b433
     * Check sampling factor validity.
rpm-build d2b433
     */
rpm-build d2b433
    for (ci = 0; ci < dcPtr->numComponents; ci++) {
rpm-build d2b433
        compPtr = &dcPtr->compInfo[ci];
rpm-build d2b433
        if ((compPtr->hSampFactor != 1) || (compPtr->vSampFactor != 1)) {
rpm-build d2b433
            throw DecodingException("Error: Downsampling is not supported.\n");
rpm-build d2b433
        }
rpm-build d2b433
    }
rpm-build d2b433
rpm-build d2b433
    /*
rpm-build d2b433
     * Prepare array describing MCU composition
rpm-build d2b433
     */
rpm-build d2b433
    if (dcPtr->compsInScan == 1) {
rpm-build d2b433
        dcPtr->MCUmembership[0] = 0;
rpm-build d2b433
    } else {
rpm-build d2b433
        if (dcPtr->compsInScan > 4) {
rpm-build d2b433
            throw DecodingException("Too many components for interleaved scan");
rpm-build d2b433
        }
rpm-build d2b433
rpm-build d2b433
        for (ci = 0; ci < dcPtr->compsInScan; ci++) {
rpm-build d2b433
            dcPtr->MCUmembership[ci] = ci;
rpm-build d2b433
        }
rpm-build d2b433
    }
rpm-build d2b433
rpm-build d2b433
    /*
rpm-build d2b433
     * Initialize mucROW1 and mcuROW2 which buffer two rows of
rpm-build d2b433
     * pixels for predictor calculation.
rpm-build d2b433
     */
rpm-build d2b433
rpm-build d2b433
    if ((m_mcuROW1 = (MCU *)malloc(dcPtr->imageWidth*sizeof(MCU)))==NULL) {
rpm-build d2b433
        throw DecodingException("Not enough memory for mcuROW1\n");
rpm-build d2b433
    }
rpm-build d2b433
    if ((m_mcuROW2 = (MCU *)malloc(dcPtr->imageWidth*sizeof(MCU)))==NULL) {
rpm-build d2b433
        throw DecodingException("Not enough memory for mcuROW2\n");
rpm-build d2b433
    }
rpm-build d2b433
rpm-build d2b433
    mcuSize=dcPtr->compsInScan * sizeof(ComponentType);
rpm-build d2b433
    if ((m_buf1 = (char *)malloc(dcPtr->imageWidth*mcuSize))==NULL) {
rpm-build d2b433
        throw DecodingException("Not enough memory for buf1\n");
rpm-build d2b433
    }
rpm-build d2b433
    if ((m_buf2 = (char *)malloc(dcPtr->imageWidth*mcuSize))==NULL) {
rpm-build d2b433
        throw DecodingException("Not enough memory for buf2\n");
rpm-build d2b433
    }
rpm-build d2b433
rpm-build d2b433
    for (i=0;i<dcPtr->imageWidth;i++) {
rpm-build d2b433
        m_mcuROW1[i]=(MCU)(m_buf1+i*mcuSize);
rpm-build d2b433
        m_mcuROW2[i]=(MCU)(m_buf2+i*mcuSize);
rpm-build d2b433
    }
rpm-build d2b433
}
rpm-build d2b433
rpm-build d2b433
rpm-build d2b433
/*
rpm-build d2b433
 *--------------------------------------------------------------
rpm-build d2b433
 *
rpm-build d2b433
 * fillBitBuffer --
rpm-build d2b433
 *
rpm-build d2b433
 *	Load up the bit buffer with at least nbits
rpm-build d2b433
 *	Process any stuffed bytes at this time.
rpm-build d2b433
 *
rpm-build d2b433
 * Results:
rpm-build d2b433
 *	None
rpm-build d2b433
 *
rpm-build d2b433
 * Side effects:
rpm-build d2b433
 *	The bitwise global variables are updated.
rpm-build d2b433
 *
rpm-build d2b433
 *--------------------------------------------------------------
rpm-build d2b433
 */
rpm-build d2b433
void
rpm-build d2b433
LJpegDecompressor::fillBitBuffer (IO::Stream * s,uint16_t nbits)
rpm-build d2b433
{
rpm-build d2b433
    uint8_t c, c2;
rpm-build d2b433
			
rpm-build d2b433
    while (m_bitsLeft < MIN_GET_BITS) {
rpm-build d2b433
        c = s->readByte();
rpm-build d2b433
				
rpm-build d2b433
        /*
rpm-build d2b433
         * If it's 0xFF, check and discard stuffed zero byte
rpm-build d2b433
         */
rpm-build d2b433
        if (c == 0xFF) {
rpm-build d2b433
            c2 = s->readByte();
rpm-build d2b433
					
rpm-build d2b433
            if (c2 != 0) {
rpm-build d2b433
						
rpm-build d2b433
                /*
rpm-build d2b433
                 * Oops, it's actually a marker indicating end of
rpm-build d2b433
                 * compressed data.  Better put it back for use later.
rpm-build d2b433
                 */
rpm-build d2b433
                s->seek(-2, SEEK_CUR);
rpm-build d2b433
						
rpm-build d2b433
                /*
rpm-build d2b433
                 * There should be enough bits still left in the data
rpm-build d2b433
                 * segment; if so, just break out of the while loop.
rpm-build d2b433
                 */
rpm-build d2b433
                if (m_bitsLeft >= nbits)
rpm-build d2b433
                    break;
rpm-build d2b433
						
rpm-build d2b433
                /*
rpm-build d2b433
                 * Uh-oh.  Corrupted data: stuff zeroes into the data
rpm-build d2b433
                 * stream, since this sometimes occurs when we are on the
rpm-build d2b433
                 * last show_bits(8) during decoding of the Huffman
rpm-build d2b433
                 * segment.
rpm-build d2b433
                 */
rpm-build d2b433
                c = 0;
rpm-build d2b433
            }
rpm-build d2b433
        }
rpm-build d2b433
        /*
rpm-build d2b433
         * OK, load c into getBuffer
rpm-build d2b433
         */
rpm-build d2b433
        m_getBuffer = (m_getBuffer << 8) | c;
rpm-build d2b433
        m_bitsLeft += 8;
rpm-build d2b433
    }
rpm-build d2b433
}
rpm-build d2b433
rpm-build d2b433
rpm-build d2b433
rpm-build d2b433
inline int32_t LJpegDecompressor::QuickPredict(int32_t col, int16_t curComp,
rpm-build d2b433
                                               MCU *curRowBuf, 
rpm-build d2b433
                                               MCU *prevRowBuf,
rpm-build d2b433
                                               int32_t psv)
rpm-build d2b433
{
rpm-build d2b433
    int32_t left,upper,diag,leftcol;
rpm-build d2b433
    int32_t predictor;
rpm-build d2b433
rpm-build d2b433
    leftcol=col-1;
rpm-build d2b433
    upper=prevRowBuf[col][curComp];
rpm-build d2b433
    left=curRowBuf[leftcol][curComp];
rpm-build d2b433
    diag=prevRowBuf[leftcol][curComp];
rpm-build d2b433
	
rpm-build d2b433
    /*
rpm-build d2b433
     * All predictor are calculated according to psv.
rpm-build d2b433
     */
rpm-build d2b433
    switch (psv) {
rpm-build d2b433
    case 0:
rpm-build d2b433
        predictor = 0;
rpm-build d2b433
        break;
rpm-build d2b433
    case 1:
rpm-build d2b433
        predictor = left;
rpm-build d2b433
        break;
rpm-build d2b433
    case 2:
rpm-build d2b433
        predictor = upper;
rpm-build d2b433
        break;
rpm-build d2b433
    case 3:
rpm-build d2b433
        predictor = diag;
rpm-build d2b433
        break;
rpm-build d2b433
    case 4:
rpm-build d2b433
        predictor = left+upper-diag;
rpm-build d2b433
        break;
rpm-build d2b433
    case 5:
rpm-build d2b433
        predictor = left+((upper-diag)>>1);
rpm-build d2b433
        break;
rpm-build d2b433
    case 6:
rpm-build d2b433
        predictor = upper+((left-diag)>>1);
rpm-build d2b433
        break;
rpm-build d2b433
    case 7:
rpm-build d2b433
        predictor = (left+upper)>>1;
rpm-build d2b433
        break;
rpm-build d2b433
    default:
rpm-build d2b433
        LOGWARN("Warning: Undefined PSV\n");
rpm-build d2b433
        predictor = 0;
rpm-build d2b433
    }
rpm-build d2b433
    return predictor;
rpm-build d2b433
}
rpm-build d2b433
rpm-build d2b433
inline
rpm-build d2b433
int32_t LJpegDecompressor::show_bits8(IO::Stream * s)
rpm-build d2b433
{
rpm-build d2b433
    if (m_bitsLeft < 8) {
rpm-build d2b433
        fillBitBuffer(s, 8);
rpm-build d2b433
    }
rpm-build d2b433
    return (m_getBuffer >> (m_bitsLeft-8)) & 0xff;
rpm-build d2b433
}
rpm-build d2b433
rpm-build d2b433
inline
rpm-build d2b433
void LJpegDecompressor::flush_bits(uint16_t nbits)
rpm-build d2b433
{
rpm-build d2b433
    m_bitsLeft -= (nbits);
rpm-build d2b433
}
rpm-build d2b433
rpm-build d2b433
inline
rpm-build d2b433
int32_t LJpegDecompressor::get_bits(uint16_t nbits)
rpm-build d2b433
{
rpm-build d2b433
    if (m_bitsLeft < nbits) 
rpm-build d2b433
        fillBitBuffer(m_stream, nbits);
rpm-build d2b433
    return ((m_getBuffer >> (m_bitsLeft -= (nbits)))) & bmask[nbits];
rpm-build d2b433
}
rpm-build d2b433
		
rpm-build d2b433
inline
rpm-build d2b433
int32_t LJpegDecompressor::get_bit() 
rpm-build d2b433
{
rpm-build d2b433
    if (!m_bitsLeft) 
rpm-build d2b433
        fillBitBuffer(m_stream, 1);
rpm-build d2b433
    return (m_getBuffer >> (--m_bitsLeft)) & 1;
rpm-build d2b433
}
rpm-build d2b433
rpm-build d2b433
rpm-build d2b433
inline
rpm-build d2b433
int32_t LJpegDecompressor::readBits(IO::Stream * s, uint16_t nbits)
rpm-build d2b433
{
rpm-build d2b433
    if (m_bitsLeft < nbits) {
rpm-build d2b433
        fillBitBuffer(s, nbits);
rpm-build d2b433
    }
rpm-build d2b433
    return ((m_getBuffer >> (m_bitsLeft -= (nbits)))) & bmask[nbits];
rpm-build d2b433
}
rpm-build d2b433
rpm-build d2b433
rpm-build d2b433
rpm-build d2b433
/*
rpm-build d2b433
 *--------------------------------------------------------------
rpm-build d2b433
 *
rpm-build d2b433
 * PmPutRow --
rpm-build d2b433
 *
rpm-build d2b433
 *      Output one row of pixels stored in RowBuf.
rpm-build d2b433
 *
rpm-build d2b433
 * Results:
rpm-build d2b433
 *      None
rpm-build d2b433
 *
rpm-build d2b433
 * Side effects:
rpm-build d2b433
 *      One row of pixels are write to file pointed by outFile.
rpm-build d2b433
 *
rpm-build d2b433
 *--------------------------------------------------------------
rpm-build d2b433
 */
rpm-build d2b433
inline void
rpm-build d2b433
LJpegDecompressor::PmPutRow(MCU* RowBuf, int32_t numComp, int32_t numCol, int32_t Pt)
rpm-build d2b433
{
rpm-build d2b433
    // TODO this might be wrong in 8 bits...
rpm-build d2b433
    // original code was using putc which *i think* was a problem for
rpm-build d2b433
    // 16bpp
rpm-build d2b433
    int32_t comp;
rpm-build d2b433
    int32_t col;
rpm-build d2b433
    uint16_t v;
rpm-build d2b433
rpm-build d2b433
    for (col = 0; col < numCol; col++) {
rpm-build d2b433
        for (comp = 0; comp < numComp; comp++) {
rpm-build d2b433
            v = RowBuf[col][comp]<
rpm-build d2b433
            m_output->append(v);
rpm-build d2b433
        }
rpm-build d2b433
    }
rpm-build d2b433
//			m_output->nextRow();
rpm-build d2b433
}
rpm-build d2b433
rpm-build d2b433
/*
rpm-build d2b433
 *--------------------------------------------------------------
rpm-build d2b433
 *
rpm-build d2b433
 * HuffDecode --
rpm-build d2b433
 *
rpm-build d2b433
 *	Taken from Figure F.16: extract next coded symbol from
rpm-build d2b433
 *	input stream.  This should becode a macro.
rpm-build d2b433
 *
rpm-build d2b433
 * Results:
rpm-build d2b433
 *	Next coded symbol
rpm-build d2b433
 *
rpm-build d2b433
 * Side effects:
rpm-build d2b433
 *	Bitstream is parsed.
rpm-build d2b433
 *
rpm-build d2b433
 *--------------------------------------------------------------
rpm-build d2b433
 */
rpm-build d2b433
inline int32_t 
rpm-build d2b433
LJpegDecompressor::HuffDecode(HuffmanTable *htbl)
rpm-build d2b433
{
rpm-build d2b433
    int32_t rv;
rpm-build d2b433
    int32_t l, temp;
rpm-build d2b433
    int32_t code;
rpm-build d2b433
rpm-build d2b433
    /*
rpm-build d2b433
     * If the huffman code is less than 8 bits, we can use the fast
rpm-build d2b433
     * table lookup to get its value.  It's more than 8 bits about
rpm-build d2b433
     * 3-4% of the time.
rpm-build d2b433
     */
rpm-build d2b433
    code = show_bits8(m_stream);
rpm-build d2b433
    if (htbl->numbits[code]) {
rpm-build d2b433
        flush_bits(htbl->numbits[code]);
rpm-build d2b433
        rv=htbl->value[code];
rpm-build d2b433
    }  else {
rpm-build d2b433
        flush_bits(8);
rpm-build d2b433
        l = 8;
rpm-build d2b433
        while (code > htbl->maxcode[l]) {
rpm-build d2b433
            temp = get_bit();
rpm-build d2b433
            code = (code << 1) | temp;
rpm-build d2b433
            l++;
rpm-build d2b433
        }
rpm-build d2b433
rpm-build d2b433
        /*
rpm-build d2b433
         * With garbage input we may reach the sentinel value l = 17.
rpm-build d2b433
         */
rpm-build d2b433
rpm-build d2b433
        if (l > 16) {
rpm-build d2b433
            //LOGWARN("Corrupt JPEG data: bad Huffman code %d\n", l);
rpm-build d2b433
            rv = 0;		/* fake a zero as the safest result */
rpm-build d2b433
        } else {
rpm-build d2b433
            rv = htbl->huffval[htbl->valptr[l] +
rpm-build d2b433
                               ((int)(code - htbl->mincode[l]))];
rpm-build d2b433
        }
rpm-build d2b433
    }
rpm-build d2b433
    return rv;
rpm-build d2b433
}
rpm-build d2b433
rpm-build d2b433
/*
rpm-build d2b433
 *--------------------------------------------------------------
rpm-build d2b433
 *
rpm-build d2b433
 * HuffExtend --
rpm-build d2b433
 *
rpm-build d2b433
 *	Code and table for Figure F.12: extend sign bit
rpm-build d2b433
 *
rpm-build d2b433
 * Results:
rpm-build d2b433
 *	The extended value.
rpm-build d2b433
 *
rpm-build d2b433
 * Side effects:
rpm-build d2b433
 *	None.
rpm-build d2b433
 *
rpm-build d2b433
 *--------------------------------------------------------------
rpm-build d2b433
 */
rpm-build d2b433
static const int32_t extendTest[16] =	/* entry n is 2**(n-1) */
rpm-build d2b433
{0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
rpm-build d2b433
 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000};
rpm-build d2b433
rpm-build d2b433
// we can't bitshift -1. So we use 0xffffffff as a value.
rpm-build d2b433
// gcc complain about it otherwise.
rpm-build d2b433
#define EXTEND(n) (int32_t)(0xffffffff << n) + 1
rpm-build d2b433
static const int32_t extendOffset[16] =	/* entry n is (-1 << n) + 1 */
rpm-build d2b433
{
rpm-build d2b433
    0, EXTEND(1), EXTEND(2), EXTEND(3),
rpm-build d2b433
    EXTEND(4), EXTEND(5), EXTEND(6), EXTEND(7),
rpm-build d2b433
    EXTEND(8), EXTEND(9), EXTEND(10), EXTEND(11),
rpm-build d2b433
    EXTEND(12), EXTEND(13), EXTEND(14), EXTEND(15)
rpm-build d2b433
};
rpm-build d2b433
rpm-build d2b433
inline
rpm-build d2b433
void HuffExtend(int32_t & x, int32_t s) noexcept
rpm-build d2b433
{
rpm-build d2b433
    if ((x) < extendTest[s]) {
rpm-build d2b433
        (x) += extendOffset[s];
rpm-build d2b433
    }
rpm-build d2b433
}
rpm-build d2b433
rpm-build d2b433
/*
rpm-build d2b433
 *--------------------------------------------------------------
rpm-build d2b433
 *
rpm-build d2b433
 * HuffDecoderInit --
rpm-build d2b433
 *
rpm-build d2b433
 *	Initialize for a Huffman-compressed scan.
rpm-build d2b433
 *	This is invoked after reading the SOS marker.
rpm-build d2b433
 *
rpm-build d2b433
 * Results:
rpm-build d2b433
 *	None
rpm-build d2b433
 *
rpm-build d2b433
 * Side effects:
rpm-build d2b433
 *	None.
rpm-build d2b433
 *
rpm-build d2b433
 *--------------------------------------------------------------
rpm-build d2b433
 */
rpm-build d2b433
void
rpm-build d2b433
LJpegDecompressor::HuffDecoderInit (DecompressInfo *dcPtr)
rpm-build d2b433
    noexcept(false)
rpm-build d2b433
{
rpm-build d2b433
    int16_t ci;
rpm-build d2b433
    JpegComponentInfo *compptr;
rpm-build d2b433
rpm-build d2b433
    /*
rpm-build d2b433
     * Initialize static variables
rpm-build d2b433
     */
rpm-build d2b433
    m_bitsLeft = 0;
rpm-build d2b433
rpm-build d2b433
    for (ci = 0; ci < dcPtr->compsInScan; ci++) {
rpm-build d2b433
        compptr = dcPtr->curCompInfo[ci];
rpm-build d2b433
        /*
rpm-build d2b433
         * Make sure requested tables are present
rpm-build d2b433
         */
rpm-build d2b433
        if (dcPtr->dcHuffTblPtrs[compptr->dcTblNo] == NULL) { 
rpm-build d2b433
            throw DecodingException("Error: Use of undefined Huffman table\n");
rpm-build d2b433
        }
rpm-build d2b433
rpm-build d2b433
        /*
rpm-build d2b433
         * Compute derived values for Huffman tables.
rpm-build d2b433
         * We may do this more than once for same table, but it's not a
rpm-build d2b433
         * big deal
rpm-build d2b433
         */
rpm-build d2b433
        FixHuffTbl (dcPtr->dcHuffTblPtrs[compptr->dcTblNo]);
rpm-build d2b433
    }
rpm-build d2b433
rpm-build d2b433
    /*
rpm-build d2b433
     * Initialize restart stuff
rpm-build d2b433
     */
rpm-build d2b433
    dcPtr->restartInRows = (dcPtr->restartInterval)/(dcPtr->imageWidth);
rpm-build d2b433
    dcPtr->restartRowsToGo = dcPtr->restartInRows;
rpm-build d2b433
    dcPtr->nextRestartNum = 0;
rpm-build d2b433
}
rpm-build d2b433
rpm-build d2b433
/*
rpm-build d2b433
 *--------------------------------------------------------------
rpm-build d2b433
 *
rpm-build d2b433
 * ProcessRestart --
rpm-build d2b433
 *
rpm-build d2b433
 *	Check for a restart marker & resynchronize decoder.
rpm-build d2b433
 *
rpm-build d2b433
 * Results:
rpm-build d2b433
 *	None.
rpm-build d2b433
 *
rpm-build d2b433
 * Side effects:
rpm-build d2b433
 *	BitStream is parsed, bit buffer is reset, etc.
rpm-build d2b433
 *
rpm-build d2b433
 *--------------------------------------------------------------
rpm-build d2b433
 */
rpm-build d2b433
void
rpm-build d2b433
LJpegDecompressor::ProcessRestart (DecompressInfo *dcPtr)
rpm-build d2b433
    noexcept(false)
rpm-build d2b433
{
rpm-build d2b433
    int32_t c, nbytes;
rpm-build d2b433
rpm-build d2b433
    /*
rpm-build d2b433
     * Throw away any unused bits remaining in bit buffer
rpm-build d2b433
     */
rpm-build d2b433
    nbytes = m_bitsLeft / 8;
rpm-build d2b433
    m_bitsLeft = 0;
rpm-build d2b433
rpm-build d2b433
    /*
rpm-build d2b433
     * Scan for next JPEG marker
rpm-build d2b433
     */
rpm-build d2b433
    do {
rpm-build d2b433
        do {			/* skip any non-FF bytes */
rpm-build d2b433
            nbytes++;
rpm-build d2b433
            c = m_stream->readByte();
rpm-build d2b433
        } while (c != 0xFF);
rpm-build d2b433
        do {			/* skip any duplicate FFs */
rpm-build d2b433
            /*
rpm-build d2b433
             * we don't increment nbytes here since extra FFs are legal
rpm-build d2b433
             */
rpm-build d2b433
            c = m_stream->readByte();
rpm-build d2b433
        } while (c == 0xFF);
rpm-build d2b433
    } while (c == 0);		/* repeat if it was a stuffed FF/00 */
rpm-build d2b433
rpm-build d2b433
    if (c != (RST0 + dcPtr->nextRestartNum)) {
rpm-build d2b433
rpm-build d2b433
        /*
rpm-build d2b433
         * Uh-oh, the restart markers have been messed up too.
rpm-build d2b433
         * Just bail out.
rpm-build d2b433
         */
rpm-build d2b433
        throw DecodingException("Error: Corrupt JPEG data. "
rpm-build d2b433
                                "Aborting decoding...\n");
rpm-build d2b433
    }
rpm-build d2b433
rpm-build d2b433
    /*
rpm-build d2b433
     * Update restart state
rpm-build d2b433
     */
rpm-build d2b433
    dcPtr->restartRowsToGo = dcPtr->restartInRows;
rpm-build d2b433
    dcPtr->nextRestartNum = (dcPtr->nextRestartNum + 1) & 7;
rpm-build d2b433
}
rpm-build d2b433
rpm-build d2b433
/*
rpm-build d2b433
 *--------------------------------------------------------------
rpm-build d2b433
 *
rpm-build d2b433
 * DecodeFirstRow --
rpm-build d2b433
 *
rpm-build d2b433
 *	Decode the first raster line of samples at the start of 
rpm-build d2b433
 *      the scan and at the beginning of each restart interval.
rpm-build d2b433
 *	This includes modifying the component value so the real
rpm-build d2b433
 *      value, not the difference is returned.
rpm-build d2b433
 *
rpm-build d2b433
 * Results:
rpm-build d2b433
 *	None.
rpm-build d2b433
 *
rpm-build d2b433
 * Side effects:
rpm-build d2b433
 *	Bitstream is parsed.
rpm-build d2b433
 *
rpm-build d2b433
 *--------------------------------------------------------------
rpm-build d2b433
 */
rpm-build d2b433
void LJpegDecompressor::DecodeFirstRow(DecompressInfo *dcPtr,
rpm-build d2b433
                                       MCU *curRowBuf)
rpm-build d2b433
{
rpm-build d2b433
    uint16_t curComp,ci;
rpm-build d2b433
    int32_t s,col,compsInScan,numCOL;
rpm-build d2b433
    JpegComponentInfo *compptr;
rpm-build d2b433
    int32_t Pr,Pt,d;
rpm-build d2b433
    HuffmanTable *dctbl;
rpm-build d2b433
rpm-build d2b433
    Pr=dcPtr->dataPrecision;
rpm-build d2b433
    Pt=dcPtr->Pt;
rpm-build d2b433
    compsInScan=dcPtr->compsInScan;
rpm-build d2b433
    numCOL=dcPtr->imageWidth;
rpm-build d2b433
rpm-build d2b433
    /*
rpm-build d2b433
     * the start of the scan or at the beginning of restart interval.
rpm-build d2b433
     */
rpm-build d2b433
    for (curComp = 0; curComp < compsInScan; curComp++) {
rpm-build d2b433
        ci = dcPtr->MCUmembership[curComp];
rpm-build d2b433
        compptr = dcPtr->curCompInfo[ci];
rpm-build d2b433
        dctbl = dcPtr->dcHuffTblPtrs[compptr->dcTblNo];
rpm-build d2b433
rpm-build d2b433
        /*
rpm-build d2b433
         * Section F.2.2.1: decode the difference
rpm-build d2b433
         */
rpm-build d2b433
        s = HuffDecode (dctbl);
rpm-build d2b433
        if (s) {
rpm-build d2b433
            d = get_bits(s);
rpm-build d2b433
            HuffExtend(d,s);
rpm-build d2b433
        } else {
rpm-build d2b433
            d = 0;
rpm-build d2b433
        }
rpm-build d2b433
rpm-build d2b433
        /* 
rpm-build d2b433
         * Add the predictor to the difference.
rpm-build d2b433
         */
rpm-build d2b433
        curRowBuf[0][curComp]=d+(1<<(Pr-Pt-1));
rpm-build d2b433
    }
rpm-build d2b433
rpm-build d2b433
    /*
rpm-build d2b433
     * the rest of the first row
rpm-build d2b433
     */
rpm-build d2b433
    for (col=1; col
rpm-build d2b433
        for (curComp = 0; curComp < compsInScan; curComp++) {
rpm-build d2b433
            ci = dcPtr->MCUmembership[curComp];
rpm-build d2b433
            compptr = dcPtr->curCompInfo[ci];
rpm-build d2b433
            dctbl = dcPtr->dcHuffTblPtrs[compptr->dcTblNo];
rpm-build d2b433
rpm-build d2b433
            /*
rpm-build d2b433
             * Section F.2.2.1: decode the difference
rpm-build d2b433
             */
rpm-build d2b433
            s = HuffDecode (dctbl);
rpm-build d2b433
            if (s) {
rpm-build d2b433
                d = get_bits(s);
rpm-build d2b433
                HuffExtend(d,s);
rpm-build d2b433
            } else {
rpm-build d2b433
                d = 0;
rpm-build d2b433
            }
rpm-build d2b433
rpm-build d2b433
            /* 
rpm-build d2b433
             * Add the predictor to the difference.
rpm-build d2b433
             */
rpm-build d2b433
            curRowBuf[col][curComp]=d+curRowBuf[col-1][curComp];
rpm-build d2b433
        }
rpm-build d2b433
    }
rpm-build d2b433
rpm-build d2b433
    if (dcPtr->restartInRows) {
rpm-build d2b433
        (dcPtr->restartRowsToGo)--;
rpm-build d2b433
    }
rpm-build d2b433
}
rpm-build d2b433
rpm-build d2b433
/*
rpm-build d2b433
 *--------------------------------------------------------------
rpm-build d2b433
 *
rpm-build d2b433
 * DecodeImage --
rpm-build d2b433
 *
rpm-build d2b433
 *      Decode the input stream. This includes modifying
rpm-build d2b433
 *      the component value so the real value, not the
rpm-build d2b433
 *      difference is returned.
rpm-build d2b433
 *
rpm-build d2b433
 * Results:
rpm-build d2b433
 *      None.
rpm-build d2b433
 *
rpm-build d2b433
 * Side effects:
rpm-build d2b433
 *      Bitstream is parsed.
rpm-build d2b433
 *
rpm-build d2b433
 *--------------------------------------------------------------
rpm-build d2b433
 */
rpm-build d2b433
void
rpm-build d2b433
LJpegDecompressor::DecodeImage(DecompressInfo *dcPtr)
rpm-build d2b433
{
rpm-build d2b433
    int32_t s,d,col,row;
rpm-build d2b433
    int16_t curComp, ci;
rpm-build d2b433
    HuffmanTable *dctbl;
rpm-build d2b433
    JpegComponentInfo *compptr;
rpm-build d2b433
    int32_t predictor;
rpm-build d2b433
    int32_t numCOL,numROW,compsInScan;
rpm-build d2b433
    MCU *prevRowBuf,*curRowBuf;
rpm-build d2b433
    int32_t imagewidth,Pt,psv;
rpm-build d2b433
rpm-build d2b433
    numCOL=imagewidth=dcPtr->imageWidth;
rpm-build d2b433
    numROW=dcPtr->imageHeight;
rpm-build d2b433
    compsInScan=dcPtr->compsInScan;
rpm-build d2b433
    Pt=dcPtr->Pt;
rpm-build d2b433
    psv=dcPtr->Ss;
rpm-build d2b433
    prevRowBuf=m_mcuROW2;
rpm-build d2b433
    curRowBuf=m_mcuROW1;
rpm-build d2b433
rpm-build d2b433
    /*
rpm-build d2b433
     * Decode the first row of image. Output the row and
rpm-build d2b433
     * turn this row into a previous row for later predictor
rpm-build d2b433
     * calculation.
rpm-build d2b433
     */  
rpm-build d2b433
    DecodeFirstRow(dcPtr,curRowBuf);
rpm-build d2b433
    PmPutRow(curRowBuf,compsInScan,numCOL,Pt);
rpm-build d2b433
    std::swap(prevRowBuf,curRowBuf);
rpm-build d2b433
rpm-build d2b433
    for (row=1; row
rpm-build d2b433
rpm-build d2b433
        /*
rpm-build d2b433
         * Account for restart interval, process restart marker if needed.
rpm-build d2b433
         */
rpm-build d2b433
        if (dcPtr->restartInRows) {
rpm-build d2b433
            if (dcPtr->restartRowsToGo == 0) {
rpm-build d2b433
                ProcessRestart (dcPtr);
rpm-build d2b433
            
rpm-build d2b433
                /*
rpm-build d2b433
                 * Reset predictors at restart.
rpm-build d2b433
                 */
rpm-build d2b433
                DecodeFirstRow(dcPtr,curRowBuf);
rpm-build d2b433
                PmPutRow(curRowBuf,compsInScan,numCOL,Pt);
rpm-build d2b433
                std::swap(prevRowBuf,curRowBuf);
rpm-build d2b433
                continue;
rpm-build d2b433
            }
rpm-build d2b433
            dcPtr->restartRowsToGo--;
rpm-build d2b433
        }
rpm-build d2b433
rpm-build d2b433
        /*
rpm-build d2b433
         * The upper neighbors are predictors for the first column.
rpm-build d2b433
         */
rpm-build d2b433
        for (curComp = 0; curComp < compsInScan; curComp++) {
rpm-build d2b433
            ci = dcPtr->MCUmembership[curComp];
rpm-build d2b433
            compptr = dcPtr->curCompInfo[ci];
rpm-build d2b433
            dctbl = dcPtr->dcHuffTblPtrs[compptr->dcTblNo];
rpm-build d2b433
rpm-build d2b433
            /*
rpm-build d2b433
             * Section F.2.2.1: decode the difference
rpm-build d2b433
             */
rpm-build d2b433
            s = HuffDecode (dctbl);
rpm-build d2b433
            if (s) {
rpm-build d2b433
                d = get_bits(s);
rpm-build d2b433
                HuffExtend(d,s);
rpm-build d2b433
            } else {
rpm-build d2b433
                d = 0;
rpm-build d2b433
            }
rpm-build d2b433
rpm-build d2b433
            curRowBuf[0][curComp]=d+prevRowBuf[0][curComp];
rpm-build d2b433
        }
rpm-build d2b433
rpm-build d2b433
        /*
rpm-build d2b433
         * For the rest of the column on this row, predictor
rpm-build d2b433
         * calculations are base on PSV. 
rpm-build d2b433
         */
rpm-build d2b433
        for (col=1; col
rpm-build d2b433
            for (curComp = 0; curComp < compsInScan; curComp++) {
rpm-build d2b433
                ci = dcPtr->MCUmembership[curComp];
rpm-build d2b433
                compptr = dcPtr->curCompInfo[ci];
rpm-build d2b433
                dctbl = dcPtr->dcHuffTblPtrs[compptr->dcTblNo];
rpm-build d2b433
rpm-build d2b433
                /*
rpm-build d2b433
                 * Section F.2.2.1: decode the difference
rpm-build d2b433
                 */
rpm-build d2b433
                s = HuffDecode (dctbl);
rpm-build d2b433
                if (s) {
rpm-build d2b433
                    d = get_bits(s);
rpm-build d2b433
                    HuffExtend(d,s);
rpm-build d2b433
                } else {
rpm-build d2b433
                    d = 0;
rpm-build d2b433
                }
rpm-build d2b433
                predictor = QuickPredict(col,curComp,curRowBuf,prevRowBuf,
rpm-build d2b433
                                         psv);
rpm-build d2b433
rpm-build d2b433
                curRowBuf[col][curComp]=d+predictor;
rpm-build d2b433
            }
rpm-build d2b433
        }
rpm-build d2b433
        PmPutRow(curRowBuf,compsInScan,numCOL,Pt);
rpm-build d2b433
        std::swap(prevRowBuf,curRowBuf);
rpm-build d2b433
    }
rpm-build d2b433
}
rpm-build d2b433
rpm-build d2b433
rpm-build d2b433
rpm-build d2b433
rpm-build d2b433
/*
rpm-build d2b433
 *--------------------------------------------------------------
rpm-build d2b433
 *
rpm-build d2b433
 * Get2bytes --
rpm-build d2b433
 *
rpm-build d2b433
 *	Get a 2-byte unsigned integer (e.g., a marker parameter length
rpm-build d2b433
 *	field)
rpm-build d2b433
 *
rpm-build d2b433
 * Results:
rpm-build d2b433
 *	Next two byte of input as an integer.
rpm-build d2b433
 *
rpm-build d2b433
 * Side effects:
rpm-build d2b433
 *	Bitstream is parsed.
rpm-build d2b433
 *
rpm-build d2b433
 *--------------------------------------------------------------
rpm-build d2b433
 */
rpm-build d2b433
static inline uint16_t
rpm-build d2b433
Get2bytes (IO::Stream * s)
rpm-build d2b433
{
rpm-build d2b433
    uint16_t a;
rpm-build d2b433
rpm-build d2b433
    a = s->readByte();
rpm-build d2b433
    return (a << 8) | s->readByte();
rpm-build d2b433
}
rpm-build d2b433
rpm-build d2b433
/*
rpm-build d2b433
 *--------------------------------------------------------------
rpm-build d2b433
 *
rpm-build d2b433
 * SkipVariable --
rpm-build d2b433
 *
rpm-build d2b433
 *	Skip over an unknown or uninteresting variable-length marker
rpm-build d2b433
 *
rpm-build d2b433
 * Results:
rpm-build d2b433
 *	None.
rpm-build d2b433
 *
rpm-build d2b433
 * Side effects:
rpm-build d2b433
 *	Bitstream is parsed over marker.
rpm-build d2b433
 *
rpm-build d2b433
 *
rpm-build d2b433
 *--------------------------------------------------------------
rpm-build d2b433
 */
rpm-build d2b433
static inline void SkipVariable(IO::Stream * s)
rpm-build d2b433
{
rpm-build d2b433
    int32_t length;
rpm-build d2b433
rpm-build d2b433
    length = Get2bytes(s) - 2;
rpm-build d2b433
rpm-build d2b433
    s->seek(length, SEEK_CUR);
rpm-build d2b433
}
rpm-build d2b433
rpm-build d2b433
/*
rpm-build d2b433
 *--------------------------------------------------------------
rpm-build d2b433
 *
rpm-build d2b433
 * GetDht --
rpm-build d2b433
 *
rpm-build d2b433
 *	Process a DHT marker
rpm-build d2b433
 *
rpm-build d2b433
 * Results:
rpm-build d2b433
 *	None
rpm-build d2b433
 *
rpm-build d2b433
 * Side effects:
rpm-build d2b433
 *	A huffman table is read.
rpm-build d2b433
 *	Exits on error.
rpm-build d2b433
 *
rpm-build d2b433
 *--------------------------------------------------------------
rpm-build d2b433
 */
rpm-build d2b433
void
rpm-build d2b433
LJpegDecompressor::GetDht (DecompressInfo *dcPtr)
rpm-build d2b433
    noexcept(false)
rpm-build d2b433
{
rpm-build d2b433
    int32_t length;
rpm-build d2b433
    int32_t i, index, count;
rpm-build d2b433
rpm-build d2b433
    length = Get2bytes(m_stream) - 2;
rpm-build d2b433
rpm-build d2b433
    while (length) {
rpm-build d2b433
        index = m_stream->readByte();
rpm-build d2b433
rpm-build d2b433
        if (index < 0 || index >= 4) {
rpm-build d2b433
            throw DecodingException(str(boost::format("Bogus DHT index %1%")
rpm-build d2b433
                                        % index));
rpm-build d2b433
        }
rpm-build d2b433
rpm-build d2b433
        HuffmanTable *& htblptr = dcPtr->dcHuffTblPtrs[index];
rpm-build d2b433
        if (htblptr == NULL) {
rpm-build d2b433
            htblptr = (HuffmanTable *) malloc(sizeof (HuffmanTable));
rpm-build d2b433
            if (htblptr==NULL) {
rpm-build d2b433
                throw DecodingException("Can't malloc HuffmanTable");
rpm-build d2b433
            }
rpm-build d2b433
        }
rpm-build d2b433
rpm-build d2b433
        htblptr->bits[0] = 0;
rpm-build d2b433
        count = 0;
rpm-build d2b433
        for (i = 1; i <= 16; i++) {
rpm-build d2b433
            htblptr->bits[i] = m_stream->readByte();
rpm-build d2b433
            count += htblptr->bits[i];
rpm-build d2b433
        }
rpm-build d2b433
rpm-build d2b433
        if (count > 256) {
rpm-build d2b433
            throw DecodingException("Bogus DHT counts");
rpm-build d2b433
        }
rpm-build d2b433
rpm-build d2b433
        for (i = 0; i < count; i++)
rpm-build d2b433
            htblptr->huffval[i] = m_stream->readByte();
rpm-build d2b433
rpm-build d2b433
        length -= 1 + 16 + count;
rpm-build d2b433
    }
rpm-build d2b433
}
rpm-build d2b433
rpm-build d2b433
/*
rpm-build d2b433
 *--------------------------------------------------------------
rpm-build d2b433
 *
rpm-build d2b433
 * GetDri --
rpm-build d2b433
 *
rpm-build d2b433
 *	Process a DRI marker
rpm-build d2b433
 *
rpm-build d2b433
 * Results:
rpm-build d2b433
 *	None
rpm-build d2b433
 *
rpm-build d2b433
 * Side effects:
rpm-build d2b433
 *	Exits on error.
rpm-build d2b433
 *	Bitstream is parsed.
rpm-build d2b433
 *
rpm-build d2b433
 *--------------------------------------------------------------
rpm-build d2b433
 */
rpm-build d2b433
void
rpm-build d2b433
LJpegDecompressor::GetDri(DecompressInfo *dcPtr)
rpm-build d2b433
    noexcept(false)
rpm-build d2b433
{
rpm-build d2b433
    if (Get2bytes(m_stream) != 4) {
rpm-build d2b433
        throw DecodingException("Bogus length in DRI");
rpm-build d2b433
    }
rpm-build d2b433
rpm-build d2b433
    dcPtr->restartInterval = Get2bytes(m_stream);
rpm-build d2b433
}
rpm-build d2b433
rpm-build d2b433
/*
rpm-build d2b433
 *--------------------------------------------------------------
rpm-build d2b433
 *
rpm-build d2b433
 * GetApp0 --
rpm-build d2b433
 *
rpm-build d2b433
 *	Process an APP0 marker.
rpm-build d2b433
 *
rpm-build d2b433
 * Results:
rpm-build d2b433
 *	None
rpm-build d2b433
 *
rpm-build d2b433
 * Side effects:
rpm-build d2b433
 *	Bitstream is parsed
rpm-build d2b433
 *
rpm-build d2b433
 *--------------------------------------------------------------
rpm-build d2b433
 */
rpm-build d2b433
static void	GetApp0(IO::Stream *s)
rpm-build d2b433
{
rpm-build d2b433
    int32_t length;
rpm-build d2b433
rpm-build d2b433
    length = Get2bytes(s) - 2;
rpm-build d2b433
    s->seek(length, SEEK_CUR);
rpm-build d2b433
}
rpm-build d2b433
rpm-build d2b433
/*
rpm-build d2b433
 *--------------------------------------------------------------
rpm-build d2b433
 *
rpm-build d2b433
 * GetSof --
rpm-build d2b433
 *
rpm-build d2b433
 *	Process a SOFn marker
rpm-build d2b433
 *
rpm-build d2b433
 * Results:
rpm-build d2b433
 *	None.
rpm-build d2b433
 *
rpm-build d2b433
 * Side effects:
rpm-build d2b433
 *	Bitstream is parsed
rpm-build d2b433
 *	Exits on error
rpm-build d2b433
 *	dcPtr structure is filled in
rpm-build d2b433
 *
rpm-build d2b433
 *--------------------------------------------------------------
rpm-build d2b433
 */
rpm-build d2b433
void
rpm-build d2b433
LJpegDecompressor::GetSof(DecompressInfo *dcPtr)
rpm-build d2b433
    noexcept(false)
rpm-build d2b433
{
rpm-build d2b433
    int32_t length;
rpm-build d2b433
    int16_t ci;
rpm-build d2b433
    int32_t c;
rpm-build d2b433
    JpegComponentInfo *compptr;
rpm-build d2b433
rpm-build d2b433
    length = Get2bytes(m_stream);
rpm-build d2b433
rpm-build d2b433
    dcPtr->dataPrecision = m_stream->readByte();
rpm-build d2b433
    dcPtr->imageHeight = Get2bytes(m_stream);
rpm-build d2b433
    dcPtr->imageWidth = Get2bytes(m_stream);
rpm-build d2b433
    dcPtr->numComponents = m_stream->readByte();
rpm-build d2b433
rpm-build d2b433
    /*
rpm-build d2b433
     * We don't support files in which the image height is initially
rpm-build d2b433
     * specified as 0 and is later redefined by DNL.  As long as we
rpm-build d2b433
     * have to check that, might as well have a general sanity check.
rpm-build d2b433
     */
rpm-build d2b433
    if ((dcPtr->imageHeight <= 0 ) ||
rpm-build d2b433
        (dcPtr->imageWidth <= 0) || 
rpm-build d2b433
        (dcPtr->numComponents <= 0)) {
rpm-build d2b433
        throw DecodingException("Empty JPEG image (DNL not supported)");
rpm-build d2b433
    }
rpm-build d2b433
rpm-build d2b433
    if ((dcPtr->dataPrecision
rpm-build d2b433
        (dcPtr->dataPrecision>MaxPrecisionBits)) {
rpm-build d2b433
        throw DecodingException("Unsupported JPEG data precision");
rpm-build d2b433
    }
rpm-build d2b433
rpm-build d2b433
    if (length != (dcPtr->numComponents * 3 + 8)) {
rpm-build d2b433
        throw DecodingException("Bogus SOF length");
rpm-build d2b433
    }
rpm-build d2b433
rpm-build d2b433
    dcPtr->compInfo = (JpegComponentInfo *) malloc
rpm-build d2b433
        (dcPtr->numComponents * sizeof (JpegComponentInfo));
rpm-build d2b433
rpm-build d2b433
    for (ci = 0; ci < dcPtr->numComponents; ci++) {
rpm-build d2b433
        compptr = &dcPtr->compInfo[ci];
rpm-build d2b433
        compptr->componentIndex = ci;
rpm-build d2b433
        compptr->componentId = m_stream->readByte();
rpm-build d2b433
        c = m_stream->readByte();
rpm-build d2b433
        compptr->hSampFactor = (int16_t)((c >> 4) & 15);
rpm-build d2b433
        compptr->vSampFactor = (int16_t)((c) & 15);
rpm-build d2b433
        (void) m_stream->readByte();   /* skip Tq */
rpm-build d2b433
    }
rpm-build d2b433
}
rpm-build d2b433
rpm-build d2b433
/*
rpm-build d2b433
 *--------------------------------------------------------------
rpm-build d2b433
 *
rpm-build d2b433
 * GetSos --
rpm-build d2b433
 *
rpm-build d2b433
 *	Process a SOS marker
rpm-build d2b433
 *
rpm-build d2b433
 * Results:
rpm-build d2b433
 *	None.
rpm-build d2b433
 *
rpm-build d2b433
 * Side effects:
rpm-build d2b433
 *	Bitstream is parsed.
rpm-build d2b433
 *	Exits on error.
rpm-build d2b433
 *
rpm-build d2b433
 *--------------------------------------------------------------
rpm-build d2b433
 */
rpm-build d2b433
void
rpm-build d2b433
LJpegDecompressor::GetSos (DecompressInfo *dcPtr)
rpm-build d2b433
    noexcept(false)
rpm-build d2b433
{
rpm-build d2b433
    int32_t length;
rpm-build d2b433
    int32_t i;
rpm-build d2b433
    uint16_t n, ci, c, cc;
rpm-build d2b433
    JpegComponentInfo *compptr;
rpm-build d2b433
rpm-build d2b433
    length = Get2bytes (m_stream);
rpm-build d2b433
rpm-build d2b433
    /* 
rpm-build d2b433
     * Get the number of image components.
rpm-build d2b433
     */
rpm-build d2b433
    n = m_stream->readByte();
rpm-build d2b433
    dcPtr->compsInScan = n;
rpm-build d2b433
    length -= 3;
rpm-build d2b433
rpm-build d2b433
    if (length != (n * 2 + 3) || n < 1 || n > 4) {
rpm-build d2b433
        throw DecodingException("Bogus SOS length");
rpm-build d2b433
    }
rpm-build d2b433
rpm-build d2b433
rpm-build d2b433
    for (i = 0; i < n; i++) {
rpm-build d2b433
        cc = m_stream->readByte();
rpm-build d2b433
        c = m_stream->readByte();
rpm-build d2b433
        length -= 2;
rpm-build d2b433
rpm-build d2b433
        for (ci = 0; ci < dcPtr->numComponents; ci++)
rpm-build d2b433
            if (cc == dcPtr->compInfo[ci].componentId) {
rpm-build d2b433
                break;
rpm-build d2b433
            }
rpm-build d2b433
rpm-build d2b433
        if (ci >= dcPtr->numComponents) {
rpm-build d2b433
            throw DecodingException("Invalid component number in SOS");
rpm-build d2b433
        }
rpm-build d2b433
rpm-build d2b433
        compptr = &dcPtr->compInfo[ci];
rpm-build d2b433
        dcPtr->curCompInfo[i] = compptr;
rpm-build d2b433
        compptr->dcTblNo = (c >> 4) & 15;
rpm-build d2b433
    }
rpm-build d2b433
rpm-build d2b433
    /*
rpm-build d2b433
     * Get the PSV, skip Se, and get the point transform parameter.
rpm-build d2b433
     */
rpm-build d2b433
    dcPtr->Ss = m_stream->readByte(); 
rpm-build d2b433
    (void)m_stream->readByte();
rpm-build d2b433
    c = m_stream->readByte(); 
rpm-build d2b433
    dcPtr->Pt = c & 0x0F;
rpm-build d2b433
}
rpm-build d2b433
rpm-build d2b433
/*
rpm-build d2b433
 *--------------------------------------------------------------
rpm-build d2b433
 *
rpm-build d2b433
 * GetSoi --
rpm-build d2b433
 *
rpm-build d2b433
 *	Process an SOI marker
rpm-build d2b433
 *
rpm-build d2b433
 * Results:
rpm-build d2b433
 *	None.
rpm-build d2b433
 *
rpm-build d2b433
 * Side effects:
rpm-build d2b433
 *	Bitstream is parsed.
rpm-build d2b433
 *	Exits on error.
rpm-build d2b433
 *
rpm-build d2b433
 *--------------------------------------------------------------
rpm-build d2b433
 */
rpm-build d2b433
static inline void
rpm-build d2b433
GetSoi (DecompressInfo *dcPtr)
rpm-build d2b433
{
rpm-build d2b433
rpm-build d2b433
    /*
rpm-build d2b433
     * Reset all parameters that are defined to be reset by SOI
rpm-build d2b433
     */
rpm-build d2b433
    dcPtr->restartInterval = 0;
rpm-build d2b433
}
rpm-build d2b433
rpm-build d2b433
/*
rpm-build d2b433
 *--------------------------------------------------------------
rpm-build d2b433
 *
rpm-build d2b433
 * NextMarker --
rpm-build d2b433
 *
rpm-build d2b433
 *      Find the next JPEG marker Note that the output might not
rpm-build d2b433
 *	be a valid marker code but it will never be 0 or FF
rpm-build d2b433
 *
rpm-build d2b433
 * Results:
rpm-build d2b433
 *	The marker found.
rpm-build d2b433
 *
rpm-build d2b433
 * Side effects:
rpm-build d2b433
 *	Bitstream is parsed.
rpm-build d2b433
 *
rpm-build d2b433
 *--------------------------------------------------------------
rpm-build d2b433
 */
rpm-build d2b433
static int32_t
rpm-build d2b433
NextMarker(IO::Stream *s)
rpm-build d2b433
{
rpm-build d2b433
    int32_t c;
rpm-build d2b433
rpm-build d2b433
    do {
rpm-build d2b433
        /*
rpm-build d2b433
         * skip any non-FF bytes
rpm-build d2b433
         */
rpm-build d2b433
        do {
rpm-build d2b433
            c = s->readByte();
rpm-build d2b433
        } while (c != 0xFF);
rpm-build d2b433
        /*
rpm-build d2b433
         * skip any duplicate FFs without incrementing nbytes, since
rpm-build d2b433
         * extra FFs are legal
rpm-build d2b433
         */
rpm-build d2b433
        do {
rpm-build d2b433
            c = s->readByte();
rpm-build d2b433
        } while (c == 0xFF);
rpm-build d2b433
    } while (c == 0);		/* repeat if it was a stuffed FF/00 */
rpm-build d2b433
rpm-build d2b433
    return c;
rpm-build d2b433
}
rpm-build d2b433
rpm-build d2b433
/*
rpm-build d2b433
 *--------------------------------------------------------------
rpm-build d2b433
 *
rpm-build d2b433
 * ProcessTables --
rpm-build d2b433
 *
rpm-build d2b433
 *	Scan and process JPEG markers that can appear in any order
rpm-build d2b433
 *	Return when an SOI, EOI, SOFn, or SOS is found
rpm-build d2b433
 *
rpm-build d2b433
 * Results:
rpm-build d2b433
 *	The marker found.
rpm-build d2b433
 *
rpm-build d2b433
 * Side effects:
rpm-build d2b433
 *	Bitstream is parsed.
rpm-build d2b433
 *
rpm-build d2b433
 *--------------------------------------------------------------
rpm-build d2b433
 */
rpm-build d2b433
LJpegDecompressor::JpegMarker
rpm-build d2b433
LJpegDecompressor::ProcessTables (DecompressInfo *dcPtr)
rpm-build d2b433
{
rpm-build d2b433
    int c;
rpm-build d2b433
rpm-build d2b433
    while (1) {
rpm-build d2b433
        c = NextMarker (m_stream);
rpm-build d2b433
rpm-build d2b433
        switch (c) {
rpm-build d2b433
        case M_SOF0:
rpm-build d2b433
        case M_SOF1:
rpm-build d2b433
        case M_SOF2:
rpm-build d2b433
        case M_SOF3:
rpm-build d2b433
        case M_SOF5:
rpm-build d2b433
        case M_SOF6:
rpm-build d2b433
        case M_SOF7:
rpm-build d2b433
        case M_JPG:
rpm-build d2b433
        case M_SOF9:
rpm-build d2b433
        case M_SOF10:
rpm-build d2b433
        case M_SOF11:
rpm-build d2b433
        case M_SOF13:
rpm-build d2b433
        case M_SOF14:
rpm-build d2b433
        case M_SOF15:
rpm-build d2b433
        case M_SOI:
rpm-build d2b433
        case M_EOI:
rpm-build d2b433
        case M_SOS:
rpm-build d2b433
            return ((JpegMarker)c);
rpm-build d2b433
rpm-build d2b433
        case M_DHT:
rpm-build d2b433
            GetDht (dcPtr);
rpm-build d2b433
            break;
rpm-build d2b433
rpm-build d2b433
        case M_DQT:
rpm-build d2b433
            LOGWARN("Not a lossless JPEG file.\n");
rpm-build d2b433
            break;
rpm-build d2b433
rpm-build d2b433
        case M_DRI:
rpm-build d2b433
            GetDri (dcPtr);
rpm-build d2b433
            break;
rpm-build d2b433
rpm-build d2b433
        case M_APP0:
rpm-build d2b433
            GetApp0(m_stream);
rpm-build d2b433
            break;
rpm-build d2b433
rpm-build d2b433
        case M_RST0:		/* these are all parameterless */
rpm-build d2b433
        case M_RST1:
rpm-build d2b433
        case M_RST2:
rpm-build d2b433
        case M_RST3:
rpm-build d2b433
        case M_RST4:
rpm-build d2b433
        case M_RST5:
rpm-build d2b433
        case M_RST6:
rpm-build d2b433
        case M_RST7:
rpm-build d2b433
        case M_TEM:
rpm-build d2b433
            LOGWARN("Warning: unexpected marker 0x%x", c);
rpm-build d2b433
            break;
rpm-build d2b433
rpm-build d2b433
        default:		/* must be DNL, DHP, EXP, APPn, JPGn, COM,
rpm-build d2b433
                         * or RESn */
rpm-build d2b433
            SkipVariable (m_stream);
rpm-build d2b433
            break;
rpm-build d2b433
        }
rpm-build d2b433
    }
rpm-build d2b433
}
rpm-build d2b433
rpm-build d2b433
/*
rpm-build d2b433
 *--------------------------------------------------------------
rpm-build d2b433
 *
rpm-build d2b433
 * ReadFileHeader --
rpm-build d2b433
 *
rpm-build d2b433
 *	Initialize and read the file header (everything through
rpm-build d2b433
 *	the SOF marker).
rpm-build d2b433
 *
rpm-build d2b433
 * Results:
rpm-build d2b433
 *	None
rpm-build d2b433
 *
rpm-build d2b433
 * Side effects:
rpm-build d2b433
 *	Exit on error.
rpm-build d2b433
 *
rpm-build d2b433
 *--------------------------------------------------------------
rpm-build d2b433
 */
rpm-build d2b433
void
rpm-build d2b433
LJpegDecompressor::ReadFileHeader (DecompressInfo *dcPtr)
rpm-build d2b433
    noexcept(false)
rpm-build d2b433
{
rpm-build d2b433
    int c, c2;
rpm-build d2b433
rpm-build d2b433
    /*
rpm-build d2b433
     * Demand an SOI marker at the start of the file --- otherwise it's
rpm-build d2b433
     * probably not a JPEG file at all.
rpm-build d2b433
     */
rpm-build d2b433
    c = m_stream->readByte();
rpm-build d2b433
    c2 = m_stream->readByte();
rpm-build d2b433
    if ((c != 0xFF) || (c2 != M_SOI)) {
rpm-build d2b433
        throw DecodingException(str(boost::format("Not a JPEG file. "
rpm-build d2b433
                                                  "marker is %1% %2%\n")
rpm-build d2b433
                                    % c % c2));
rpm-build d2b433
    }
rpm-build d2b433
rpm-build d2b433
    GetSoi (dcPtr);		/* OK, process SOI */
rpm-build d2b433
rpm-build d2b433
    /*
rpm-build d2b433
     * Process markers until SOF
rpm-build d2b433
     */
rpm-build d2b433
    c = ProcessTables (dcPtr);
rpm-build d2b433
rpm-build d2b433
    switch (c) {
rpm-build d2b433
    case M_SOF0:
rpm-build d2b433
    case M_SOF1:
rpm-build d2b433
    case M_SOF3:
rpm-build d2b433
        GetSof(dcPtr);
rpm-build d2b433
        break;
rpm-build d2b433
rpm-build d2b433
    default:
rpm-build d2b433
        LOGWARN("Unsupported SOF marker type 0x%x\n", c);
rpm-build d2b433
        break;
rpm-build d2b433
    }
rpm-build d2b433
}
rpm-build d2b433
rpm-build d2b433
/*
rpm-build d2b433
 *--------------------------------------------------------------
rpm-build d2b433
 *
rpm-build d2b433
 * ReadScanHeader --
rpm-build d2b433
 *
rpm-build d2b433
 *	Read the start of a scan (everything through the SOS marker).
rpm-build d2b433
 *
rpm-build d2b433
 * Results:
rpm-build d2b433
 *	1 if find SOS, 0 if find EOI
rpm-build d2b433
 *
rpm-build d2b433
 * Side effects:
rpm-build d2b433
 *	Bitstream is parsed, may exit on errors.
rpm-build d2b433
 *
rpm-build d2b433
 *--------------------------------------------------------------
rpm-build d2b433
 */
rpm-build d2b433
int32_t
rpm-build d2b433
LJpegDecompressor::ReadScanHeader (DecompressInfo *dcPtr)
rpm-build d2b433
{
rpm-build d2b433
    int c;
rpm-build d2b433
rpm-build d2b433
    /*
rpm-build d2b433
     * Process markers until SOS or EOI
rpm-build d2b433
     */
rpm-build d2b433
    c = ProcessTables (dcPtr);
rpm-build d2b433
rpm-build d2b433
    switch (c) {
rpm-build d2b433
    case M_SOS:
rpm-build d2b433
        GetSos (dcPtr);
rpm-build d2b433
        return 1;
rpm-build d2b433
rpm-build d2b433
    case M_EOI:
rpm-build d2b433
        return 0;
rpm-build d2b433
rpm-build d2b433
    default:
rpm-build d2b433
        LOGWARN("Unexpected marker 0x%x\n", c);
rpm-build d2b433
        break;
rpm-build d2b433
    }
rpm-build d2b433
    return 0;
rpm-build d2b433
}
rpm-build d2b433
rpm-build d2b433
rpm-build d2b433
RawDataPtr LJpegDecompressor::decompress()
rpm-build d2b433
{
rpm-build d2b433
    DecompressInfo dcInfo;
rpm-build d2b433
    try {
rpm-build d2b433
        ReadFileHeader(&dcInfo); 
rpm-build d2b433
        ReadScanHeader (&dcInfo);
rpm-build d2b433
rpm-build d2b433
        m_output = RawDataPtr(new RawData);
rpm-build d2b433
        m_output->setDataType(OR_DATA_TYPE_RAW);
rpm-build d2b433
        uint32_t bpc = dcInfo.dataPrecision;
rpm-build d2b433
rpm-build d2b433
        m_output->setBpc(bpc);
rpm-build d2b433
        m_output->setWhiteLevel((1 << bpc) - 1);
rpm-build d2b433
        /*uint16_t *dataPtr = (uint16_t*)*/
rpm-build d2b433
        m_output->allocData(dcInfo.imageWidth
rpm-build d2b433
                          * sizeof(uint16_t) 
rpm-build d2b433
                          * dcInfo.imageHeight
rpm-build d2b433
                          * dcInfo.numComponents);
rpm-build d2b433
rpm-build d2b433
        LOGDBG1("dc width = %d dc height = %d\n", dcInfo.imageWidth,
rpm-build d2b433
                dcInfo.imageHeight);
rpm-build d2b433
        /* consistently the real width is the JPEG width * numComponent
rpm-build d2b433
         * at least with all the Canon.
rpm-build d2b433
         * @todo check that this is valid with DNG too.
rpm-build d2b433
         */
rpm-build d2b433
        uint32_t width = dcInfo.imageWidth * dcInfo.numComponents;
rpm-build d2b433
        m_output->setDimensions(width, dcInfo.imageHeight);
rpm-build d2b433
        m_output->setSlices(m_slices);
rpm-build d2b433
        DecoderStructInit(&dcInfo);
rpm-build d2b433
        HuffDecoderInit(&dcInfo);
rpm-build d2b433
        DecodeImage(&dcInfo);
rpm-build d2b433
        // TODO handle the error properly
rpm-build d2b433
    }
rpm-build d2b433
    catch(...)
rpm-build d2b433
    {
rpm-build d2b433
        LOGERR("Decompression error\n");
rpm-build d2b433
    }
rpm-build d2b433
    return std::move(m_output);
rpm-build d2b433
}
rpm-build d2b433
rpm-build d2b433
}
rpm-build d2b433
}
rpm-build d2b433
rpm-build d2b433
/*
rpm-build d2b433
  Local Variables:
rpm-build d2b433
  mode:c++
rpm-build d2b433
  c-file-style:"stroustrup"
rpm-build d2b433
  c-file-offsets:((innamespace . 0))
rpm-build d2b433
  indent-tabs-mode:nil
rpm-build d2b433
  fill-column:80
rpm-build d2b433
  End:
rpm-build d2b433
*/