📄 grfmt_jpeg.cpp
字号:
/*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 "stdwin.h"
#include <assert.h>
#include <string.h>
#include "grfmt_jpeg.h"
static const char fmtDescrJpeg[] = "JPEG files (*.jpeg;*.jpg;*.jpe)";
static const char fmtSignJpeg[] = "\xFF\xD8\xFF";
////////////////////// JPEG-oriented two-level bitstream ////////////////////////
RJpegBitStream::RJpegBitStream()
{
}
RJpegBitStream::~RJpegBitStream()
{
}
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;
try
{
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: ;
}
catch( int )
{
if( current == m_start ) throw;
}
m_current = m_start;
m_end = m_start + (((current - m_start) + 3) & -4);
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 postscale(x) round(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 10
#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()
{
m_signature = fmtSignJpeg;
m_sign_len = strlen(fmtSignJpeg);
m_description = fmtDescrJpeg;
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();
}
bool GrFmtJpegReader::ReadHeader()
{
char buffer[16];
int i;
bool result = false, is_jfif = 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;
try
{
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;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -