📄 jpegsegments.c
字号:
///////////////////////////////////////////////////////////////////////////////
//
// JPEGSegments.c
//
// DESCRIPTION
// This file contains routines to read the definition segments in the file
// header of JPEG file.
//
//
//
///////////////////////////////////////////////////////////////////////////////
#include "irom_PlatformDefines.h"
#include "JPEGSegments.h"
#include "JPEGHuffmanDec.h"
#include "irom_JPEGTable.h"
// -------------------------------------------------------------------------
// Macro BigEndianWord
//
// Form a 2-byte integer using the first two bytes in the string. The
// number stored in the string is in big endian.
// Input parameters:
// OP_UINT8 *string, string containing the number
// Return:
// The 2-byte number just formed.
// -------------------------------------------------------------------------
#define BigEndianWord(string) ((((int)(string)[0] & 0xFF) << 8) + ((int)(string)[1] & 0xFF))
/////////////////////////////////////////////////////////////////////////////
// NAME
// JPEGReadQuantTable
//
// DESCRIPTION
// Read DQT segment. The marker and the length field have been removed.
// One or multiple quantization tables may be defined in the segment.
// This function supports re-definition of quantization tables. However,
// It is not allowed to redefine the tables of different precision.
//
// INPUTS
// segmentString - string buffer containing the segment header
// segmentLength - length of the segment header
// jpegSegments - pointer to structure storing the segment information
// aanscales_tab - pointer to the quatization scale table
// jpegNaturalOrder_tab - pointer to IDCT coeffient order table
//
// OUTPUTS
// JPEGSegments - stores quantization table in subfields of this structure
//
// RETURN VALUE
// Returns JPEG_OK if successful, returns an error code otherwise.
//
/////////////////////////////////////////////////////////////////////////////
int JPEGReadQuantTable
(
OP_UINT8 *segmentString,
int segmentLength,
JPEGSegments *jpegSegments,
const OP_UINT16 *aanscales_tab,
const OP_UINT8 *jpegNaturalOrder_tab
)
{
int stringPtr;
int tableIdx;
int entryIdx;
OP_UINT16 *qfTable;
JPEGQuantTable *quantTable;
stringPtr = 0;
// one or multiple tables may be defined in one segment
while (stringPtr < segmentLength)
{
OP_UINT8 newTableSpec;
newTableSpec = segmentString[stringPtr ++];
if (stringPtr > segmentLength)
{
return JPEG_ERR_QUANT_TABLE;
}
// get the table spec, does a quant table of same ID exist?
for (tableIdx = 0; tableIdx < jpegSegments->numQuantTables; tableIdx ++)
{
OP_UINT8 prevTableSpec;
prevTableSpec = jpegSegments->quantTables[tableIdx].tableSpec;
// previous table will be replaced
if (newTableSpec == prevTableSpec)
{
break;
}
else if ((newTableSpec & 0x0F)==(jpegSegments->quantTables[tableIdx].tableSpec & 0x0F))
{
// same ID but different precision, must be something wrong
return JPEG_ERR_QUANT_TABLE;
}
}
quantTable = &(jpegSegments->quantTables[tableIdx]);
quantTable->tableSpec = newTableSpec;
// upper 4 bits are for precision
if ((newTableSpec >> 4) != 0)
{
// 16-bit precision is not supported
return JPEG_ERR_QUANT_TABLE;
}
qfTable = quantTable->table;
// generate specific table coupled with fast IDCT
// For AA&N IDCT method, multipliers are equal to quantization
// coefficients scaled by scalefactor[row]*scalefactor[col], where
// scalefactor[0] = 1
// scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7
// For integer operation, the multiplier table is to be scaled by
// IFAST_SCALE_BITS.
for (entryIdx = 0; entryIdx < BLOCK_AREA; entryIdx ++)
{
OP_UINT16 qFactor;
qFactor = segmentString[stringPtr ++];
if (stringPtr > segmentLength)
{
return JPEG_ERR_QUANT_TABLE;
}
// this is for floating point implementation
qfTable[entryIdx] = (qFactor * aanscales_tab[jpegNaturalOrder_tab[entryIdx]] + 64) >> 7;
// this is for fixed point implementation
// qfTable[entryIdx] =
// (qFactor * aanscales[jpegNaturalOrder_tab[entryIdx]] + 2048) >> 12;
}
// a new quantization table is installed
if (tableIdx == jpegSegments->numQuantTables)
{
jpegSegments->numQuantTables += 1;
}
// else a previous table is replaced
}
return JPEG_OK;
}
/////////////////////////////////////////////////////////////////////////////
// NAME
// JPEGReadHuffTable
//
// DESCRIPTION
// Read Huff tables. One or multiple tables can be defined in one
// DHT segments.
// Each Huff table is stored as two parts, the code_bits part, and
// huff_val part. The first table records the number of codes of certain
// length (the index to this table). The second table records the values
// corresponding to these codes. The actual Huff codes are generated
// by the decoder following the well-defined rule.
// This function supports re-definition of some Huff tables. A Huff
// table is unique identified by its tableSpec (table class + table ID).
// A DC table can have the same ID as an AC table.
//
// INPUTS
// segmentString - string buffer containing the segment header
// segmentLength - length of the segment header
// jpegSegments - pointer to structure storing the segment information
// AllocateMemory - function pointer for memory allocation
// Deallocate - function pointer for memory deallocation
//
// OUTPUTS
// JPEGSegments - stores huffman table in subfields of this structure
//
// RETURN VALUE
// Returns JPEG_OK if successful, returns an error code otherwise.
//
/////////////////////////////////////////////////////////////////////////////
int JPEGReadHuffTable
(
OP_UINT8 *segmentString,
int segmentLength,
JPEGSegments *jpegSegments,
GetMemoryFunction AllocateMemory,
FreeMemoryFunction Deallocate
)
{
int i;
int stringPtr;
int tableIdx;
int entryIdx;
int symbolIdx;
JPEGHuffTable *huffTable;
stringPtr = 0;
// one or multiple tables may be defined in one segment
while (stringPtr < segmentLength)
{
OP_UINT8 newTableSpec;
OP_UINT8 prevTableSpec;
newTableSpec = segmentString[stringPtr ++];
if (stringPtr > segmentLength)
{
return JPEG_ERR_HUFFMAN_TABLE;
}
// get the table spec, does a Huff table of same ID exist?
for (tableIdx = 0; tableIdx < jpegSegments->numHuffTables; tableIdx ++)
{
prevTableSpec = jpegSegments->huffTables[tableIdx].tableSpec;
if (newTableSpec == prevTableSpec)
{
break;
}
}
huffTable = &(jpegSegments->huffTables[tableIdx]);
huffTable->tableSpec = newTableSpec;
// read the code_bits table
huffTable->numSymbols = 0;
for (entryIdx = 1; entryIdx <= 16; entryIdx ++)
{
huffTable->numCodes[entryIdx] = segmentString[stringPtr ++];
if (stringPtr > segmentLength)
{
return JPEG_ERR_HUFFMAN_TABLE;
}
huffTable->numSymbols += huffTable->numCodes[entryIdx];
}
// allocate the huff_val table
if (huffTable->symbols)
{
Deallocate(huffTable->symbols);
huffTable->symbols = 0;
}
huffTable->symbols = (OP_UINT8 *) AllocateMemory(sizeof(OP_UINT8) * huffTable->numSymbols);
// read the huff_val table
symbolIdx = 0;
for (entryIdx = 1; entryIdx <= 16; entryIdx ++)
{
for (i = 0; i < huffTable->numCodes[entryIdx]; i ++)
{
huffTable->symbols[symbolIdx ++] = segmentString[stringPtr ++];
if (stringPtr > segmentLength)
{
return JPEG_ERR_HUFFMAN_TABLE;
}
}
}
// a new table is installed
if (tableIdx == jpegSegments->numHuffTables)
{
jpegSegments->numHuffTables += 1;
}
}
return JPEG_OK;
}
/////////////////////////////////////////////////////////////////////////////
// NAME
// JPEGReadFrameHeader
//
// DESCRIPTION
// Read JPEG frame header.
//
// INPUTS
// segmentString - string buffer containing the segment header
// segmentLength - length of the segment header
// frameHeader - pointer to structure storing the frame header
//
// OUTPUTS
// frameHeader - stores frame header information in this structure
//
// RETURN VALUE
// Returns JPEG_OK if successful, returns an error code otherwise.
//
/////////////////////////////////////////////////////////////////////////////
int JPEGReadFrameHeader
(
OP_UINT8 *segmentString,
int segmentLength,
JPEGFrameHeader *frameHeader
)
{
int stringPtr;
int compIdx;
stringPtr = 0;
frameHeader->precision = segmentString[stringPtr ++];
frameHeader->frameHeight = BigEndianWord(segmentString + stringPtr);
stringPtr += 2;
frameHeader->frameWidth = BigEndianWord(segmentString + stringPtr);
stringPtr += 2;
frameHeader->numComponents = segmentString[stringPtr ++];
// read the component description
for (compIdx = 0; compIdx < frameHeader->numComponents; compIdx ++)
{
JPEGFrameCompBlock *thisCompBlock;
thisCompBlock = frameHeader->frameCompBlocks + compIdx;
thisCompBlock->componentID = segmentString[stringPtr];
thisCompBlock->sampFactor = segmentString[stringPtr + 1];
thisCompBlock->quantTableID = segmentString[stringPtr + 2];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -