Update to 2.0.0 tree from current Fremantle build
[opencv] / otherlibs / highgui / grfmt_jpeg.cpp
diff --git a/otherlibs/highgui/grfmt_jpeg.cpp b/otherlibs/highgui/grfmt_jpeg.cpp
deleted file mode 100644 (file)
index 3235fe4..0000000
+++ /dev/null
@@ -1,1866 +0,0 @@
-/*M///////////////////////////////////////////////////////////////////////////////////////
-//
-//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
-//
-//  By downloading, copying, installing or using the software you agree to this license.
-//  If you do not agree to this license, do not download, install,
-//  copy or use the software.
-//
-//
-//                        Intel License Agreement
-//                For Open Source Computer Vision Library
-//
-// Copyright (C) 2000, Intel Corporation, all rights reserved.
-// Third party copyrights are property of their respective owners.
-//
-// Redistribution and use in source and binary forms, with or without modification,
-// are permitted provided that the following conditions are met:
-//
-//   * Redistribution's of source code must retain the above copyright notice,
-//     this list of conditions and the following disclaimer.
-//
-//   * Redistribution's in binary form must reproduce the above copyright notice,
-//     this list of conditions and the following disclaimer in the documentation
-//     and/or other materials provided with the distribution.
-//
-//   * The name of Intel Corporation may not be used to endorse or promote products
-//     derived from this software without specific prior written permission.
-//
-// This software is provided by the copyright holders and contributors "as is" and
-// any express or implied warranties, including, but not limited to, the implied
-// warranties of merchantability and fitness for a particular purpose are disclaimed.
-// In no event shall the Intel Corporation or contributors be liable for any direct,
-// indirect, incidental, special, exemplary, or consequential damages
-// (including, but not limited to, procurement of substitute goods or services;
-// loss of use, data, or profits; or business interruption) however caused
-// and on any theory of liability, whether in contract, strict liability,
-// or tort (including negligence or otherwise) arising in any way out of
-// the use of this software, even if advised of the possibility of such damage.
-//
-//M*/
-
-#include "_highgui.h"
-#include "grfmt_jpeg.h"
-
-// JPEG filter factory
-
-GrFmtJpeg::GrFmtJpeg()
-{
-    m_sign_len = 3;
-    m_signature = "\xFF\xD8\xFF";
-    m_description = "JPEG files (*.jpeg;*.jpg;*.jpe)";
-}
-
-
-GrFmtJpeg::~GrFmtJpeg()
-{
-}
-
-
-GrFmtReader* GrFmtJpeg::NewReader( const char* filename )
-{
-    return new GrFmtJpegReader( filename );
-}
-
-
-GrFmtWriter* GrFmtJpeg::NewWriter( const char* filename )
-{
-    return new GrFmtJpegWriter( filename );
-}
-
-
-#ifdef HAVE_JPEG
-
-/****************************************************************************************\
-    This part of the file implements JPEG codec on base of IJG libjpeg library,
-    in particular, this is the modified example.doc from libjpeg package.
-    See otherlibs/_graphics/readme.txt for copyright notice.
-\****************************************************************************************/
-
-#include <stdio.h>
-#include <setjmp.h>
-
-#ifdef WIN32
-
-#define XMD_H // prevent redefinition of INT32
-#undef FAR  // prevent FAR redefinition
-
-#endif
-
-#if defined WIN32 && defined __GNUC__
-typedef unsigned char boolean;
-#endif
-
-extern "C" {
-#include "jpeglib.h"
-}
-
-/////////////////////// Error processing /////////////////////
-
-typedef struct GrFmtJpegErrorMgr
-{
-    struct jpeg_error_mgr pub;    /* "parent" structure */
-    jmp_buf setjmp_buffer;        /* jump label */
-}
-GrFmtJpegErrorMgr;
-
-
-METHODDEF(void)
-error_exit( j_common_ptr cinfo )
-{
-    GrFmtJpegErrorMgr* err_mgr = (GrFmtJpegErrorMgr*)(cinfo->err);
-    
-    /* Return control to the setjmp point */
-    longjmp( err_mgr->setjmp_buffer, 1 );
-}
-
-
-/////////////////////// GrFmtJpegReader ///////////////////
-
-
-GrFmtJpegReader::GrFmtJpegReader( const char* filename ) : GrFmtReader( filename )
-{
-    m_cinfo = 0;
-    m_f = 0;
-}
-
-
-GrFmtJpegReader::~GrFmtJpegReader()
-{
-}
-
-
-void  GrFmtJpegReader::Close()
-{
-    if( m_f )
-    {
-        fclose( m_f );
-        m_f = 0;
-    }
-
-    if( m_cinfo )
-    {
-        jpeg_decompress_struct* cinfo = (jpeg_decompress_struct*)m_cinfo;
-        GrFmtJpegErrorMgr* jerr = (GrFmtJpegErrorMgr*)m_jerr;
-
-        jpeg_destroy_decompress( cinfo );
-        delete cinfo;
-        delete jerr;
-        m_cinfo = 0;
-        m_jerr = 0;
-    }
-    GrFmtReader::Close();
-}
-
-
-bool  GrFmtJpegReader::ReadHeader()
-{
-    bool result = false;
-    Close();
-
-    jpeg_decompress_struct* cinfo = new jpeg_decompress_struct;
-    GrFmtJpegErrorMgr* jerr = new GrFmtJpegErrorMgr;
-
-    cinfo->err = jpeg_std_error(&jerr->pub);
-    jerr->pub.error_exit = error_exit;
-
-    m_cinfo = cinfo;
-    m_jerr = jerr;
-
-    if( setjmp( jerr->setjmp_buffer ) == 0 )
-    {
-        jpeg_create_decompress( cinfo );
-
-        m_f = fopen( m_filename, "rb" );
-        if( m_f )
-        {
-            jpeg_stdio_src( cinfo, m_f );
-            jpeg_read_header( cinfo, TRUE );
-
-            m_width = cinfo->image_width;
-            m_height = cinfo->image_height;
-            m_iscolor = cinfo->num_components > 1;
-
-            result = true;
-        }
-    }
-
-    if( !result )
-        Close();
-
-    return result;
-}
-
-/***************************************************************************
- * following code is for supporting MJPEG image files
- * based on a message of Laurent Pinchart on the video4linux mailing list
- ***************************************************************************/
-
-/* JPEG DHT Segment for YCrCb omitted from MJPEG data */
-static
-unsigned char my_jpeg_odml_dht[0x1a4] = {
-    0xff, 0xc4, 0x01, 0xa2,
-
-    0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
-
-    0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-    0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
-
-    0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04,
-    0x04, 0x00, 0x00, 0x01, 0x7d,
-    0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06,
-    0x13, 0x51, 0x61, 0x07,
-    0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1,
-    0x15, 0x52, 0xd1, 0xf0,
-    0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a,
-    0x25, 0x26, 0x27, 0x28,
-    0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45,
-    0x46, 0x47, 0x48, 0x49,
-    0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65,
-    0x66, 0x67, 0x68, 0x69,
-    0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, 0x85,
-    0x86, 0x87, 0x88, 0x89,
-    0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3,
-    0xa4, 0xa5, 0xa6, 0xa7,
-    0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba,
-    0xc2, 0xc3, 0xc4, 0xc5,
-    0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
-    0xd9, 0xda, 0xe1, 0xe2,
-    0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4,
-    0xf5, 0xf6, 0xf7, 0xf8,
-    0xf9, 0xfa,
-
-    0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04,
-    0x04, 0x00, 0x01, 0x02, 0x77,
-    0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41,
-    0x51, 0x07, 0x61, 0x71,
-    0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1, 0xc1, 0x09,
-    0x23, 0x33, 0x52, 0xf0,
-    0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17,
-    0x18, 0x19, 0x1a, 0x26,
-    0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44,
-    0x45, 0x46, 0x47, 0x48,
-    0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64,
-    0x65, 0x66, 0x67, 0x68,
-    0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83,
-    0x84, 0x85, 0x86, 0x87,
-    0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a,
-    0xa2, 0xa3, 0xa4, 0xa5,
-    0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8,
-    0xb9, 0xba, 0xc2, 0xc3,
-    0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
-    0xd7, 0xd8, 0xd9, 0xda,
-    0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4,
-    0xf5, 0xf6, 0xf7, 0xf8,
-    0xf9, 0xfa
-};
-
-/*
- * Parse the DHT table.
- * This code comes from jpeg6b (jdmarker.c).
- */
-static
-int my_jpeg_load_dht (struct jpeg_decompress_struct *info, unsigned char *dht,
-              JHUFF_TBL *ac_tables[], JHUFF_TBL *dc_tables[])
-{
-    unsigned int length = (dht[2] << 8) + dht[3] - 2;
-    unsigned int pos = 4;
-    unsigned int count, i;
-    int index;
-
-    JHUFF_TBL **hufftbl;
-    unsigned char bits[17];
-    unsigned char huffval[256];
-
-    while (length > 16)
-    {
-       bits[0] = 0;
-       index = dht[pos++];
-       count = 0;
-       for (i = 1; i <= 16; ++i)
-       {
-           bits[i] = dht[pos++];
-           count += bits[i];
-       }
-       length -= 17;
-
-       if (count > 256 || count > length)
-           return -1;
-    
-       for (i = 0; i < count; ++i)
-           huffval[i] = dht[pos++];
-       length -= count;
-
-       if (index & 0x10)
-       {
-           index -= 0x10;
-           hufftbl = &ac_tables[index];
-       }
-       else
-           hufftbl = &dc_tables[index];
-    
-       if (index < 0 || index >= NUM_HUFF_TBLS)
-           return -1;
-    
-       if (*hufftbl == NULL)
-           *hufftbl = jpeg_alloc_huff_table ((j_common_ptr)info);
-       if (*hufftbl == NULL)
-           return -1;
-
-       memcpy ((*hufftbl)->bits, bits, sizeof (*hufftbl)->bits);
-       memcpy ((*hufftbl)->huffval, huffval, sizeof (*hufftbl)->huffval);
-    }
-    
-    if (length != 0)
-       return -1;
-    
-    return 0;
-}
-
-/***************************************************************************
- * end of code for supportting MJPEG image files
- * based on a message of Laurent Pinchart on the video4linux mailing list
- ***************************************************************************/
-
-bool  GrFmtJpegReader::ReadData( uchar* data, int step, int color )
-{
-    bool result = false;
-
-    color = color > 0 || (m_iscolor && color < 0);
-    
-    if( m_cinfo && m_jerr && m_width && m_height )
-    {
-        jpeg_decompress_struct* cinfo = (jpeg_decompress_struct*)m_cinfo;
-        GrFmtJpegErrorMgr* jerr = (GrFmtJpegErrorMgr*)m_jerr;
-        JSAMPARRAY buffer = 0;
-        
-        if( setjmp( jerr->setjmp_buffer ) == 0 )
-        {
-            /* check if this is a mjpeg image format */
-            if ( cinfo->ac_huff_tbl_ptrs[0] == NULL &&
-                cinfo->ac_huff_tbl_ptrs[1] == NULL &&
-                cinfo->dc_huff_tbl_ptrs[0] == NULL &&
-                cinfo->dc_huff_tbl_ptrs[1] == NULL )
-            {
-                /* yes, this is a mjpeg image format, so load the correct
-                huffman table */
-                my_jpeg_load_dht( cinfo,
-                    my_jpeg_odml_dht,
-                    cinfo->ac_huff_tbl_ptrs,
-                    cinfo->dc_huff_tbl_ptrs );
-            }
-
-            if( color > 0 || (m_iscolor && color < 0) )
-            {
-                color = 1;
-                if( cinfo->num_components != 4 )
-                {
-                    cinfo->out_color_space = JCS_RGB;
-                    cinfo->out_color_components = 3;
-                }
-                else
-                {
-                    cinfo->out_color_space = JCS_CMYK;
-                    cinfo->out_color_components = 4;
-                }
-            }
-            else
-            {
-                color = 0;
-                if( cinfo->num_components != 4 )
-                {
-                    cinfo->out_color_space = JCS_GRAYSCALE;
-                    cinfo->out_color_components = 1;
-                }
-                else
-                {
-                    cinfo->out_color_space = JCS_CMYK;
-                    cinfo->out_color_components = 4;
-                }
-            }
-
-            jpeg_start_decompress( cinfo );
-
-            buffer = (*cinfo->mem->alloc_sarray)((j_common_ptr)cinfo,
-                                              JPOOL_IMAGE, m_width*4, 1 );
-
-            for( ; m_height--; data += step )
-            {
-                jpeg_read_scanlines( cinfo, buffer, 1 );
-                if( color )
-                {
-                    if( cinfo->out_color_components == 3 )
-                        icvCvt_RGB2BGR_8u_C3R( buffer[0], 0, data, 0, cvSize(m_width,1) );
-                    else
-                        icvCvt_CMYK2BGR_8u_C4C3R( buffer[0], 0, data, 0, cvSize(m_width,1) );
-                }
-                else
-                {
-                    if( cinfo->out_color_components == 1 )
-                        memcpy( data, buffer[0], m_width );
-                    else
-                        icvCvt_CMYK2Gray_8u_C4C1R( buffer[0], 0, data, 0, cvSize(m_width,1) );
-                }
-            }
-            result = true;
-            jpeg_finish_decompress( cinfo );
-        }
-    }
-
-    Close();
-    return result;
-}
-
-
-/////////////////////// GrFmtJpegWriter ///////////////////
-
-GrFmtJpegWriter::GrFmtJpegWriter( const char* filename ) : GrFmtWriter( filename )
-{
-}
-
-
-GrFmtJpegWriter::~GrFmtJpegWriter()
-{
-}
-
-
-bool  GrFmtJpegWriter::WriteImage( const uchar* data, int step,
-                                   int width, int height, int /*depth*/, int _channels )
-{
-    const int default_quality = 95;
-    struct jpeg_compress_struct cinfo;
-    GrFmtJpegErrorMgr jerr;
-
-    bool result = false;
-    FILE* f = 0;
-    int channels = _channels > 1 ? 3 : 1;
-    uchar* buffer = 0; // temporary buffer for row flipping
-    
-    cinfo.err = jpeg_std_error(&jerr.pub);
-    jerr.pub.error_exit = error_exit;
-
-    if( setjmp( jerr.setjmp_buffer ) == 0 )
-    {
-        jpeg_create_compress(&cinfo);
-        f = fopen( m_filename, "wb" );
-
-        if( f )
-        {
-            jpeg_stdio_dest( &cinfo, f );
-
-            cinfo.image_width = width;
-            cinfo.image_height = height;
-            cinfo.input_components = channels;
-            cinfo.in_color_space = channels > 1 ? JCS_RGB : JCS_GRAYSCALE;
-
-            jpeg_set_defaults( &cinfo );
-            jpeg_set_quality( &cinfo, default_quality,
-                              TRUE /* limit to baseline-JPEG values */ );
-            jpeg_start_compress( &cinfo, TRUE );
-
-            if( channels > 1 )
-                buffer = new uchar[width*channels];
-
-            for( ; height--; data += step )
-            {
-                uchar* ptr = (uchar*)data;
-            
-                if( _channels == 3 )
-                {
-                    icvCvt_BGR2RGB_8u_C3R( data, 0, buffer, 0, cvSize(width,1) );
-                    ptr = buffer;
-                }
-                else if( _channels == 4 )
-                {
-                    icvCvt_BGRA2BGR_8u_C4C3R( data, 0, buffer, 0, cvSize(width,1), 2 );
-                    ptr = buffer;
-                }
-
-                jpeg_write_scanlines( &cinfo, &ptr, 1 );
-            }
-
-            jpeg_finish_compress( &cinfo );
-            result = true;
-        }
-    }
-
-    if(f) fclose(f);
-    jpeg_destroy_compress( &cinfo );
-
-    delete[] buffer;
-    return result;
-}
-
-#else
-
-//////////////////////  JPEG-oriented two-level bitstream ////////////////////////
-
-RJpegBitStream::RJpegBitStream()
-{
-}
-
-RJpegBitStream::~RJpegBitStream()
-{
-    Close();
-}
-
-
-bool  RJpegBitStream::Open( const char* filename )
-{
-    Close();
-    Allocate();
-    
-    m_is_opened = m_low_strm.Open( filename );
-    if( m_is_opened ) SetPos(0);
-    return m_is_opened;
-}
-
-
-void  RJpegBitStream::Close()
-{
-    m_low_strm.Close();
-    m_is_opened = false;
-}
-
-
-void  RJpegBitStream::ReadBlock()
-{
-    uchar* end = m_start + m_block_size;
-    uchar* current = m_start;
-
-    if( setjmp( m_low_strm.JmpBuf()) == 0 )
-    {
-        int sz = m_unGetsize;
-        memmove( current - sz, m_end - sz, sz );
-        while( current < end )
-        {
-            int val = m_low_strm.GetByte();
-            if( val != 0xff )
-            {
-                *current++ = (uchar)val;
-            }
-            else
-            {
-                val = m_low_strm.GetByte();
-                if( val == 0 )
-                    *current++ = 0xFF;
-                else if( !(0xD0 <= val && val <= 0xD7) )
-                {
-                    m_low_strm.SetPos( m_low_strm.GetPos() - 2 );
-                    goto fetch_end;
-                }
-            }
-        }
-fetch_end: ;
-    }
-    else
-    {
-        if( current == m_start && m_jmp_set )
-            longjmp( m_jmp_buf, RBS_THROW_EOS );
-    }
-    m_current = m_start;
-    m_end = m_start + (((current - m_start) + 3) & -4);
-    if( !bsIsBigEndian() )
-        bsBSwapBlock( m_start, m_end );
-}
-
-
-void  RJpegBitStream::Flush()
-{
-    m_end = m_start + m_block_size;
-    m_current = m_end - 4;
-    m_bit_idx = 0;
-}
-
-void  RJpegBitStream::AlignOnByte()
-{
-    m_bit_idx &= -8;
-}
-
-int  RJpegBitStream::FindMarker()
-{
-    int code = m_low_strm.GetWord();
-    while( (code & 0xFF00) != 0xFF00 || (code == 0xFFFF || code == 0xFF00 ))
-    {
-        code = ((code&255) << 8) | m_low_strm.GetByte();
-    }
-    return code;
-}
-
-
-/****************************** JPEG (JFIF) reader ***************************/
-
-// zigzag & IDCT prescaling (AAN algorithm) tables
-static const uchar zigzag[] =
-{
-  0,  8,  1,  2,  9, 16, 24, 17, 10,  3,  4, 11, 18, 25, 32, 40,
- 33, 26, 19, 12,  5,  6, 13, 20, 27, 34, 41, 48, 56, 49, 42, 35,
- 28, 21, 14,  7, 15, 22, 29, 36, 43, 50, 57, 58, 51, 44, 37, 30,
- 23, 31, 38, 45, 52, 59, 60, 53, 46, 39, 47, 54, 61, 62, 55, 63,
- 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63
-};
-
-
-static const int idct_prescale[] =
-{
-    16384, 22725, 21407, 19266, 16384, 12873,  8867,  4520,
-    22725, 31521, 29692, 26722, 22725, 17855, 12299,  6270,
-    21407, 29692, 27969, 25172, 21407, 16819, 11585,  5906,
-    19266, 26722, 25172, 22654, 19266, 15137, 10426,  5315,
-    16384, 22725, 21407, 19266, 16384, 12873,  8867,  4520,
-    12873, 17855, 16819, 15137, 12873, 10114,  6967,  3552,
-     8867, 12299, 11585, 10426,  8867,  6967,  4799,  2446,
-     4520,  6270,  5906,  5315,  4520,  3552,  2446,  1247
-};
-
-
-#define fixb         14
-#define fix(x, n)    (int)((x)*(1 << (n)) + .5)
-#define fix1(x, n)   (x)
-#define fixmul(x)    (x)
-
-#define C0_707     fix( 0.707106781f, fixb )
-#define C0_924     fix( 0.923879533f, fixb )
-#define C0_541     fix( 0.541196100f, fixb )
-#define C0_382     fix( 0.382683432f, fixb )
-#define C1_306     fix( 1.306562965f, fixb )
-
-#define C1_082     fix( 1.082392200f, fixb )
-#define C1_414     fix( 1.414213562f, fixb )
-#define C1_847     fix( 1.847759065f, fixb )
-#define C2_613     fix( 2.613125930f, fixb )
-
-#define fixc       12
-#define b_cb       fix( 1.772, fixc )
-#define g_cb      -fix( 0.34414, fixc )
-#define g_cr      -fix( 0.71414, fixc )
-#define r_cr       fix( 1.402, fixc )
-
-#define y_r        fix( 0.299, fixc )
-#define y_g        fix( 0.587, fixc )
-#define y_b        fix( 0.114, fixc )
-
-#define cb_r      -fix( 0.1687, fixc )
-#define cb_g      -fix( 0.3313, fixc )
-#define cb_b       fix( 0.5,    fixc )
-
-#define cr_r       fix( 0.5,    fixc )
-#define cr_g      -fix( 0.4187, fixc )
-#define cr_b      -fix( 0.0813, fixc )
-
-
-// IDCT without prescaling
-static void aan_idct8x8( int *src, int *dst, int step )
-{
-    int   workspace[64], *work = workspace;
-    int   i;
-
-    /* Pass 1: process rows */
-    for( i = 8; i > 0; i--, src += 8, work += 8 )
-    {
-        /* Odd part */
-        int  x0 = src[5], x1 = src[3];
-        int  x2 = src[1], x3 = src[7];
-
-        int  x4 = x0 + x1; x0 -= x1;
-
-        x1 = x2 + x3; x2 -= x3;
-        x3 = x1 + x4; x1 -= x4;
-
-        x4 = (x0 + x2)*C1_847;
-        x0 = descale( x4 - x0*C2_613, fixb);
-        x2 = descale( x2*C1_082 - x4, fixb);
-        x1 = descale( x1*C1_414, fixb);
-
-        x0 -= x3;
-        x1 -= x0;
-        x2 += x1;
-
-        work[7] = x3; work[6] = x0;
-        work[5] = x1; work[4] = x2;
-
-        /* Even part */
-        x2 = src[2]; x3 = src[6];
-        x0 = src[0]; x1 = src[4];
-
-        x4 = x2 + x3;
-        x2 = descale((x2-x3)*C1_414, fixb) - x4;
-
-        x3 = x0 + x1; x0 -= x1;
-        x1 = x3 + x4; x3 -= x4;
-        x4 = x0 + x2; x0 -= x2;
-
-        x2 = work[7];
-        x1 -= x2; x2 = 2*x2 + x1;
-        work[7] = x1; work[0] = x2;
-
-        x2 = work[6];
-        x1 = x4 + x2; x4 -= x2;
-        work[1] = x1; work[6] = x4;
-
-        x1 = work[5]; x2 = work[4];
-        x4 = x0 + x1; x0 -= x1;
-        x1 = x3 + x2; x3 -= x2;
-
-        work[2] = x4; work[5] = x0;
-        work[3] = x3; work[4] = x1;
-    }
-
-    /* Pass 2: process columns */
-    work = workspace;
-    for( i = 8; i > 0; i--, dst += step, work++ )
-    {
-        /* Odd part */
-        int  x0 = work[8*5], x1 = work[8*3];
-        int  x2 = work[8*1], x3 = work[8*7];
-
-        int  x4 = x0 + x1; x0 -= x1;
-        x1 = x2 + x3; x2 -= x3;
-        x3 = x1 + x4; x1 -= x4;
-
-        x4 = (x0 + x2)*C1_847;
-        x0 = descale( x4 - x0*C2_613, fixb);
-        x2 = descale( x2*C1_082 - x4, fixb);
-        x1 = descale( x1*C1_414, fixb);
-
-        x0 -= x3;
-        x1 -= x0;
-        x2 += x1;
-
-        dst[7] = x3; dst[6] = x0;
-        dst[5] = x1; dst[4] = x2;
-
-        /* Even part */
-        x2 = work[8*2]; x3 = work[8*6];
-        x0 = work[8*0]; x1 = work[8*4];
-
-        x4 = x2 + x3;
-        x2 = descale((x2-x3)*C1_414, fixb) - x4;
-
-        x3 = x0 + x1; x0 -= x1;
-        x1 = x3 + x4; x3 -= x4;
-        x4 = x0 + x2; x0 -= x2;
-
-        x2 = dst[7];
-        x1 -= x2; x2 = 2*x2 + x1;
-        x1 = descale(x1,3);
-        x2 = descale(x2,3);
-
-        dst[7] = x1; dst[0] = x2;
-
-        x2 = dst[6];
-        x1 = descale(x4 + x2,3);
-        x4 = descale(x4 - x2,3);
-        dst[1] = x1; dst[6] = x4;
-
-        x1 = dst[5]; x2 = dst[4];
-
-        x4 = descale(x0 + x1,3);
-        x0 = descale(x0 - x1,3);
-        x1 = descale(x3 + x2,3);
-        x3 = descale(x3 - x2,3);
-       
-        dst[2] = x4; dst[5] = x0;
-        dst[3] = x3; dst[4] = x1;
-    }
-}
-
-
-static const int max_dec_htable_size = 1 << 12;
-static const int first_table_bits = 9;
-
-GrFmtJpegReader::GrFmtJpegReader( const char* filename ) : GrFmtReader( filename )
-{
-    m_planes= -1;
-    m_offset= -1;
-
-    int i;
-    for( i = 0; i < 4; i++ )
-    {
-        m_td[i] = new short[max_dec_htable_size];
-        m_ta[i] = new short[max_dec_htable_size];
-    }
-}
-
-
-GrFmtJpegReader::~GrFmtJpegReader()
-{
-    for( int i = 0; i < 4; i++ )
-    {
-        delete[] m_td[i];
-        m_td[i] = 0;
-        delete[] m_ta[i];
-        m_ta[i] = 0;
-    }
-}
-
-
-void  GrFmtJpegReader::Close()
-{
-    m_strm.Close();
-    GrFmtReader::Close();
-}
-
-
-bool GrFmtJpegReader::ReadHeader()
-{
-    char buffer[16];
-    int  i;
-    bool result = false, is_sof = false, 
-         is_qt = false, is_ht = false, is_sos = false;
-    
-    assert( strlen(m_filename) != 0 );
-    if( !m_strm.Open( m_filename )) return false;
-
-    memset( m_is_tq, 0, sizeof(m_is_tq));
-    memset( m_is_td, 0, sizeof(m_is_td));
-    memset( m_is_ta, 0, sizeof(m_is_ta));
-    m_MCUs = 0;
-
-    if( setjmp( m_strm.JmpBuf()) == 0 )
-    {
-        RMByteStream& lstrm = m_strm.m_low_strm;
-        
-        lstrm.Skip( 2 ); // skip SOI marker
-        
-        for(;;)
-        {
-            int marker = m_strm.FindMarker() & 255;
-
-            // check for standalone markers
-            if( marker != 0xD8 /* SOI */ && marker != 0xD9 /* EOI */ &&
-                marker != 0x01 /* TEM */ && !( 0xD0 <= marker && marker <= 0xD7 ))
-            {
-                int pos    = lstrm.GetPos();
-                int length = lstrm.GetWord();
-            
-                switch( marker )
-                {
-                case 0xE0: // APP0
-                    lstrm.GetBytes( buffer, 5 );
-                    if( strcmp(buffer, "JFIF") == 0 ) // JFIF identification
-                    {
-                        m_version = lstrm.GetWord();
-                        //is_jfif = true;
-                    }
-                    break;
-
-                case 0xC0: // SOF0
-                    m_precision = lstrm.GetByte();
-                    m_height = lstrm.GetWord();
-                    m_width = lstrm.GetWord();
-                    m_planes = lstrm.GetByte();
-
-                    if( m_width == 0 || m_height == 0 || // DNL not supported
-                       (m_planes != 1 && m_planes != 3)) goto parsing_end;
-
-                    m_iscolor = m_planes == 3;
-                
-                    memset( m_ci, -1, sizeof(m_ci));
-
-                    for( i = 0; i < m_planes; i++ )
-                    {
-                        int idx = lstrm.GetByte();
-
-                        if( idx < 1 || idx > m_planes ) // wrong index
-                        {
-                            idx = i+1; // hack
-                        }
-                        cmp_info& ci = m_ci[idx-1];
-                        
-                        if( ci.tq > 0 /* duplicated description */) goto parsing_end;
-
-                        ci.h = (char)lstrm.GetByte();
-                        ci.v = (char)(ci.h & 15);
-                        ci.h >>= 4;
-                        ci.tq = (char)lstrm.GetByte();
-                        if( !((ci.h == 1 || ci.h == 2 || ci.h == 4) &&
-                              (ci.v == 1 || ci.v == 2 || ci.v == 4) &&
-                              ci.tq < 3) ||
-                            // chroma mcu-parts should have equal sizes and
-                            // be non greater then luma sizes
-                            !( i != 2 || (ci.h == m_ci[1].h && ci.v == m_ci[1].v &&
-                                          ci.h <= m_ci[0].h && ci.v <= m_ci[0].v)))
-                            goto parsing_end;
-                    }
-                    is_sof = true;
-                    m_type = marker - 0xC0;
-                    break;
-
-                case 0xDB: // DQT
-                    if( !LoadQuantTables( length )) goto parsing_end;
-                    is_qt = true;
-                    break;
-
-                case 0xC4: // DHT
-                    if( !LoadHuffmanTables( length )) goto parsing_end;
-                    is_ht = true;
-                    break;
-
-                case 0xDA: // SOS
-                    is_sos = true;
-                    m_offset = pos - 2;
-                    goto parsing_end;
-
-                case 0xDD: // DRI
-                    m_MCUs = lstrm.GetWord();
-                    break;
-                }
-                lstrm.SetPos( pos + length );
-            }
-        }
-parsing_end: ;
-    }
-
-    result = /*is_jfif &&*/ is_sof && is_qt && is_ht && is_sos;
-    if( !result )
-    {
-        m_width = m_height = -1;
-        m_offset = -1;
-        m_strm.Close();
-    }
-    return result;
-}
-
-
-bool GrFmtJpegReader::LoadQuantTables( int length )
-{
-    uchar buffer[128];
-    int  i, tq_size;
-    
-    RMByteStream& lstrm = m_strm.m_low_strm;
-    length -= 2;
-
-    while( length > 0 )
-    {
-        int tq = lstrm.GetByte();
-        int size = tq >> 4;
-        tq &= 15;
-
-        tq_size = (64<<size) + 1; 
-        if( tq > 3 || size > 1 || length < tq_size ) return false;
-        length -= tq_size;
-
-        lstrm.GetBytes( buffer, tq_size - 1 );
-        
-        if( size == 0 ) // 8 bit quant factors
-        {
-            for( i = 0; i < 64; i++ )
-            {
-                int idx = zigzag[i];
-                m_tq[tq][idx] = buffer[i] * 16 * idct_prescale[idx];
-            }
-        }
-        else // 16 bit quant factors
-        {
-            for( i = 0; i < 64; i++ )
-            {
-                int idx = zigzag[i];
-                m_tq[tq][idx] = ((unsigned short*)buffer)[i] * idct_prescale[idx];
-            }
-        }
-        m_is_tq[tq] = true;
-    }
-
-    return true;
-}
-
-
-bool GrFmtJpegReader::LoadHuffmanTables( int length )
-{
-    const int max_bits = 16;
-    uchar buffer[1024];
-    int  buffer2[1024];
-
-    int  i, ht_size;
-    RMByteStream& lstrm = m_strm.m_low_strm;
-    length -= 2;
-
-    while( length > 0 )
-    {
-        int t = lstrm.GetByte();
-        int hclass = t >> 4;
-        t &= 15;
-
-        if( t > 3 || hclass > 1 || length < 17 ) return false;
-        length -= 17;
-
-        lstrm.GetBytes( buffer, max_bits );
-        for( i = 0, ht_size = 0; i < max_bits; i++ ) ht_size += buffer[i];
-
-        if( length < ht_size ) return false;
-        length -= ht_size;
-
-        lstrm.GetBytes( buffer + max_bits, ht_size );
-        
-        if( !::bsCreateDecodeHuffmanTable( 
-                  ::bsCreateSourceHuffmanTable( 
-                        buffer, buffer2, max_bits, first_table_bits ),
-                        hclass == 0 ? m_td[t] : m_ta[t], 
-                        max_dec_htable_size )) return false;
-        if( hclass == 0 )
-            m_is_td[t] = true;
-        else
-            m_is_ta[t] = true;
-    }
-    return true;
-}
-
-
-bool GrFmtJpegReader::ReadData( uchar* data, int step, int color )
-{
-    if( m_offset < 0 || !m_strm.IsOpened())
-        return false;
-
-    if( setjmp( m_strm.JmpBuf()) == 0 )
-    {
-        RMByteStream& lstrm = m_strm.m_low_strm;
-        lstrm.SetPos( m_offset );
-
-        for(;;)
-        {
-            int marker = m_strm.FindMarker() & 255;
-
-            if( marker == 0xD8 /* SOI */ || marker == 0xD9 /* EOI */ )
-                goto decoding_end;
-
-            // check for standalone markers
-            if( marker != 0x01 /* TEM */ && !( 0xD0 <= marker && marker <= 0xD7 ))
-            {
-                int pos    = lstrm.GetPos();
-                int length = lstrm.GetWord();
-            
-                switch( marker )
-                {
-                case 0xC4: // DHT
-                    if( !LoadHuffmanTables( length )) goto decoding_end;
-                    break;
-
-                case 0xDA: // SOS
-                    // read scan header
-                    {
-                        int idx[3] = { -1, -1, -1 };
-                        int i, ns = lstrm.GetByte();
-                        int sum = 0, a; // spectral selection & approximation
-
-                        if( ns != m_planes ) goto decoding_end;
-                        for( i = 0; i < ns; i++ )
-                        {
-                            int td, ta, c = lstrm.GetByte() - 1;
-                            if( c < 0 || m_planes <= c )
-                            {
-                                c = i; // hack
-                            }
-                            
-                            if( idx[c] != -1 ) goto decoding_end;
-                            idx[i] = c;
-                            td = lstrm.GetByte();
-                            ta = td & 15;
-                            td >>= 4;
-                            if( !(ta <= 3 && m_is_ta[ta] && 
-                                  td <= 3 && m_is_td[td] &&
-                                  m_is_tq[m_ci[c].tq]) )
-                                goto decoding_end;
-
-                            m_ci[c].td = (char)td;
-                            m_ci[c].ta = (char)ta;
-
-                            sum += m_ci[c].h*m_ci[c].v;
-                        }
-
-                        if( sum > 10 ) goto decoding_end;
-
-                        m_ss = lstrm.GetByte();
-                        m_se = lstrm.GetByte();
-
-                        a = lstrm.GetByte();
-                        m_al = a & 15;
-                        m_ah = a >> 4;
-
-                        ProcessScan( idx, ns, data, step, color );
-                        goto decoding_end; // only single scan case is supported now
-                    }
-
-                    //m_offset = pos - 2;
-                    //break;
-
-                case 0xDD: // DRI
-                    m_MCUs = lstrm.GetWord();
-                    break;
-                }
-                
-                if( marker != 0xDA ) lstrm.SetPos( pos + length );
-            }
-        }
-decoding_end: ;
-    }
-
-    return true;
-}
-
-
-void  GrFmtJpegReader::ResetDecoder()
-{
-    m_ci[0].dc_pred = m_ci[1].dc_pred = m_ci[2].dc_pred = 0; 
-}
-
-void  GrFmtJpegReader::ProcessScan( int* idx, int ns, uchar* data, int step, int color )
-{
-    int   i, s = 0, mcu, x1 = 0, y1 = 0;
-    int   temp[64];
-    int   blocks[10][64];
-    int   pos[3], h[3], v[3];
-    int   x_shift = 0, y_shift = 0;
-    int   nch = color ? 3 : 1;
-
-    assert( ns == m_planes && m_ss == 0 && m_se == 63 &&
-            m_al == 0 && m_ah == 0 ); // sequental & single scan
-
-    assert( idx[0] == 0 && (ns ==1 || (idx[1] == 1 && idx[2] == 2)));
-
-    for( i = 0; i < ns; i++ )
-    {
-        int c = idx[i];
-        h[c] = m_ci[c].h*8;
-        v[c] = m_ci[c].v*8;
-        pos[c] = s >> 6;
-        s += h[c]*v[c];
-    }
-
-    if( ns == 3 )
-    {
-        x_shift = h[0]/(h[1]*2);
-        y_shift = v[0]/(v[1]*2);
-    }
-
-    m_strm.Flush();
-    ResetDecoder();
-
-    for( mcu = 0;; mcu++ )
-    {
-        int  x2, y2, x, y, xc;
-        int* cmp;
-        uchar* data1;
-        
-        if( mcu == m_MCUs && m_MCUs != 0 )
-        {
-            ResetDecoder();
-            m_strm.AlignOnByte();
-            mcu = 0;
-        }
-
-        // Get mcu
-        for( i = 0; i < ns; i++ )
-        {
-            int  c = idx[i];
-            cmp = blocks[pos[c]];
-            for( y = 0; y < v[c]; y += 8, cmp += h[c]*8 )
-                for( x = 0; x < h[c]; x += 8 )
-                {
-                    GetBlock( temp, c );
-                    if( i < (color ? 3 : 1))
-                    {
-                        aan_idct8x8( temp, cmp + x, h[c] );
-                    }
-                }
-        }
-
-        y2 = v[0];
-        x2 = h[0];
-
-        if( y1 + y2 > m_height ) y2 = m_height - y1;
-        if( x1 + x2 > m_width ) x2 = m_width - x1;
-
-        cmp = blocks[0];
-        data1 = data + x1*nch;
-
-        if( ns == 1 )
-            for( y = 0; y < y2; y++, data1 += step, cmp += h[0] )
-            {
-                if( color )
-                {
-                    for( x = 0; x < x2; x++ )
-                    {
-                        int val = descale( cmp[x] + 128*4, 2 );
-                        data1[x*3] = data1[x*3 + 1] = data1[x*3 + 2] = saturate( val );
-                    }
-                }
-                else
-                {
-                    for( x = 0; x < x2; x++ )
-                    {
-                        int val = descale( cmp[x] + 128*4, 2 );
-                        data1[x] = saturate( val );
-                    }
-                }
-            }
-        else
-        {
-            for( y = 0; y < y2; y++, data1 += step, cmp += h[0] )
-            {
-                if( color )
-                {
-                    int  shift = h[1]*(y >> y_shift);
-                    int* cmpCb = blocks[pos[1]] + shift; 
-                    int* cmpCr = blocks[pos[2]] + shift;
-                    x = 0;
-                    if( x_shift == 0 )
-                    {
-                        for( ; x < x2; x++ )
-                        {
-                            int Y  = (cmp[x] + 128*4) << fixc;
-                            int Cb = cmpCb[x];
-                            int Cr = cmpCr[x];
-                            int t = (Y + Cb*b_cb) >> (fixc + 2);
-                            data1[x*3] = saturate(t);
-                            t = (Y + Cb*g_cb + Cr*g_cr) >> (fixc + 2);
-                            data1[x*3 + 1] = saturate(t);
-                            t = (Y + Cr*r_cr) >> (fixc + 2);
-                            data1[x*3 + 2] = saturate(t);
-                        }
-                    }
-                    else if( x_shift == 1 )
-                    {
-                        for( xc = 0; x <= x2 - 2; x += 2, xc++ )
-                        {
-                            int Y  = (cmp[x] + 128*4) << fixc;
-                            int Cb = cmpCb[xc];
-                            int Cr = cmpCr[xc];
-                            int t = (Y + Cb*b_cb) >> (fixc + 2);
-                            data1[x*3] = saturate(t);
-                            t = (Y + Cb*g_cb + Cr*g_cr) >> (fixc + 2);
-                            data1[x*3 + 1] = saturate(t);
-                            t = (Y + Cr*r_cr) >> (fixc + 2);
-                            data1[x*3 + 2] = saturate(t);
-                            Y = (cmp[x+1] + 128*4) << fixc;
-                            t = (Y + Cb*b_cb) >> (fixc + 2);
-                            data1[x*3 + 3] = saturate(t);
-                            t = (Y + Cb*g_cb + Cr*g_cr) >> (fixc + 2);
-                            data1[x*3 + 4] = saturate(t);
-                            t = (Y + Cr*r_cr) >> (fixc + 2);
-                            data1[x*3 + 5] = saturate(t);
-                        }
-                    }
-                    for( ; x < x2; x++ )
-                    {
-                        int Y  = (cmp[x] + 128*4) << fixc;
-                        int Cb = cmpCb[x >> x_shift];
-                        int Cr = cmpCr[x >> x_shift];
-                        int t = (Y + Cb*b_cb) >> (fixc + 2);
-                        data1[x*3] = saturate(t);
-                        t = (Y + Cb*g_cb + Cr*g_cr) >> (fixc + 2);
-                        data1[x*3 + 1] = saturate(t);
-                        t = (Y + Cr*r_cr) >> (fixc + 2);
-                        data1[x*3 + 2] = saturate(t);
-                    }
-                }
-                else
-                {
-                    for( x = 0; x < x2; x++ )
-                    {
-                        int val = descale( cmp[x] + 128*4, 2 );
-                        data1[x] = saturate(val);
-                    }
-                }
-            }
-        }
-
-        x1 += h[0];
-        if( x1 >= m_width )
-        {
-            x1 = 0;
-            y1 += v[0];
-            data += v[0]*step;
-            if( y1 >= m_height ) break;
-        }
-    }
-}
-
-
-void  GrFmtJpegReader::GetBlock( int* block, int c )
-{
-    memset( block, 0, 64*sizeof(block[0]) );
-
-    assert( 0 <= c && c < 3 );
-    const short* td = m_td[m_ci[c].td];
-    const short* ta = m_ta[m_ci[c].ta];
-    const int* tq = m_tq[m_ci[c].tq];
-
-    // Get DC coefficient
-    int i = 0, cat  = m_strm.GetHuff( td );
-    int mask = bs_bit_mask[cat];
-    int val  = m_strm.Get( cat );
-
-    val -= (val*2 <= mask ? mask : 0);
-    m_ci[c].dc_pred = val += m_ci[c].dc_pred;
-    
-    block[0] = descale(val * tq[0],16);
-
-    // Get AC coeffs
-    for(;;)
-    {
-        cat = m_strm.GetHuff( ta );
-        if( cat == 0 ) break; // end of block
-
-        i += (cat >> 4) + 1;
-        cat &= 15;
-        mask = bs_bit_mask[cat];
-        val  = m_strm.Get( cat );
-        cat  = zigzag[i];
-        val -= (val*2 <= mask ? mask : 0);
-        block[cat] = descale(val * tq[cat], 16);
-        assert( i <= 63 );
-        if( i >= 63 ) break;
-    }
-}
-
-////////////////////// WJpegStream ///////////////////////
-
-WJpegBitStream::WJpegBitStream()
-{
-}
-
-
-WJpegBitStream::~WJpegBitStream()
-{
-    Close();
-    m_is_opened = false;
-}
-
-
-
-bool  WJpegBitStream::Open( const char* filename )
-{
-    Close();
-    Allocate();
-    
-    m_is_opened = m_low_strm.Open( filename );
-    if( m_is_opened )
-    {
-        m_block_pos = 0;
-        ResetBuffer();
-    }
-    return m_is_opened;
-}
-
-
-void  WJpegBitStream::Close()
-{
-    if( m_is_opened )
-    {
-        Flush();
-        m_low_strm.Close();
-        m_is_opened = false;
-    }
-}
-
-
-void  WJpegBitStream::Flush()
-{
-    Put( -1, m_bit_idx & 31 );
-    *((ulong*&)m_current)++ = m_val;
-    WriteBlock();
-    ResetBuffer();
-}
-
-
-void  WJpegBitStream::WriteBlock()
-{
-    uchar* ptr = m_start;
-    if( !bsIsBigEndian() )
-        bsBSwapBlock( m_start, m_current );
-
-    while( ptr < m_current )
-    {
-        int val = *ptr++;
-        m_low_strm.PutByte( val );
-        if( val == 0xff )
-        {
-            m_low_strm.PutByte( 0 );
-        }
-    }
-    
-    m_current = m_start;
-}
-
-
-/////////////////////// GrFmtJpegWriter ///////////////////
-
-GrFmtJpegWriter::GrFmtJpegWriter( const char* filename ) : GrFmtWriter( filename )
-{
-}
-
-GrFmtJpegWriter::~GrFmtJpegWriter()
-{
-}
-
-//  Standard JPEG quantization tables
-static const uchar jpegTableK1_T[] =
-{
-    16, 12, 14, 14,  18,  24,  49,  72,
-    11, 12, 13, 17,  22,  35,  64,  92,
-    10, 14, 16, 22,  37,  55,  78,  95,
-    16, 19, 24, 29,  56,  64,  87,  98,
-    24, 26, 40, 51,  68,  81, 103, 112,
-    40, 58, 57, 87, 109, 104, 121, 100,
-    51, 60, 69, 80, 103, 113, 120, 103,
-    61, 55, 56, 62,  77,  92, 101,  99
-};
-
-
-static const uchar jpegTableK2_T[] =
-{
-    17, 18, 24, 47, 99, 99, 99, 99,
-    18, 21, 26, 66, 99, 99, 99, 99,
-    24, 26, 56, 99, 99, 99, 99, 99,
-    47, 66, 99, 99, 99, 99, 99, 99,
-    99, 99, 99, 99, 99, 99, 99, 99,
-    99, 99, 99, 99, 99, 99, 99, 99,
-    99, 99, 99, 99, 99, 99, 99, 99,
-    99, 99, 99, 99, 99, 99, 99, 99
-};
-
-
-// Standard Huffman tables
-
-// ... for luma DCs.
-static const uchar jpegTableK3[] =
-{
-    0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
-    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
-};
-
-
-// ... for chroma DCs.
-static const uchar jpegTableK4[] =
-{
-    0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
-    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
-};
-
-
-// ... for luma ACs.
-static const uchar jpegTableK5[] =
-{
-    0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 125,
-    0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
-    0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
-    0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
-    0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
-    0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
-    0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
-    0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
-    0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
-    0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
-    0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
-    0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
-    0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
-    0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
-    0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
-    0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
-    0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
-    0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
-    0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
-    0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
-    0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
-    0xf9, 0xfa
-};
-
-// ... for chroma ACs  
-static const uchar jpegTableK6[] =
-{
-    0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 119,
-    0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
-    0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
-    0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
-    0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
-    0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
-    0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
-    0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
-    0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
-    0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
-    0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
-    0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
-    0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
-    0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
-    0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
-    0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
-    0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
-    0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
-    0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
-    0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
-    0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
-    0xf9, 0xfa
-};
-
-
-static const char jpegHeader[] = 
-    "\xFF\xD8"  // SOI  - start of image
-    "\xFF\xE0"  // APP0 - jfif extention
-    "\x00\x10"  // 2 bytes: length of APP0 segment
-    "JFIF\x00"  // JFIF signature
-    "\x01\x02"  // version of JFIF
-    "\x00"      // units = pixels ( 1 - inch, 2 - cm )
-    "\x00\x01\x00\x01" // 2 2-bytes values: x density & y density
-    "\x00\x00"; // width & height of thumbnail: ( 0x0 means no thumbnail)
-
-#define postshift 14
-
-// FDCT with postscaling
-static void aan_fdct8x8( int *src, int *dst,
-                         int step, const int *postscale )
-{
-    int  workspace[64], *work = workspace;
-    int  i;
-
-    // Pass 1: process rows
-    for( i = 8; i > 0; i--, src += step, work += 8 )
-    {
-        int x0 = src[0], x1 = src[7];
-        int x2 = src[3], x3 = src[4];
-
-        int x4 = x0 + x1; x0 -= x1;
-        x1 = x2 + x3; x2 -= x3;
-    
-        work[7] = x0; work[1] = x2;
-        x2 = x4 + x1; x4 -= x1;
-
-        x0 = src[1]; x3 = src[6];
-        x1 = x0 + x3; x0 -= x3;
-        work[5] = x0;
-
-        x0 = src[2]; x3 = src[5];
-        work[3] = x0 - x3; x0 += x3;
-
-        x3 = x0 + x1; x0 -= x1;
-        x1 = x2 + x3; x2 -= x3;
-
-        work[0] = x1; work[4] = x2;
-
-        x0 = descale((x0 - x4)*C0_707, fixb);
-        x1 = x4 + x0; x4 -= x0;
-        work[2] = x4; work[6] = x1;
-
-        x0 = work[1]; x1 = work[3];
-        x2 = work[5]; x3 = work[7];
-
-        x0 += x1; x1 += x2; x2 += x3;
-        x1 = descale(x1*C0_707, fixb);
-
-        x4 = x1 + x3; x3 -= x1;
-        x1 = (x0 - x2)*C0_382;
-        x0 = descale(x0*C0_541 + x1, fixb);
-        x2 = descale(x2*C1_306 + x1, fixb);
-
-        x1 = x0 + x3; x3 -= x0;
-        x0 = x4 + x2; x4 -= x2;
-
-        work[5] = x1; work[1] = x0;
-        work[7] = x4; work[3] = x3;
-    }
-
-    work = workspace;
-    // pass 2: process columns
-    for( i = 8; i > 0; i--, work++, postscale += 8, dst += 8 )
-    {
-        int  x0 = work[8*0], x1 = work[8*7];
-        int  x2 = work[8*3], x3 = work[8*4];
-
-        int  x4 = x0 + x1; x0 -= x1;
-        x1 = x2 + x3; x2 -= x3;
-    
-        work[8*7] = x0; work[8*0] = x2;
-        x2 = x4 + x1; x4 -= x1;
-
-        x0 = work[8*1]; x3 = work[8*6];
-        x1 = x0 + x3; x0 -= x3;
-        work[8*4] = x0;
-
-        x0 = work[8*2]; x3 = work[8*5];
-        work[8*3] = x0 - x3; x0 += x3;
-
-        x3 = x0 + x1; x0 -= x1;
-        x1 = x2 + x3; x2 -= x3;
-
-        dst[0] = descale(x1*postscale[0], postshift);
-        dst[4] = descale(x2*postscale[4], postshift);
-
-        x0 = descale((x0 - x4)*C0_707, fixb);
-        x1 = x4 + x0; x4 -= x0;
-
-        dst[2] = descale(x4*postscale[2], postshift);
-        dst[6] = descale(x1*postscale[6], postshift);
-
-        x0 = work[8*0]; x1 = work[8*3];
-        x2 = work[8*4]; x3 = work[8*7];
-
-        x0 += x1; x1 += x2; x2 += x3;
-        x1 = descale(x1*C0_707, fixb);
-
-        x4 = x1 + x3; x3 -= x1;
-        x1 = (x0 - x2)*C0_382;
-        x0 = descale(x0*C0_541 + x1, fixb);
-        x2 = descale(x2*C1_306 + x1, fixb);
-
-        x1 = x0 + x3; x3 -= x0;
-        x0 = x4 + x2; x4 -= x2;
-
-        dst[5] = descale(x1*postscale[5], postshift);
-        dst[1] = descale(x0*postscale[1], postshift);
-        dst[7] = descale(x4*postscale[7], postshift);
-        dst[3] = descale(x3*postscale[3], postshift);
-    }
-}
-
-
-bool  GrFmtJpegWriter::WriteImage( const uchar* data, int step,
-                                   int width, int height, int /*depth*/, int _channels )
-{
-    assert( data && width > 0 && height > 0 );
-    
-    if( !m_strm.Open( m_filename ) ) return false;
-
-    // encode the header and tables
-    // for each mcu:
-    //   convert rgb to yuv with downsampling (if color).
-    //   for every block:
-    //     calc dct and quantize
-    //     encode block.
-    int x, y;
-    int i, j;
-    const int max_quality = 12;
-    int   quality = max_quality;
-    WMByteStream& lowstrm = m_strm.m_low_strm;
-    int   fdct_qtab[2][64];
-    ulong huff_dc_tab[2][16];
-    ulong huff_ac_tab[2][256];
-    int  channels = _channels > 1 ? 3 : 1;
-    int  x_scale = channels > 1 ? 2 : 1, y_scale = x_scale;
-    int  dc_pred[] = { 0, 0, 0 };
-    int  x_step = x_scale * 8;
-    int  y_step = y_scale * 8;
-    int  block[6][64];
-    int  buffer[1024];
-    int  luma_count = x_scale*y_scale;
-    int  block_count = luma_count + channels - 1;
-    int  Y_step = x_scale*8;
-    const int UV_step = 16;
-    double inv_quality;
-
-    if( quality < 3 ) quality = 3;
-    if( quality > max_quality ) quality = max_quality;
-
-    inv_quality = 1./quality;
-
-    // Encode header
-    lowstrm.PutBytes( jpegHeader, sizeof(jpegHeader) - 1 );
-    
-    // Encode quantization tables
-    for( i = 0; i < (channels > 1 ? 2 : 1); i++ )
-    {
-        const uchar* qtable = i == 0 ? jpegTableK1_T : jpegTableK2_T;
-        int chroma_scale = i > 0 ? luma_count : 1;
-        
-        lowstrm.PutWord( 0xffdb );   // DQT marker
-        lowstrm.PutWord( 2 + 65*1 ); // put single qtable
-        lowstrm.PutByte( 0*16 + i ); // 8-bit table
-
-        // put coefficients
-        for( j = 0; j < 64; j++ )
-        {
-            int idx = zigzag[j];
-            int qval = cvRound(qtable[idx]*inv_quality);
-            if( qval < 1 )
-                qval = 1;
-            if( qval > 255 )
-                qval = 255;
-            fdct_qtab[i][idx] = cvRound((1 << (postshift + 9))/
-                                      (qval*chroma_scale*idct_prescale[idx]));
-            lowstrm.PutByte( qval );
-        }
-    }
-
-    // Encode huffman tables
-    for( i = 0; i < (channels > 1 ? 4 : 2); i++ )
-    {
-        const uchar* htable = i == 0 ? jpegTableK3 : i == 1 ? jpegTableK5 :
-                              i == 2 ? jpegTableK4 : jpegTableK6;
-        int is_ac_tab = i & 1;
-        int idx = i >= 2;
-        int tableSize = 16 + (is_ac_tab ? 162 : 12);
-
-        lowstrm.PutWord( 0xFFC4   );      // DHT marker
-        lowstrm.PutWord( 3 + tableSize ); // define one huffman table
-        lowstrm.PutByte( is_ac_tab*16 + idx ); // put DC/AC flag and table index
-        lowstrm.PutBytes( htable, tableSize ); // put table
-
-        bsCreateEncodeHuffmanTable( bsCreateSourceHuffmanTable(
-            htable, buffer, 16, 9 ), is_ac_tab ? huff_ac_tab[idx] :
-            huff_dc_tab[idx], is_ac_tab ? 256 : 16 );
-    }
-
-    // put frame header
-    lowstrm.PutWord( 0xFFC0 );          // SOF0 marker
-    lowstrm.PutWord( 8 + 3*channels );  // length of frame header
-    lowstrm.PutByte( 8 );               // sample precision
-    lowstrm.PutWord( height );
-    lowstrm.PutWord( width );
-    lowstrm.PutByte( channels );        // number of components
-
-    for( i = 0; i < channels; i++ )
-    {
-        lowstrm.PutByte( i + 1 );  // (i+1)-th component id (Y,U or V)
-        if( i == 0 )
-            lowstrm.PutByte(x_scale*16 + y_scale); // chroma scale factors
-        else
-            lowstrm.PutByte(1*16 + 1);
-        lowstrm.PutByte( i > 0 ); // quantization table idx
-    }
-
-    // put scan header
-    lowstrm.PutWord( 0xFFDA );          // SOS marker
-    lowstrm.PutWord( 6 + 2*channels );  // length of scan header
-    lowstrm.PutByte( channels );        // number of components in the scan
-
-    for( i = 0; i < channels; i++ )
-    {
-        lowstrm.PutByte( i+1 );             // component id
-        lowstrm.PutByte( (i>0)*16 + (i>0) );// selection of DC & AC tables
-    }
-
-    lowstrm.PutWord(0*256 + 63);// start and end of spectral selection - for
-                                // sequental DCT start is 0 and end is 63
-
-    lowstrm.PutByte( 0 );  // successive approximation bit position 
-                           // high & low - (0,0) for sequental DCT  
-
-    // encode data
-    for( y = 0; y < height; y += y_step, data += y_step*step )
-    {
-        for( x = 0; x < width; x += x_step )
-        {
-            int x_limit = x_step;
-            int y_limit = y_step;
-            const uchar* rgb_data = data + x*_channels;
-            int* Y_data = block[0];
-
-            if( x + x_limit > width ) x_limit = width - x;
-            if( y + y_limit > height ) y_limit = height - y;
-
-            memset( block, 0, block_count*64*sizeof(block[0][0]));
-            
-            if( channels > 1 )
-            {
-                int* UV_data = block[luma_count];
-
-                for( i = 0; i < y_limit; i++, rgb_data += step, Y_data += Y_step )
-                {
-                    for( j = 0; j < x_limit; j++, rgb_data += _channels )
-                    {
-                        int r = rgb_data[2];
-                        int g = rgb_data[1];
-                        int b = rgb_data[0];
-
-                        int Y = descale( r*y_r + g*y_g + b*y_b, fixc - 2) - 128*4;
-                        int U = descale( r*cb_r + g*cb_g + b*cb_b, fixc - 2 );
-                        int V = descale( r*cr_r + g*cr_g + b*cr_b, fixc - 2 );
-                        int j2 = j >> (x_scale - 1); 
-
-                        Y_data[j] = Y;
-                        UV_data[j2] += U;
-                        UV_data[j2 + 8] += V;
-                    }
-
-                    rgb_data -= x_limit*_channels;
-                    if( ((i+1) & (y_scale - 1)) == 0 )
-                    {
-                        UV_data += UV_step;
-                    }
-                }
-            }
-            else
-            {
-                for( i = 0; i < y_limit; i++, rgb_data += step, Y_data += Y_step )
-                {
-                    for( j = 0; j < x_limit; j++ )
-                        Y_data[j] = rgb_data[j]*4 - 128*4;
-                }
-            }
-
-            for( i = 0; i < block_count; i++ )
-            {
-                int is_chroma = i >= luma_count;
-                int src_step = x_scale * 8;
-                int run = 0, val;
-                int* src_ptr = block[i & -2] + (i & 1)*8;
-                const ulong* htable = huff_ac_tab[is_chroma];
-
-                aan_fdct8x8( src_ptr, buffer, src_step, fdct_qtab[is_chroma] );
-
-                j = is_chroma + (i > luma_count);
-                val = buffer[0] - dc_pred[j];
-                dc_pred[j] = buffer[0];
-
-                {
-                float a = (float)val;
-                int cat = (((int&)a >> 23) & 255) - (126 & (val ? -1 : 0));
-
-                assert( cat <= 11 );
-                m_strm.PutHuff( cat, huff_dc_tab[is_chroma] );
-                m_strm.Put( val - (val < 0 ? 1 : 0), cat );
-                }
-
-                for( j = 1; j < 64; j++ )
-                {
-                    val = buffer[zigzag[j]];
-
-                    if( val == 0 )
-                    {
-                        run++;
-                    }
-                    else
-                    {
-                        while( run >= 16 )
-                        {
-                            m_strm.PutHuff( 0xF0, htable ); // encode 16 zeros
-                            run -= 16;
-                        }
-
-                        {
-                        float a = (float)val;
-                        int cat = (((int&)a >> 23) & 255) - (126 & (val ? -1 : 0));
-
-                        assert( cat <= 10 );
-                        m_strm.PutHuff( cat + run*16, htable );
-                        m_strm.Put( val - (val < 0 ? 1 : 0), cat );
-                        }
-
-                        run = 0;
-                    }
-                }
-
-                if( run )
-                {
-                    m_strm.PutHuff( 0x00, htable ); // encode EOB
-                }
-            }
-        }
-    }
-
-    // Flush 
-    m_strm.Flush();
-
-    lowstrm.PutWord( 0xFFD9 ); // EOI marker
-    m_strm.Close();
-
-    return true;
-}
-
-#endif
-
-/* End of file. */
-
-