16acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/*M///////////////////////////////////////////////////////////////////////////////////////
26acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
36acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
46acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
56acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//  By downloading, copying, installing or using the software you agree to this license.
66acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//  If you do not agree to this license, do not download, install,
76acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//  copy or use the software.
86acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
96acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//                        Intel License Agreement
116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//                For Open Source Computer Vision Library
126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Copyright (C) 2000, Intel Corporation, all rights reserved.
146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Third party copyrights are property of their respective owners.
156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Redistribution and use in source and binary forms, with or without modification,
176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// are permitted provided that the following conditions are met:
186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//   * Redistribution's of source code must retain the above copyright notice,
206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//     this list of conditions and the following disclaimer.
216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//   * Redistribution's in binary form must reproduce the above copyright notice,
236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//     this list of conditions and the following disclaimer in the documentation
246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//     and/or other materials provided with the distribution.
256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//   * The name of Intel Corporation may not be used to endorse or promote products
276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//     derived from this software without specific prior written permission.
286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// This software is provided by the copyright holders and contributors "as is" and
306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// any express or implied warranties, including, but not limited to, the implied
316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// warranties of merchantability and fitness for a particular purpose are disclaimed.
326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// In no event shall the Intel Corporation or contributors be liable for any direct,
336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// indirect, incidental, special, exemplary, or consequential damages
346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// (including, but not limited to, procurement of substitute goods or services;
356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// loss of use, data, or profits; or business interruption) however caused
366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// and on any theory of liability, whether in contract, strict liability,
376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// or tort (including negligence or otherwise) arising in any way out of
386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// the use of this software, even if advised of the possibility of such damage.
396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//M*/
416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "_highgui.h"
436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "grfmt_jpeg.h"
446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// JPEG filter factory
466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennGrFmtJpeg::GrFmtJpeg()
486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    m_sign_len = 3;
506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    m_signature = "\xFF\xD8\xFF";
516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    m_description = "JPEG files (*.jpeg;*.jpg;*.jpe)";
526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennGrFmtJpeg::~GrFmtJpeg()
566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennGrFmtReader* GrFmtJpeg::NewReader( const char* filename )
616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return new GrFmtJpegReader( filename );
636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennGrFmtWriter* GrFmtJpeg::NewWriter( const char* filename )
676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return new GrFmtJpegWriter( filename );
696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#ifdef HAVE_JPEG
736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/****************************************************************************************\
756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    This part of the file implements JPEG codec on base of IJG libjpeg library,
766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    in particular, this is the modified example.doc from libjpeg package.
776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    See otherlibs/_graphics/readme.txt for copyright notice.
786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn\****************************************************************************************/
796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include <stdio.h>
816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include <setjmp.h>
826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#ifdef WIN32
846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define XMD_H // prevent redefinition of INT32
866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#undef FAR  // prevent FAR redefinition
876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#endif
896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#if defined WIN32 && defined __GNUC__
916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renntypedef unsigned char boolean;
926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#endif
936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennextern "C" {
956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "jpeglib.h"
966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/////////////////////// Error processing /////////////////////
996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renntypedef struct GrFmtJpegErrorMgr
1016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
1026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    struct jpeg_error_mgr pub;    /* "parent" structure */
1036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    jmp_buf setjmp_buffer;        /* jump label */
1046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
1056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennGrFmtJpegErrorMgr;
1066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennMETHODDEF(void)
1096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennerror_exit( j_common_ptr cinfo )
1106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
1116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    GrFmtJpegErrorMgr* err_mgr = (GrFmtJpegErrorMgr*)(cinfo->err);
1126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    /* Return control to the setjmp point */
1146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    longjmp( err_mgr->setjmp_buffer, 1 );
1156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
1166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/////////////////////// GrFmtJpegReader ///////////////////
1196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennGrFmtJpegReader::GrFmtJpegReader( const char* filename ) : GrFmtReader( filename )
1226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
1236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    m_cinfo = 0;
1246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    m_f = 0;
1256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
1266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennGrFmtJpegReader::~GrFmtJpegReader()
1296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
1306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
1316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid  GrFmtJpegReader::Close()
1346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
1356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( m_f )
1366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
1376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        fclose( m_f );
1386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        m_f = 0;
1396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
1406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( m_cinfo )
1426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
1436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        jpeg_decompress_struct* cinfo = (jpeg_decompress_struct*)m_cinfo;
1446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        GrFmtJpegErrorMgr* jerr = (GrFmtJpegErrorMgr*)m_jerr;
1456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        jpeg_destroy_decompress( cinfo );
1476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        delete cinfo;
1486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        delete jerr;
1496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        m_cinfo = 0;
1506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        m_jerr = 0;
1516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
1526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    GrFmtReader::Close();
1536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
1546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennbool  GrFmtJpegReader::ReadHeader()
1576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
1586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    bool result = false;
1596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    Close();
1606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    jpeg_decompress_struct* cinfo = new jpeg_decompress_struct;
1626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    GrFmtJpegErrorMgr* jerr = new GrFmtJpegErrorMgr;
1636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cinfo->err = jpeg_std_error(&jerr->pub);
1656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    jerr->pub.error_exit = error_exit;
1666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    m_cinfo = cinfo;
1686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    m_jerr = jerr;
1696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( setjmp( jerr->setjmp_buffer ) == 0 )
1716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
1726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        jpeg_create_decompress( cinfo );
1736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        m_f = fopen( m_filename, "rb" );
1756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( m_f )
1766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
1776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            jpeg_stdio_src( cinfo, m_f );
1786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            jpeg_read_header( cinfo, TRUE );
1796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            m_width = cinfo->image_width;
1816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            m_height = cinfo->image_height;
1826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            m_iscolor = cinfo->num_components > 1;
1836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            result = true;
1856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
1866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
1876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !result )
1896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        Close();
1906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return result;
1926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
1936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/***************************************************************************
1956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * following code is for supporting MJPEG image files
1966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * based on a message of Laurent Pinchart on the video4linux mailing list
1976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ***************************************************************************/
1986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* JPEG DHT Segment for YCrCb omitted from MJPEG data */
2006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic
2016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennunsigned char my_jpeg_odml_dht[0x1a4] = {
2026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0xff, 0xc4, 0x01, 0xa2,
2036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00,
2056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x00, 0x00, 0x00, 0x00, 0x00,
2066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
2076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
2096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x00, 0x00, 0x00, 0x00, 0x00,
2106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
2116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04,
2136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x04, 0x00, 0x00, 0x01, 0x7d,
2146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06,
2156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x13, 0x51, 0x61, 0x07,
2166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1,
2176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x15, 0x52, 0xd1, 0xf0,
2186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a,
2196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x25, 0x26, 0x27, 0x28,
2206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45,
2216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x46, 0x47, 0x48, 0x49,
2226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65,
2236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x66, 0x67, 0x68, 0x69,
2246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, 0x85,
2256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x86, 0x87, 0x88, 0x89,
2266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3,
2276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0xa4, 0xa5, 0xa6, 0xa7,
2286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba,
2296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0xc2, 0xc3, 0xc4, 0xc5,
2306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
2316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0xd9, 0xda, 0xe1, 0xe2,
2326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4,
2336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0xf5, 0xf6, 0xf7, 0xf8,
2346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0xf9, 0xfa,
2356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04,
2376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x04, 0x00, 0x01, 0x02, 0x77,
2386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41,
2396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x51, 0x07, 0x61, 0x71,
2406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1, 0xc1, 0x09,
2416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x23, 0x33, 0x52, 0xf0,
2426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17,
2436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x18, 0x19, 0x1a, 0x26,
2446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44,
2456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x45, 0x46, 0x47, 0x48,
2466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64,
2476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x65, 0x66, 0x67, 0x68,
2486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83,
2496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x84, 0x85, 0x86, 0x87,
2506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a,
2516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0xa2, 0xa3, 0xa4, 0xa5,
2526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8,
2536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0xb9, 0xba, 0xc2, 0xc3,
2546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
2556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0xd7, 0xd8, 0xd9, 0xda,
2566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4,
2576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0xf5, 0xf6, 0xf7, 0xf8,
2586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0xf9, 0xfa
2596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn};
2606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/*
2626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * Parse the DHT table.
2636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * This code comes from jpeg6b (jdmarker.c).
2646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn */
2656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic
2666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennint my_jpeg_load_dht (struct jpeg_decompress_struct *info, unsigned char *dht,
2676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn              JHUFF_TBL *ac_tables[], JHUFF_TBL *dc_tables[])
2686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
2696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    unsigned int length = (dht[2] << 8) + dht[3] - 2;
2706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    unsigned int pos = 4;
2716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    unsigned int count, i;
2726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int index;
2736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    JHUFF_TBL **hufftbl;
2756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    unsigned char bits[17];
2766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    unsigned char huffval[256];
2776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    while (length > 16)
2796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
2806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn       bits[0] = 0;
2816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn       index = dht[pos++];
2826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn       count = 0;
2836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn       for (i = 1; i <= 16; ++i)
2846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn       {
2856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn           bits[i] = dht[pos++];
2866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn           count += bits[i];
2876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn       }
2886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn       length -= 17;
2896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn       if (count > 256 || count > length)
2916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn           return -1;
2926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn       for (i = 0; i < count; ++i)
2946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn           huffval[i] = dht[pos++];
2956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn       length -= count;
2966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn       if (index & 0x10)
2986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn       {
2996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn           index -= 0x10;
3006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn           hufftbl = &ac_tables[index];
3016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn       }
3026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn       else
3036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn           hufftbl = &dc_tables[index];
3046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn       if (index < 0 || index >= NUM_HUFF_TBLS)
3066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn           return -1;
3076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn       if (*hufftbl == NULL)
3096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn           *hufftbl = jpeg_alloc_huff_table ((j_common_ptr)info);
3106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn       if (*hufftbl == NULL)
3116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn           return -1;
3126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn       memcpy ((*hufftbl)->bits, bits, sizeof (*hufftbl)->bits);
3146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn       memcpy ((*hufftbl)->huffval, huffval, sizeof (*hufftbl)->huffval);
3156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
3166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if (length != 0)
3186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn       return -1;
3196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return 0;
3216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
3226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/***************************************************************************
3246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * end of code for supportting MJPEG image files
3256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * based on a message of Laurent Pinchart on the video4linux mailing list
3266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ***************************************************************************/
3276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennbool  GrFmtJpegReader::ReadData( uchar* data, int step, int color )
3296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
3306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    bool result = false;
3316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    color = color > 0 || (m_iscolor && color < 0);
3336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( m_cinfo && m_jerr && m_width && m_height )
3356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
3366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        jpeg_decompress_struct* cinfo = (jpeg_decompress_struct*)m_cinfo;
3376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        GrFmtJpegErrorMgr* jerr = (GrFmtJpegErrorMgr*)m_jerr;
3386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        JSAMPARRAY buffer = 0;
3396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( setjmp( jerr->setjmp_buffer ) == 0 )
3416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
3426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            /* check if this is a mjpeg image format */
3436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if ( cinfo->ac_huff_tbl_ptrs[0] == NULL &&
3446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                cinfo->ac_huff_tbl_ptrs[1] == NULL &&
3456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                cinfo->dc_huff_tbl_ptrs[0] == NULL &&
3466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                cinfo->dc_huff_tbl_ptrs[1] == NULL )
3476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
3486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                /* yes, this is a mjpeg image format, so load the correct
3496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                huffman table */
3506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                my_jpeg_load_dht( cinfo,
3516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    my_jpeg_odml_dht,
3526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    cinfo->ac_huff_tbl_ptrs,
3536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    cinfo->dc_huff_tbl_ptrs );
3546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
3556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( color > 0 || (m_iscolor && color < 0) )
3576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
3586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                color = 1;
3596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( cinfo->num_components != 4 )
3606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
3616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    cinfo->out_color_space = JCS_RGB;
3626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    cinfo->out_color_components = 3;
3636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
3646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                else
3656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
3666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    cinfo->out_color_space = JCS_CMYK;
3676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    cinfo->out_color_components = 4;
3686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
3696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
3706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
3716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
3726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                color = 0;
3736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( cinfo->num_components != 4 )
3746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
3756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    cinfo->out_color_space = JCS_GRAYSCALE;
3766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    cinfo->out_color_components = 1;
3776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
3786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                else
3796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
3806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    cinfo->out_color_space = JCS_CMYK;
3816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    cinfo->out_color_components = 4;
3826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
3836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
3846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            jpeg_start_decompress( cinfo );
3866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            buffer = (*cinfo->mem->alloc_sarray)((j_common_ptr)cinfo,
3886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                              JPOOL_IMAGE, m_width*4, 1 );
3896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( ; m_height--; data += step )
3916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
3926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                jpeg_read_scanlines( cinfo, buffer, 1 );
3936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( color )
3946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
3956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if( cinfo->out_color_components == 3 )
3966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        icvCvt_RGB2BGR_8u_C3R( buffer[0], 0, data, 0, cvSize(m_width,1) );
3976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    else
3986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        icvCvt_CMYK2BGR_8u_C4C3R( buffer[0], 0, data, 0, cvSize(m_width,1) );
3996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
4006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                else
4016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
4026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if( cinfo->out_color_components == 1 )
4036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        memcpy( data, buffer[0], m_width );
4046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    else
4056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        icvCvt_CMYK2Gray_8u_C4C1R( buffer[0], 0, data, 0, cvSize(m_width,1) );
4066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
4076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
4086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            result = true;
4096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            jpeg_finish_decompress( cinfo );
4106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
4116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
4126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    Close();
4146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return result;
4156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
4166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/////////////////////// GrFmtJpegWriter ///////////////////
4196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennGrFmtJpegWriter::GrFmtJpegWriter( const char* filename ) : GrFmtWriter( filename )
4216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
4226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
4236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennGrFmtJpegWriter::~GrFmtJpegWriter()
4266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
4276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
4286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennbool  GrFmtJpegWriter::WriteImage( const uchar* data, int step,
4316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                   int width, int height, int /*depth*/, int _channels )
4326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
4336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const int default_quality = 95;
4346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    struct jpeg_compress_struct cinfo;
4356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    GrFmtJpegErrorMgr jerr;
4366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    bool result = false;
4386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    FILE* f = 0;
4396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int channels = _channels > 1 ? 3 : 1;
4406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    uchar* buffer = 0; // temporary buffer for row flipping
4416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cinfo.err = jpeg_std_error(&jerr.pub);
4436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    jerr.pub.error_exit = error_exit;
4446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( setjmp( jerr.setjmp_buffer ) == 0 )
4466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
4476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        jpeg_create_compress(&cinfo);
4486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        f = fopen( m_filename, "wb" );
4496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( f )
4516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
4526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            jpeg_stdio_dest( &cinfo, f );
4536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cinfo.image_width = width;
4556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cinfo.image_height = height;
4566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cinfo.input_components = channels;
4576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cinfo.in_color_space = channels > 1 ? JCS_RGB : JCS_GRAYSCALE;
4586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            jpeg_set_defaults( &cinfo );
4606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            jpeg_set_quality( &cinfo, default_quality,
4616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              TRUE /* limit to baseline-JPEG values */ );
4626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            jpeg_start_compress( &cinfo, TRUE );
4636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( channels > 1 )
4656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                buffer = new uchar[width*channels];
4666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( ; height--; data += step )
4686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
4696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                uchar* ptr = (uchar*)data;
4706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( _channels == 3 )
4726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
4736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    icvCvt_BGR2RGB_8u_C3R( data, 0, buffer, 0, cvSize(width,1) );
4746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    ptr = buffer;
4756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
4766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                else if( _channels == 4 )
4776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
4786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    icvCvt_BGRA2BGR_8u_C4C3R( data, 0, buffer, 0, cvSize(width,1), 2 );
4796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    ptr = buffer;
4806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
4816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                jpeg_write_scanlines( &cinfo, &ptr, 1 );
4836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
4846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            jpeg_finish_compress( &cinfo );
4866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            result = true;
4876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
4886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
4896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if(f) fclose(f);
4916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    jpeg_destroy_compress( &cinfo );
4926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    delete[] buffer;
4946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return result;
4956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
4966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#else
4986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//////////////////////  JPEG-oriented two-level bitstream ////////////////////////
5006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennRJpegBitStream::RJpegBitStream()
5026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
5036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
5046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennRJpegBitStream::~RJpegBitStream()
5066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
5076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    Close();
5086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
5096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennbool  RJpegBitStream::Open( const char* filename )
5126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
5136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    Close();
5146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    Allocate();
5156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    m_is_opened = m_low_strm.Open( filename );
5176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( m_is_opened ) SetPos(0);
5186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return m_is_opened;
5196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
5206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid  RJpegBitStream::Close()
5236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
5246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    m_low_strm.Close();
5256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    m_is_opened = false;
5266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
5276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid  RJpegBitStream::ReadBlock()
5306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
5316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    uchar* end = m_start + m_block_size;
5326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    uchar* current = m_start;
5336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( setjmp( m_low_strm.JmpBuf()) == 0 )
5356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
5366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int sz = m_unGetsize;
5376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        memmove( current - sz, m_end - sz, sz );
5386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        while( current < end )
5396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
5406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int val = m_low_strm.GetByte();
5416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( val != 0xff )
5426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
5436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                *current++ = (uchar)val;
5446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
5456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
5466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
5476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                val = m_low_strm.GetByte();
5486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( val == 0 )
5496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    *current++ = 0xFF;
5506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                else if( !(0xD0 <= val && val <= 0xD7) )
5516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
5526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    m_low_strm.SetPos( m_low_strm.GetPos() - 2 );
5536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    goto fetch_end;
5546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
5556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
5566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
5576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennfetch_end: ;
5586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
5596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
5606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
5616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( current == m_start && m_jmp_set )
5626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            longjmp( m_jmp_buf, RBS_THROW_EOS );
5636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
5646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    m_current = m_start;
5656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    m_end = m_start + (((current - m_start) + 3) & -4);
5666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !bsIsBigEndian() )
5676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        bsBSwapBlock( m_start, m_end );
5686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
5696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid  RJpegBitStream::Flush()
5726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
5736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    m_end = m_start + m_block_size;
5746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    m_current = m_end - 4;
5756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    m_bit_idx = 0;
5766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
5776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid  RJpegBitStream::AlignOnByte()
5796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
5806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    m_bit_idx &= -8;
5816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
5826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennint  RJpegBitStream::FindMarker()
5846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
5856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int code = m_low_strm.GetWord();
5866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    while( (code & 0xFF00) != 0xFF00 || (code == 0xFFFF || code == 0xFF00 ))
5876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
5886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        code = ((code&255) << 8) | m_low_strm.GetByte();
5896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
5906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return code;
5916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
5926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/****************************** JPEG (JFIF) reader ***************************/
5956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// zigzag & IDCT prescaling (AAN algorithm) tables
5976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic const uchar zigzag[] =
5986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
5996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  0,  8,  1,  2,  9, 16, 24, 17, 10,  3,  4, 11, 18, 25, 32, 40,
6006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 33, 26, 19, 12,  5,  6, 13, 20, 27, 34, 41, 48, 56, 49, 42, 35,
6016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 28, 21, 14,  7, 15, 22, 29, 36, 43, 50, 57, 58, 51, 44, 37, 30,
6026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 23, 31, 38, 45, 52, 59, 60, 53, 46, 39, 47, 54, 61, 62, 55, 63,
6036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63
6046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn};
6056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic const int idct_prescale[] =
6086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
6096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    16384, 22725, 21407, 19266, 16384, 12873,  8867,  4520,
6106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    22725, 31521, 29692, 26722, 22725, 17855, 12299,  6270,
6116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    21407, 29692, 27969, 25172, 21407, 16819, 11585,  5906,
6126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    19266, 26722, 25172, 22654, 19266, 15137, 10426,  5315,
6136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    16384, 22725, 21407, 19266, 16384, 12873,  8867,  4520,
6146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    12873, 17855, 16819, 15137, 12873, 10114,  6967,  3552,
6156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn     8867, 12299, 11585, 10426,  8867,  6967,  4799,  2446,
6166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn     4520,  6270,  5906,  5315,  4520,  3552,  2446,  1247
6176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn};
6186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define fixb         14
6216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define fix(x, n)    (int)((x)*(1 << (n)) + .5)
6226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define fix1(x, n)   (x)
6236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define fixmul(x)    (x)
6246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define C0_707     fix( 0.707106781f, fixb )
6266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define C0_924     fix( 0.923879533f, fixb )
6276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define C0_541     fix( 0.541196100f, fixb )
6286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define C0_382     fix( 0.382683432f, fixb )
6296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define C1_306     fix( 1.306562965f, fixb )
6306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define C1_082     fix( 1.082392200f, fixb )
6326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define C1_414     fix( 1.414213562f, fixb )
6336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define C1_847     fix( 1.847759065f, fixb )
6346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define C2_613     fix( 2.613125930f, fixb )
6356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define fixc       12
6376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define b_cb       fix( 1.772, fixc )
6386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define g_cb      -fix( 0.34414, fixc )
6396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define g_cr      -fix( 0.71414, fixc )
6406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define r_cr       fix( 1.402, fixc )
6416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define y_r        fix( 0.299, fixc )
6436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define y_g        fix( 0.587, fixc )
6446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define y_b        fix( 0.114, fixc )
6456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define cb_r      -fix( 0.1687, fixc )
6476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define cb_g      -fix( 0.3313, fixc )
6486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define cb_b       fix( 0.5,    fixc )
6496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define cr_r       fix( 0.5,    fixc )
6516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define cr_g      -fix( 0.4187, fixc )
6526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define cr_b      -fix( 0.0813, fixc )
6536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// IDCT without prescaling
6566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void aan_idct8x8( int *src, int *dst, int step )
6576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
6586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int   workspace[64], *work = workspace;
6596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int   i;
6606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    /* Pass 1: process rows */
6626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 8; i > 0; i--, src += 8, work += 8 )
6636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
6646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        /* Odd part */
6656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int  x0 = src[5], x1 = src[3];
6666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int  x2 = src[1], x3 = src[7];
6676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int  x4 = x0 + x1; x0 -= x1;
6696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x1 = x2 + x3; x2 -= x3;
6716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x3 = x1 + x4; x1 -= x4;
6726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x4 = (x0 + x2)*C1_847;
6746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x0 = descale( x4 - x0*C2_613, fixb);
6756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x2 = descale( x2*C1_082 - x4, fixb);
6766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x1 = descale( x1*C1_414, fixb);
6776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x0 -= x3;
6796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x1 -= x0;
6806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x2 += x1;
6816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        work[7] = x3; work[6] = x0;
6836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        work[5] = x1; work[4] = x2;
6846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        /* Even part */
6866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x2 = src[2]; x3 = src[6];
6876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x0 = src[0]; x1 = src[4];
6886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x4 = x2 + x3;
6906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x2 = descale((x2-x3)*C1_414, fixb) - x4;
6916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x3 = x0 + x1; x0 -= x1;
6936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x1 = x3 + x4; x3 -= x4;
6946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x4 = x0 + x2; x0 -= x2;
6956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x2 = work[7];
6976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x1 -= x2; x2 = 2*x2 + x1;
6986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        work[7] = x1; work[0] = x2;
6996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x2 = work[6];
7016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x1 = x4 + x2; x4 -= x2;
7026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        work[1] = x1; work[6] = x4;
7036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x1 = work[5]; x2 = work[4];
7056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x4 = x0 + x1; x0 -= x1;
7066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x1 = x3 + x2; x3 -= x2;
7076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        work[2] = x4; work[5] = x0;
7096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        work[3] = x3; work[4] = x1;
7106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
7116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    /* Pass 2: process columns */
7136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    work = workspace;
7146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 8; i > 0; i--, dst += step, work++ )
7156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
7166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        /* Odd part */
7176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int  x0 = work[8*5], x1 = work[8*3];
7186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int  x2 = work[8*1], x3 = work[8*7];
7196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int  x4 = x0 + x1; x0 -= x1;
7216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x1 = x2 + x3; x2 -= x3;
7226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x3 = x1 + x4; x1 -= x4;
7236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x4 = (x0 + x2)*C1_847;
7256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x0 = descale( x4 - x0*C2_613, fixb);
7266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x2 = descale( x2*C1_082 - x4, fixb);
7276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x1 = descale( x1*C1_414, fixb);
7286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x0 -= x3;
7306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x1 -= x0;
7316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x2 += x1;
7326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        dst[7] = x3; dst[6] = x0;
7346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        dst[5] = x1; dst[4] = x2;
7356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        /* Even part */
7376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x2 = work[8*2]; x3 = work[8*6];
7386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x0 = work[8*0]; x1 = work[8*4];
7396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x4 = x2 + x3;
7416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x2 = descale((x2-x3)*C1_414, fixb) - x4;
7426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x3 = x0 + x1; x0 -= x1;
7446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x1 = x3 + x4; x3 -= x4;
7456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x4 = x0 + x2; x0 -= x2;
7466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x2 = dst[7];
7486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x1 -= x2; x2 = 2*x2 + x1;
7496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x1 = descale(x1,3);
7506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x2 = descale(x2,3);
7516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        dst[7] = x1; dst[0] = x2;
7536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x2 = dst[6];
7556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x1 = descale(x4 + x2,3);
7566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x4 = descale(x4 - x2,3);
7576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        dst[1] = x1; dst[6] = x4;
7586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x1 = dst[5]; x2 = dst[4];
7606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x4 = descale(x0 + x1,3);
7626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x0 = descale(x0 - x1,3);
7636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x1 = descale(x3 + x2,3);
7646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x3 = descale(x3 - x2,3);
7656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        dst[2] = x4; dst[5] = x0;
7676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        dst[3] = x3; dst[4] = x1;
7686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
7696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
7706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic const int max_dec_htable_size = 1 << 12;
7736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic const int first_table_bits = 9;
7746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennGrFmtJpegReader::GrFmtJpegReader( const char* filename ) : GrFmtReader( filename )
7766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
7776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    m_planes= -1;
7786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    m_offset= -1;
7796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i;
7816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < 4; i++ )
7826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
7836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        m_td[i] = new short[max_dec_htable_size];
7846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        m_ta[i] = new short[max_dec_htable_size];
7856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
7866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
7876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennGrFmtJpegReader::~GrFmtJpegReader()
7906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
7916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( int i = 0; i < 4; i++ )
7926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
7936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        delete[] m_td[i];
7946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        m_td[i] = 0;
7956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        delete[] m_ta[i];
7966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        m_ta[i] = 0;
7976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
7986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
7996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid  GrFmtJpegReader::Close()
8026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
8036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    m_strm.Close();
8046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    GrFmtReader::Close();
8056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
8066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennbool GrFmtJpegReader::ReadHeader()
8096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
8106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char buffer[16];
8116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int  i;
8126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    bool result = false, is_sof = false,
8136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn         is_qt = false, is_ht = false, is_sos = false;
8146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert( strlen(m_filename) != 0 );
8166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !m_strm.Open( m_filename )) return false;
8176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    memset( m_is_tq, 0, sizeof(m_is_tq));
8196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    memset( m_is_td, 0, sizeof(m_is_td));
8206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    memset( m_is_ta, 0, sizeof(m_is_ta));
8216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    m_MCUs = 0;
8226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( setjmp( m_strm.JmpBuf()) == 0 )
8246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
8256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        RMByteStream& lstrm = m_strm.m_low_strm;
8266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        lstrm.Skip( 2 ); // skip SOI marker
8286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for(;;)
8306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
8316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int marker = m_strm.FindMarker() & 255;
8326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            // check for standalone markers
8346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( marker != 0xD8 /* SOI */ && marker != 0xD9 /* EOI */ &&
8356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                marker != 0x01 /* TEM */ && !( 0xD0 <= marker && marker <= 0xD7 ))
8366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
8376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int pos    = lstrm.GetPos();
8386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int length = lstrm.GetWord();
8396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                switch( marker )
8416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
8426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                case 0xE0: // APP0
8436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    lstrm.GetBytes( buffer, 5 );
8446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if( strcmp(buffer, "JFIF") == 0 ) // JFIF identification
8456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
8466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        m_version = lstrm.GetWord();
8476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        //is_jfif = true;
8486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
8496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    break;
8506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                case 0xC0: // SOF0
8526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    m_precision = lstrm.GetByte();
8536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    m_height = lstrm.GetWord();
8546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    m_width = lstrm.GetWord();
8556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    m_planes = lstrm.GetByte();
8566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if( m_width == 0 || m_height == 0 || // DNL not supported
8586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                       (m_planes != 1 && m_planes != 3)) goto parsing_end;
8596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    m_iscolor = m_planes == 3;
8616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    memset( m_ci, -1, sizeof(m_ci));
8636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    for( i = 0; i < m_planes; i++ )
8656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
8666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        int idx = lstrm.GetByte();
8676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        if( idx < 1 || idx > m_planes ) // wrong index
8696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        {
8706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            idx = i+1; // hack
8716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        }
8726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        cmp_info& ci = m_ci[idx-1];
8736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        if( ci.tq > 0 /* duplicated description */) goto parsing_end;
8756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        ci.h = (char)lstrm.GetByte();
8776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        ci.v = (char)(ci.h & 15);
8786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        ci.h >>= 4;
8796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        ci.tq = (char)lstrm.GetByte();
8806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        if( !((ci.h == 1 || ci.h == 2 || ci.h == 4) &&
8816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              (ci.v == 1 || ci.v == 2 || ci.v == 4) &&
8826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              ci.tq < 3) ||
8836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            // chroma mcu-parts should have equal sizes and
8846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            // be non greater then luma sizes
8856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            !( i != 2 || (ci.h == m_ci[1].h && ci.v == m_ci[1].v &&
8866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                          ci.h <= m_ci[0].h && ci.v <= m_ci[0].v)))
8876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            goto parsing_end;
8886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
8896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    is_sof = true;
8906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    m_type = marker - 0xC0;
8916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    break;
8926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                case 0xDB: // DQT
8946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if( !LoadQuantTables( length )) goto parsing_end;
8956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    is_qt = true;
8966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    break;
8976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                case 0xC4: // DHT
8996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if( !LoadHuffmanTables( length )) goto parsing_end;
9006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    is_ht = true;
9016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    break;
9026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                case 0xDA: // SOS
9046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    is_sos = true;
9056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    m_offset = pos - 2;
9066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    goto parsing_end;
9076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                case 0xDD: // DRI
9096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    m_MCUs = lstrm.GetWord();
9106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    break;
9116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
9126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                lstrm.SetPos( pos + length );
9136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
9146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
9156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennparsing_end: ;
9166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
9176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    result = /*is_jfif &&*/ is_sof && is_qt && is_ht && is_sos;
9196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !result )
9206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
9216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        m_width = m_height = -1;
9226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        m_offset = -1;
9236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        m_strm.Close();
9246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
9256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return result;
9266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
9276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennbool GrFmtJpegReader::LoadQuantTables( int length )
9306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
9316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    uchar buffer[128];
9326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int  i, tq_size;
9336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    RMByteStream& lstrm = m_strm.m_low_strm;
9356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    length -= 2;
9366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    while( length > 0 )
9386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
9396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int tq = lstrm.GetByte();
9406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int size = tq >> 4;
9416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        tq &= 15;
9426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        tq_size = (64<<size) + 1;
9446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( tq > 3 || size > 1 || length < tq_size ) return false;
9456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        length -= tq_size;
9466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        lstrm.GetBytes( buffer, tq_size - 1 );
9486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( size == 0 ) // 8 bit quant factors
9506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
9516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( i = 0; i < 64; i++ )
9526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
9536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int idx = zigzag[i];
9546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                m_tq[tq][idx] = buffer[i] * 16 * idct_prescale[idx];
9556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
9566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
9576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else // 16 bit quant factors
9586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
9596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( i = 0; i < 64; i++ )
9606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
9616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int idx = zigzag[i];
9626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                m_tq[tq][idx] = ((unsigned short*)buffer)[i] * idct_prescale[idx];
9636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
9646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
9656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        m_is_tq[tq] = true;
9666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
9676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return true;
9696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
9706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennbool GrFmtJpegReader::LoadHuffmanTables( int length )
9736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
9746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const int max_bits = 16;
9756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    uchar buffer[1024];
9766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int  buffer2[1024];
9776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int  i, ht_size;
9796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    RMByteStream& lstrm = m_strm.m_low_strm;
9806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    length -= 2;
9816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    while( length > 0 )
9836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
9846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int t = lstrm.GetByte();
9856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int hclass = t >> 4;
9866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        t &= 15;
9876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( t > 3 || hclass > 1 || length < 17 ) return false;
9896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        length -= 17;
9906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        lstrm.GetBytes( buffer, max_bits );
9926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( i = 0, ht_size = 0; i < max_bits; i++ ) ht_size += buffer[i];
9936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( length < ht_size ) return false;
9956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        length -= ht_size;
9966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        lstrm.GetBytes( buffer + max_bits, ht_size );
9986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !::bsCreateDecodeHuffmanTable(
10006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  ::bsCreateSourceHuffmanTable(
10016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        buffer, buffer2, max_bits, first_table_bits ),
10026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        hclass == 0 ? m_td[t] : m_ta[t],
10036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        max_dec_htable_size )) return false;
10046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( hclass == 0 )
10056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            m_is_td[t] = true;
10066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
10076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            m_is_ta[t] = true;
10086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
10096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return true;
10106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
10116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennbool GrFmtJpegReader::ReadData( uchar* data, int step, int color )
10146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
10156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( m_offset < 0 || !m_strm.IsOpened())
10166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        return false;
10176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( setjmp( m_strm.JmpBuf()) == 0 )
10196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
10206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        RMByteStream& lstrm = m_strm.m_low_strm;
10216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        lstrm.SetPos( m_offset );
10226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for(;;)
10246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
10256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int marker = m_strm.FindMarker() & 255;
10266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( marker == 0xD8 /* SOI */ || marker == 0xD9 /* EOI */ )
10286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                goto decoding_end;
10296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            // check for standalone markers
10316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( marker != 0x01 /* TEM */ && !( 0xD0 <= marker && marker <= 0xD7 ))
10326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
10336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int pos    = lstrm.GetPos();
10346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int length = lstrm.GetWord();
10356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                switch( marker )
10376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
10386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                case 0xC4: // DHT
10396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if( !LoadHuffmanTables( length )) goto decoding_end;
10406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    break;
10416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                case 0xDA: // SOS
10436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    // read scan header
10446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
10456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        int idx[3] = { -1, -1, -1 };
10466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        int i, ns = lstrm.GetByte();
10476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        int sum = 0, a; // spectral selection & approximation
10486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        if( ns != m_planes ) goto decoding_end;
10506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        for( i = 0; i < ns; i++ )
10516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        {
10526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            int td, ta, c = lstrm.GetByte() - 1;
10536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            if( c < 0 || m_planes <= c )
10546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            {
10556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                c = i; // hack
10566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            }
10576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            if( idx[c] != -1 ) goto decoding_end;
10596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            idx[i] = c;
10606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            td = lstrm.GetByte();
10616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            ta = td & 15;
10626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            td >>= 4;
10636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            if( !(ta <= 3 && m_is_ta[ta] &&
10646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                  td <= 3 && m_is_td[td] &&
10656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                  m_is_tq[m_ci[c].tq]) )
10666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                goto decoding_end;
10676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            m_ci[c].td = (char)td;
10696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            m_ci[c].ta = (char)ta;
10706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            sum += m_ci[c].h*m_ci[c].v;
10726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        }
10736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        if( sum > 10 ) goto decoding_end;
10756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        m_ss = lstrm.GetByte();
10776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        m_se = lstrm.GetByte();
10786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        a = lstrm.GetByte();
10806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        m_al = a & 15;
10816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        m_ah = a >> 4;
10826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        ProcessScan( idx, ns, data, step, color );
10846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        goto decoding_end; // only single scan case is supported now
10856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
10866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    //m_offset = pos - 2;
10886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    //break;
10896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                case 0xDD: // DRI
10916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    m_MCUs = lstrm.GetWord();
10926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    break;
10936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
10946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( marker != 0xDA ) lstrm.SetPos( pos + length );
10966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
10976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
10986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renndecoding_end: ;
10996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
11006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return true;
11026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
11036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid  GrFmtJpegReader::ResetDecoder()
11066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
11076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    m_ci[0].dc_pred = m_ci[1].dc_pred = m_ci[2].dc_pred = 0;
11086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
11096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid  GrFmtJpegReader::ProcessScan( int* idx, int ns, uchar* data, int step, int color )
11116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
11126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int   i, s = 0, mcu, x1 = 0, y1 = 0;
11136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int   temp[64];
11146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int   blocks[10][64];
11156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int   pos[3], h[3], v[3];
11166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int   x_shift = 0, y_shift = 0;
11176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int   nch = color ? 3 : 1;
11186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert( ns == m_planes && m_ss == 0 && m_se == 63 &&
11206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            m_al == 0 && m_ah == 0 ); // sequental & single scan
11216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert( idx[0] == 0 && (ns ==1 || (idx[1] == 1 && idx[2] == 2)));
11236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < ns; i++ )
11256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
11266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int c = idx[i];
11276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        h[c] = m_ci[c].h*8;
11286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        v[c] = m_ci[c].v*8;
11296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        pos[c] = s >> 6;
11306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        s += h[c]*v[c];
11316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
11326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( ns == 3 )
11346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
11356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x_shift = h[0]/(h[1]*2);
11366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        y_shift = v[0]/(v[1]*2);
11376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
11386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    m_strm.Flush();
11406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ResetDecoder();
11416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( mcu = 0;; mcu++ )
11436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
11446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int  x2, y2, x, y, xc;
11456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int* cmp;
11466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        uchar* data1;
11476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( mcu == m_MCUs && m_MCUs != 0 )
11496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
11506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            ResetDecoder();
11516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            m_strm.AlignOnByte();
11526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            mcu = 0;
11536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
11546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        // Get mcu
11566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( i = 0; i < ns; i++ )
11576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
11586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int  c = idx[i];
11596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cmp = blocks[pos[c]];
11606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( y = 0; y < v[c]; y += 8, cmp += h[c]*8 )
11616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( x = 0; x < h[c]; x += 8 )
11626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
11636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    GetBlock( temp, c );
11646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if( i < (color ? 3 : 1))
11656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
11666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        aan_idct8x8( temp, cmp + x, h[c] );
11676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
11686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
11696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
11706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        y2 = v[0];
11726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x2 = h[0];
11736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( y1 + y2 > m_height ) y2 = m_height - y1;
11756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( x1 + x2 > m_width ) x2 = m_width - x1;
11766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cmp = blocks[0];
11786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        data1 = data + x1*nch;
11796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( ns == 1 )
11816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( y = 0; y < y2; y++, data1 += step, cmp += h[0] )
11826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
11836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( color )
11846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
11856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    for( x = 0; x < x2; x++ )
11866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
11876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        int val = descale( cmp[x] + 128*4, 2 );
11886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        data1[x*3] = data1[x*3 + 1] = data1[x*3 + 2] = saturate( val );
11896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
11906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
11916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                else
11926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
11936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    for( x = 0; x < x2; x++ )
11946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
11956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        int val = descale( cmp[x] + 128*4, 2 );
11966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        data1[x] = saturate( val );
11976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
11986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
11996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
12006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
12016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
12026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( y = 0; y < y2; y++, data1 += step, cmp += h[0] )
12036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
12046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( color )
12056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
12066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    int  shift = h[1]*(y >> y_shift);
12076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    int* cmpCb = blocks[pos[1]] + shift;
12086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    int* cmpCr = blocks[pos[2]] + shift;
12096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    x = 0;
12106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if( x_shift == 0 )
12116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
12126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        for( ; x < x2; x++ )
12136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        {
12146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            int Y  = (cmp[x] + 128*4) << fixc;
12156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            int Cb = cmpCb[x];
12166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            int Cr = cmpCr[x];
12176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            int t = (Y + Cb*b_cb) >> (fixc + 2);
12186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            data1[x*3] = saturate(t);
12196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            t = (Y + Cb*g_cb + Cr*g_cr) >> (fixc + 2);
12206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            data1[x*3 + 1] = saturate(t);
12216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            t = (Y + Cr*r_cr) >> (fixc + 2);
12226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            data1[x*3 + 2] = saturate(t);
12236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        }
12246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
12256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    else if( x_shift == 1 )
12266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
12276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        for( xc = 0; x <= x2 - 2; x += 2, xc++ )
12286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        {
12296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            int Y  = (cmp[x] + 128*4) << fixc;
12306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            int Cb = cmpCb[xc];
12316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            int Cr = cmpCr[xc];
12326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            int t = (Y + Cb*b_cb) >> (fixc + 2);
12336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            data1[x*3] = saturate(t);
12346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            t = (Y + Cb*g_cb + Cr*g_cr) >> (fixc + 2);
12356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            data1[x*3 + 1] = saturate(t);
12366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            t = (Y + Cr*r_cr) >> (fixc + 2);
12376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            data1[x*3 + 2] = saturate(t);
12386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            Y = (cmp[x+1] + 128*4) << fixc;
12396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            t = (Y + Cb*b_cb) >> (fixc + 2);
12406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            data1[x*3 + 3] = saturate(t);
12416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            t = (Y + Cb*g_cb + Cr*g_cr) >> (fixc + 2);
12426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            data1[x*3 + 4] = saturate(t);
12436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            t = (Y + Cr*r_cr) >> (fixc + 2);
12446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            data1[x*3 + 5] = saturate(t);
12456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        }
12466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
12476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    for( ; x < x2; x++ )
12486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
12496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        int Y  = (cmp[x] + 128*4) << fixc;
12506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        int Cb = cmpCb[x >> x_shift];
12516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        int Cr = cmpCr[x >> x_shift];
12526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        int t = (Y + Cb*b_cb) >> (fixc + 2);
12536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        data1[x*3] = saturate(t);
12546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        t = (Y + Cb*g_cb + Cr*g_cr) >> (fixc + 2);
12556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        data1[x*3 + 1] = saturate(t);
12566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        t = (Y + Cr*r_cr) >> (fixc + 2);
12576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        data1[x*3 + 2] = saturate(t);
12586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
12596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
12606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                else
12616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
12626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    for( x = 0; x < x2; x++ )
12636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
12646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        int val = descale( cmp[x] + 128*4, 2 );
12656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        data1[x] = saturate(val);
12666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
12676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
12686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
12696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
12706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x1 += h[0];
12726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( x1 >= m_width )
12736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
12746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            x1 = 0;
12756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            y1 += v[0];
12766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            data += v[0]*step;
12776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( y1 >= m_height ) break;
12786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
12796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
12806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
12816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid  GrFmtJpegReader::GetBlock( int* block, int c )
12846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
12856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    memset( block, 0, 64*sizeof(block[0]) );
12866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert( 0 <= c && c < 3 );
12886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const short* td = m_td[m_ci[c].td];
12896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const short* ta = m_ta[m_ci[c].ta];
12906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const int* tq = m_tq[m_ci[c].tq];
12916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // Get DC coefficient
12936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i = 0, cat  = m_strm.GetHuff( td );
12946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int mask = bs_bit_mask[cat];
12956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int val  = m_strm.Get( cat );
12966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    val -= (val*2 <= mask ? mask : 0);
12986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    m_ci[c].dc_pred = val += m_ci[c].dc_pred;
12996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    block[0] = descale(val * tq[0],16);
13016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // Get AC coeffs
13036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for(;;)
13046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
13056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cat = m_strm.GetHuff( ta );
13066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( cat == 0 ) break; // end of block
13076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        i += (cat >> 4) + 1;
13096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cat &= 15;
13106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        mask = bs_bit_mask[cat];
13116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        val  = m_strm.Get( cat );
13126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cat  = zigzag[i];
13136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        val -= (val*2 <= mask ? mask : 0);
13146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        block[cat] = descale(val * tq[cat], 16);
13156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        assert( i <= 63 );
13166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( i >= 63 ) break;
13176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
13186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
13196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn////////////////////// WJpegStream ///////////////////////
13216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennWJpegBitStream::WJpegBitStream()
13236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
13246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
13256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennWJpegBitStream::~WJpegBitStream()
13286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
13296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    Close();
13306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    m_is_opened = false;
13316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
13326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennbool  WJpegBitStream::Open( const char* filename )
13366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
13376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    Close();
13386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    Allocate();
13396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    m_is_opened = m_low_strm.Open( filename );
13416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( m_is_opened )
13426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
13436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        m_block_pos = 0;
13446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        ResetBuffer();
13456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
13466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return m_is_opened;
13476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
13486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid  WJpegBitStream::Close()
13516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
13526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( m_is_opened )
13536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
13546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        Flush();
13556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        m_low_strm.Close();
13566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        m_is_opened = false;
13576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
13586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
13596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid  WJpegBitStream::Flush()
13626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
13636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    Put( -1, m_bit_idx & 31 );
13646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    *((ulong*&)m_current)++ = m_val;
13656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    WriteBlock();
13666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ResetBuffer();
13676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
13686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid  WJpegBitStream::WriteBlock()
13716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
13726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    uchar* ptr = m_start;
13736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !bsIsBigEndian() )
13746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        bsBSwapBlock( m_start, m_current );
13756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    while( ptr < m_current )
13776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
13786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int val = *ptr++;
13796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        m_low_strm.PutByte( val );
13806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( val == 0xff )
13816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
13826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            m_low_strm.PutByte( 0 );
13836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
13846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
13856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    m_current = m_start;
13876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
13886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/////////////////////// GrFmtJpegWriter ///////////////////
13916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennGrFmtJpegWriter::GrFmtJpegWriter( const char* filename ) : GrFmtWriter( filename )
13936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
13946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
13956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennGrFmtJpegWriter::~GrFmtJpegWriter()
13976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
13986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
13996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//  Standard JPEG quantization tables
14016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic const uchar jpegTableK1_T[] =
14026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
14036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    16, 12, 14, 14,  18,  24,  49,  72,
14046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    11, 12, 13, 17,  22,  35,  64,  92,
14056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    10, 14, 16, 22,  37,  55,  78,  95,
14066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    16, 19, 24, 29,  56,  64,  87,  98,
14076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    24, 26, 40, 51,  68,  81, 103, 112,
14086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    40, 58, 57, 87, 109, 104, 121, 100,
14096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    51, 60, 69, 80, 103, 113, 120, 103,
14106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    61, 55, 56, 62,  77,  92, 101,  99
14116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn};
14126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic const uchar jpegTableK2_T[] =
14156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
14166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    17, 18, 24, 47, 99, 99, 99, 99,
14176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    18, 21, 26, 66, 99, 99, 99, 99,
14186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    24, 26, 56, 99, 99, 99, 99, 99,
14196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    47, 66, 99, 99, 99, 99, 99, 99,
14206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    99, 99, 99, 99, 99, 99, 99, 99,
14216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    99, 99, 99, 99, 99, 99, 99, 99,
14226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    99, 99, 99, 99, 99, 99, 99, 99,
14236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    99, 99, 99, 99, 99, 99, 99, 99
14246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn};
14256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Standard Huffman tables
14286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// ... for luma DCs.
14306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic const uchar jpegTableK3[] =
14316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
14326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
14336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
14346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn};
14356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// ... for chroma DCs.
14386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic const uchar jpegTableK4[] =
14396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
14406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
14416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
14426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn};
14436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// ... for luma ACs.
14466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic const uchar jpegTableK5[] =
14476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
14486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 125,
14496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
14506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
14516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
14526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
14536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
14546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
14556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
14566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
14576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
14586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
14596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
14606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
14616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
14626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
14636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
14646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
14656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
14666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
14676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
14686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
14696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0xf9, 0xfa
14706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn};
14716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// ... for chroma ACs
14736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic const uchar jpegTableK6[] =
14746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
14756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 119,
14766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
14776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
14786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
14796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
14806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
14816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
14826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
14836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
14846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
14856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
14866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
14876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
14886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
14896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
14906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
14916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
14926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
14936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
14946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
14956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
14966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0xf9, 0xfa
14976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn};
14986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic const char jpegHeader[] =
15016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    "\xFF\xD8"  // SOI  - start of image
15026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    "\xFF\xE0"  // APP0 - jfif extention
15036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    "\x00\x10"  // 2 bytes: length of APP0 segment
15046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    "JFIF\x00"  // JFIF signature
15056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    "\x01\x02"  // version of JFIF
15066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    "\x00"      // units = pixels ( 1 - inch, 2 - cm )
15076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    "\x00\x01\x00\x01" // 2 2-bytes values: x density & y density
15086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    "\x00\x00"; // width & height of thumbnail: ( 0x0 means no thumbnail)
15096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define postshift 14
15116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// FDCT with postscaling
15136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void aan_fdct8x8( int *src, int *dst,
15146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                         int step, const int *postscale )
15156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
15166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int  workspace[64], *work = workspace;
15176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int  i;
15186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // Pass 1: process rows
15206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 8; i > 0; i--, src += step, work += 8 )
15216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
15226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int x0 = src[0], x1 = src[7];
15236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int x2 = src[3], x3 = src[4];
15246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int x4 = x0 + x1; x0 -= x1;
15266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x1 = x2 + x3; x2 -= x3;
15276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        work[7] = x0; work[1] = x2;
15296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x2 = x4 + x1; x4 -= x1;
15306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x0 = src[1]; x3 = src[6];
15326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x1 = x0 + x3; x0 -= x3;
15336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        work[5] = x0;
15346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x0 = src[2]; x3 = src[5];
15366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        work[3] = x0 - x3; x0 += x3;
15376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x3 = x0 + x1; x0 -= x1;
15396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x1 = x2 + x3; x2 -= x3;
15406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        work[0] = x1; work[4] = x2;
15426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x0 = descale((x0 - x4)*C0_707, fixb);
15446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x1 = x4 + x0; x4 -= x0;
15456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        work[2] = x4; work[6] = x1;
15466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x0 = work[1]; x1 = work[3];
15486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x2 = work[5]; x3 = work[7];
15496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x0 += x1; x1 += x2; x2 += x3;
15516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x1 = descale(x1*C0_707, fixb);
15526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x4 = x1 + x3; x3 -= x1;
15546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x1 = (x0 - x2)*C0_382;
15556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x0 = descale(x0*C0_541 + x1, fixb);
15566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x2 = descale(x2*C1_306 + x1, fixb);
15576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x1 = x0 + x3; x3 -= x0;
15596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x0 = x4 + x2; x4 -= x2;
15606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        work[5] = x1; work[1] = x0;
15626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        work[7] = x4; work[3] = x3;
15636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
15646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    work = workspace;
15666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // pass 2: process columns
15676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 8; i > 0; i--, work++, postscale += 8, dst += 8 )
15686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
15696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int  x0 = work[8*0], x1 = work[8*7];
15706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int  x2 = work[8*3], x3 = work[8*4];
15716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int  x4 = x0 + x1; x0 -= x1;
15736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x1 = x2 + x3; x2 -= x3;
15746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        work[8*7] = x0; work[8*0] = x2;
15766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x2 = x4 + x1; x4 -= x1;
15776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x0 = work[8*1]; x3 = work[8*6];
15796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x1 = x0 + x3; x0 -= x3;
15806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        work[8*4] = x0;
15816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x0 = work[8*2]; x3 = work[8*5];
15836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        work[8*3] = x0 - x3; x0 += x3;
15846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x3 = x0 + x1; x0 -= x1;
15866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x1 = x2 + x3; x2 -= x3;
15876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        dst[0] = descale(x1*postscale[0], postshift);
15896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        dst[4] = descale(x2*postscale[4], postshift);
15906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x0 = descale((x0 - x4)*C0_707, fixb);
15926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x1 = x4 + x0; x4 -= x0;
15936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        dst[2] = descale(x4*postscale[2], postshift);
15956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        dst[6] = descale(x1*postscale[6], postshift);
15966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x0 = work[8*0]; x1 = work[8*3];
15986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x2 = work[8*4]; x3 = work[8*7];
15996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x0 += x1; x1 += x2; x2 += x3;
16016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x1 = descale(x1*C0_707, fixb);
16026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x4 = x1 + x3; x3 -= x1;
16046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x1 = (x0 - x2)*C0_382;
16056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x0 = descale(x0*C0_541 + x1, fixb);
16066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x2 = descale(x2*C1_306 + x1, fixb);
16076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x1 = x0 + x3; x3 -= x0;
16096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        x0 = x4 + x2; x4 -= x2;
16106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        dst[5] = descale(x1*postscale[5], postshift);
16126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        dst[1] = descale(x0*postscale[1], postshift);
16136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        dst[7] = descale(x4*postscale[7], postshift);
16146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        dst[3] = descale(x3*postscale[3], postshift);
16156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
16166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
16176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennbool  GrFmtJpegWriter::WriteImage( const uchar* data, int step,
16206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                   int width, int height, int /*depth*/, int _channels )
16216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
16226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert( data && width > 0 && height > 0 );
16236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !m_strm.Open( m_filename ) ) return false;
16256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // encode the header and tables
16276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // for each mcu:
16286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    //   convert rgb to yuv with downsampling (if color).
16296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    //   for every block:
16306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    //     calc dct and quantize
16316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    //     encode block.
16326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int x, y;
16336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, j;
16346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const int max_quality = 12;
16356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int   quality = max_quality;
16366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    WMByteStream& lowstrm = m_strm.m_low_strm;
16376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int   fdct_qtab[2][64];
16386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ulong huff_dc_tab[2][16];
16396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ulong huff_ac_tab[2][256];
16406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int  channels = _channels > 1 ? 3 : 1;
16416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int  x_scale = channels > 1 ? 2 : 1, y_scale = x_scale;
16426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int  dc_pred[] = { 0, 0, 0 };
16436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int  x_step = x_scale * 8;
16446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int  y_step = y_scale * 8;
16456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int  block[6][64];
16466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int  buffer[1024];
16476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int  luma_count = x_scale*y_scale;
16486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int  block_count = luma_count + channels - 1;
16496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int  Y_step = x_scale*8;
16506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const int UV_step = 16;
16516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double inv_quality;
16526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( quality < 3 ) quality = 3;
16546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( quality > max_quality ) quality = max_quality;
16556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    inv_quality = 1./quality;
16576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // Encode header
16596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    lowstrm.PutBytes( jpegHeader, sizeof(jpegHeader) - 1 );
16606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // Encode quantization tables
16626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < (channels > 1 ? 2 : 1); i++ )
16636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
16646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        const uchar* qtable = i == 0 ? jpegTableK1_T : jpegTableK2_T;
16656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int chroma_scale = i > 0 ? luma_count : 1;
16666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        lowstrm.PutWord( 0xffdb );   // DQT marker
16686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        lowstrm.PutWord( 2 + 65*1 ); // put single qtable
16696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        lowstrm.PutByte( 0*16 + i ); // 8-bit table
16706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        // put coefficients
16726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( j = 0; j < 64; j++ )
16736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
16746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int idx = zigzag[j];
16756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int qval = cvRound(qtable[idx]*inv_quality);
16766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( qval < 1 )
16776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                qval = 1;
16786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( qval > 255 )
16796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                qval = 255;
16806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            fdct_qtab[i][idx] = cvRound((1 << (postshift + 9))/
16816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                      (qval*chroma_scale*idct_prescale[idx]));
16826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            lowstrm.PutByte( qval );
16836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
16846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
16856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // Encode huffman tables
16876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < (channels > 1 ? 4 : 2); i++ )
16886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
16896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        const uchar* htable = i == 0 ? jpegTableK3 : i == 1 ? jpegTableK5 :
16906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              i == 2 ? jpegTableK4 : jpegTableK6;
16916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int is_ac_tab = i & 1;
16926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int idx = i >= 2;
16936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int tableSize = 16 + (is_ac_tab ? 162 : 12);
16946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        lowstrm.PutWord( 0xFFC4   );      // DHT marker
16966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        lowstrm.PutWord( 3 + tableSize ); // define one huffman table
16976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        lowstrm.PutByte( is_ac_tab*16 + idx ); // put DC/AC flag and table index
16986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        lowstrm.PutBytes( htable, tableSize ); // put table
16996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        bsCreateEncodeHuffmanTable( bsCreateSourceHuffmanTable(
17016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            htable, buffer, 16, 9 ), is_ac_tab ? huff_ac_tab[idx] :
17026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            huff_dc_tab[idx], is_ac_tab ? 256 : 16 );
17036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
17046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // put frame header
17066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    lowstrm.PutWord( 0xFFC0 );          // SOF0 marker
17076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    lowstrm.PutWord( 8 + 3*channels );  // length of frame header
17086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    lowstrm.PutByte( 8 );               // sample precision
17096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    lowstrm.PutWord( height );
17106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    lowstrm.PutWord( width );
17116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    lowstrm.PutByte( channels );        // number of components
17126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < channels; i++ )
17146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
17156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        lowstrm.PutByte( i + 1 );  // (i+1)-th component id (Y,U or V)
17166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( i == 0 )
17176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            lowstrm.PutByte(x_scale*16 + y_scale); // chroma scale factors
17186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
17196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            lowstrm.PutByte(1*16 + 1);
17206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        lowstrm.PutByte( i > 0 ); // quantization table idx
17216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
17226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // put scan header
17246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    lowstrm.PutWord( 0xFFDA );          // SOS marker
17256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    lowstrm.PutWord( 6 + 2*channels );  // length of scan header
17266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    lowstrm.PutByte( channels );        // number of components in the scan
17276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < channels; i++ )
17296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
17306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        lowstrm.PutByte( i+1 );             // component id
17316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        lowstrm.PutByte( (i>0)*16 + (i>0) );// selection of DC & AC tables
17326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
17336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    lowstrm.PutWord(0*256 + 63);// start and end of spectral selection - for
17356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                // sequental DCT start is 0 and end is 63
17366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    lowstrm.PutByte( 0 );  // successive approximation bit position
17386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                           // high & low - (0,0) for sequental DCT
17396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // encode data
17416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( y = 0; y < height; y += y_step, data += y_step*step )
17426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
17436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( x = 0; x < width; x += x_step )
17446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
17456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int x_limit = x_step;
17466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int y_limit = y_step;
17476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const uchar* rgb_data = data + x*_channels;
17486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int* Y_data = block[0];
17496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( x + x_limit > width ) x_limit = width - x;
17516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( y + y_limit > height ) y_limit = height - y;
17526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            memset( block, 0, block_count*64*sizeof(block[0][0]));
17546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( channels > 1 )
17566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
17576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int* UV_data = block[luma_count];
17586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( i = 0; i < y_limit; i++, rgb_data += step, Y_data += Y_step )
17606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
17616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    for( j = 0; j < x_limit; j++, rgb_data += _channels )
17626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
17636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        int r = rgb_data[2];
17646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        int g = rgb_data[1];
17656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        int b = rgb_data[0];
17666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        int Y = descale( r*y_r + g*y_g + b*y_b, fixc - 2) - 128*4;
17686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        int U = descale( r*cb_r + g*cb_g + b*cb_b, fixc - 2 );
17696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        int V = descale( r*cr_r + g*cr_g + b*cr_b, fixc - 2 );
17706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        int j2 = j >> (x_scale - 1);
17716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        Y_data[j] = Y;
17736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        UV_data[j2] += U;
17746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        UV_data[j2 + 8] += V;
17756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
17766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    rgb_data -= x_limit*_channels;
17786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if( ((i+1) & (y_scale - 1)) == 0 )
17796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
17806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        UV_data += UV_step;
17816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
17826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
17836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
17846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
17856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
17866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( i = 0; i < y_limit; i++, rgb_data += step, Y_data += Y_step )
17876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
17886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    for( j = 0; j < x_limit; j++ )
17896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        Y_data[j] = rgb_data[j]*4 - 128*4;
17906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
17916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
17926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( i = 0; i < block_count; i++ )
17946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
17956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int is_chroma = i >= luma_count;
17966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int src_step = x_scale * 8;
17976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int run = 0, val;
17986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int* src_ptr = block[i & -2] + (i & 1)*8;
17996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                const ulong* htable = huff_ac_tab[is_chroma];
18006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                aan_fdct8x8( src_ptr, buffer, src_step, fdct_qtab[is_chroma] );
18026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                j = is_chroma + (i > luma_count);
18046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                val = buffer[0] - dc_pred[j];
18056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dc_pred[j] = buffer[0];
18066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
18086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                float a = (float)val;
18096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int cat = (((int&)a >> 23) & 255) - (126 & (val ? -1 : 0));
18106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                assert( cat <= 11 );
18126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                m_strm.PutHuff( cat, huff_dc_tab[is_chroma] );
18136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                m_strm.Put( val - (val < 0 ? 1 : 0), cat );
18146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
18156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( j = 1; j < 64; j++ )
18176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
18186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    val = buffer[zigzag[j]];
18196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if( val == 0 )
18216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
18226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        run++;
18236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
18246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    else
18256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
18266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        while( run >= 16 )
18276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        {
18286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            m_strm.PutHuff( 0xF0, htable ); // encode 16 zeros
18296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            run -= 16;
18306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        }
18316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        {
18336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        float a = (float)val;
18346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        int cat = (((int&)a >> 23) & 255) - (126 & (val ? -1 : 0));
18356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        assert( cat <= 10 );
18376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        m_strm.PutHuff( cat + run*16, htable );
18386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        m_strm.Put( val - (val < 0 ? 1 : 0), cat );
18396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        }
18406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        run = 0;
18426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
18436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
18446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( run )
18466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
18476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    m_strm.PutHuff( 0x00, htable ); // encode EOB
18486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
18496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
18506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
18516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
18526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // Flush
18546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    m_strm.Flush();
18556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    lowstrm.PutWord( 0xFFD9 ); // EOI marker
18576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    m_strm.Close();
18586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return true;
18606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
18616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#endif
18636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* End of file. */
18656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1867