Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
tree: f828abd491
Fetching contributors…

Cannot retrieve contributors at this time

386 lines (360 sloc) 15.286 kb
/***************************************************************************#
# jpegenc: library to encode a jpeg frame from various input palette. #
# jpegenc works for embedded device without libjpeg #
#. #
# Copyright (C) 2005 Michel Xhaard #
# #
# This program is free software; you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation; either version 2 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program; if not, write to the Free Software #
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #
# CREDIT: #
# Original code from Nitin Gupta India (?) #
# #
#***************************************************************************/
#include "jdatatype.h"
#include "encoder.h"
#include "huffman.h"
UINT16 luminance_dc_code_table[] = {
0x0000, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x000E, 0x001E, 0x003E,
0x007E, 0x00FE, 0x01FE
};
UINT16 luminance_dc_size_table[] = {
0x0002, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0004, 0x0005, 0x0006,
0x0007, 0x0008, 0x0009
};
UINT16 chrominance_dc_code_table[] = {
0x0000, 0x0001, 0x0002, 0x0006, 0x000E, 0x001E, 0x003E, 0x007E, 0x00FE,
0x01FE, 0x03FE, 0x07FE
};
UINT16 chrominance_dc_size_table[] = {
0x0002, 0x0002, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008,
0x0009, 0x000A, 0x000B
};
UINT16 luminance_ac_code_table[] = {
0x000A, 0x0000, 0x0001, 0x0004, 0x000B, 0x001A, 0x0078, 0x00F8, 0x03F6,
0xFF82, 0xFF83, 0x000C, 0x001B, 0x0079, 0x01F6, 0x07F6, 0xFF84, 0xFF85,
0xFF86, 0xFF87, 0xFF88, 0x001C, 0x00F9, 0x03F7, 0x0FF4, 0xFF89, 0xFF8A,
0xFF8b, 0xFF8C, 0xFF8D, 0xFF8E, 0x003A, 0x01F7, 0x0FF5, 0xFF8F, 0xFF90,
0xFF91, 0xFF92, 0xFF93, 0xFF94, 0xFF95, 0x003B, 0x03F8, 0xFF96, 0xFF97,
0xFF98, 0xFF99, 0xFF9A, 0xFF9B, 0xFF9C, 0xFF9D, 0x007A, 0x07F7, 0xFF9E,
0xFF9F, 0xFFA0, 0xFFA1, 0xFFA2, 0xFFA3, 0xFFA4, 0xFFA5, 0x007B, 0x0FF6,
0xFFA6, 0xFFA7, 0xFFA8, 0xFFA9, 0xFFAA, 0xFFAB, 0xFFAC, 0xFFAD, 0x00FA,
0x0FF7, 0xFFAE, 0xFFAF, 0xFFB0, 0xFFB1, 0xFFB2, 0xFFB3, 0xFFB4, 0xFFB5,
0x01F8, 0x7FC0, 0xFFB6, 0xFFB7, 0xFFB8, 0xFFB9, 0xFFBA, 0xFFBB, 0xFFBC,
0xFFBD, 0x01F9, 0xFFBE, 0xFFBF, 0xFFC0, 0xFFC1, 0xFFC2, 0xFFC3, 0xFFC4,
0xFFC5, 0xFFC6, 0x01FA, 0xFFC7, 0xFFC8, 0xFFC9, 0xFFCA, 0xFFCB, 0xFFCC,
0xFFCD, 0xFFCE, 0xFFCF, 0x03F9, 0xFFD0, 0xFFD1, 0xFFD2, 0xFFD3, 0xFFD4,
0xFFD5, 0xFFD6, 0xFFD7, 0xFFD8, 0x03FA, 0xFFD9, 0xFFDA, 0xFFDB, 0xFFDC,
0xFFDD, 0xFFDE, 0xFFDF, 0xFFE0, 0xFFE1, 0x07F8, 0xFFE2, 0xFFE3, 0xFFE4,
0xFFE5, 0xFFE6, 0xFFE7, 0xFFE8, 0xFFE9, 0xFFEA, 0xFFEB, 0xFFEC, 0xFFED,
0xFFEE, 0xFFEF, 0xFFF0, 0xFFF1, 0xFFF2, 0xFFF3, 0xFFF4, 0xFFF5, 0xFFF6,
0xFFF7, 0xFFF8, 0xFFF9, 0xFFFA, 0xFFFB, 0xFFFC, 0xFFFD, 0xFFFE,
0x07F9
};
UINT16 luminance_ac_size_table[] = {
0x0004, 0x0002, 0x0002, 0x0003, 0x0004, 0x0005, 0x0007, 0x0008, 0x000A,
0x0010, 0x0010, 0x0004, 0x0005, 0x0007, 0x0009, 0x000B, 0x0010, 0x0010,
0x0010, 0x0010, 0x0010, 0x0005, 0x0008, 0x000A, 0x000C, 0x0010, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010, 0x0006, 0x0009, 0x000C, 0x0010, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0006, 0x000A, 0x0010, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0007, 0x000B, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0007, 0x000C,
0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0008,
0x000C, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010,
0x0009, 0x000F, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010,
0x0010, 0x0009, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010,
0x0010, 0x0010, 0x0009, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010,
0x0010, 0x0010, 0x0010, 0x000A, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010, 0x000A, 0x0010, 0x0010, 0x0010, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x000B, 0x0010, 0x0010, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010,
0x000B
};
UINT16 chrominance_ac_code_table[] = {
0x0000, 0x0001, 0x0004, 0x000A, 0x0018, 0x0019, 0x0038, 0x0078, 0x01F4,
0x03F6, 0x0FF4, 0x000B, 0x0039, 0x00F6, 0x01F5, 0x07F6, 0x0FF5, 0xFF88,
0xFF89, 0xFF8A, 0xFF8B, 0x001A, 0x00F7, 0x03F7, 0x0FF6, 0x7FC2, 0xFF8C,
0xFF8D, 0xFF8E, 0xFF8F, 0xFF90, 0x001B, 0x00F8, 0x03F8, 0x0FF7, 0xFF91,
0xFF92, 0xFF93, 0xFF94, 0xFF95, 0xFF96, 0x003A, 0x01F6, 0xFF97, 0xFF98,
0xFF99, 0xFF9A, 0xFF9B, 0xFF9C, 0xFF9D, 0xFF9E, 0x003B, 0x03F9, 0xFF9F,
0xFFA0, 0xFFA1, 0xFFA2, 0xFFA3, 0xFFA4, 0xFFA5, 0xFFA6, 0x0079, 0x07F7,
0xFFA7, 0xFFA8, 0xFFA9, 0xFFAA, 0xFFAB, 0xFFAC, 0xFFAD, 0xFFAE, 0x007A,
0x07F8, 0xFFAF, 0xFFB0, 0xFFB1, 0xFFB2, 0xFFB3, 0xFFB4, 0xFFB5, 0xFFB6,
0x00F9, 0xFFB7, 0xFFB8, 0xFFB9, 0xFFBA, 0xFFBB, 0xFFBC, 0xFFBD, 0xFFBE,
0xFFBF, 0x01F7, 0xFFC0, 0xFFC1, 0xFFC2, 0xFFC3, 0xFFC4, 0xFFC5, 0xFFC6,
0xFFC7, 0xFFC8, 0x01F8, 0xFFC9, 0xFFCA, 0xFFCB, 0xFFCC, 0xFFCD, 0xFFCE,
0xFFCF, 0xFFD0, 0xFFD1, 0x01F9, 0xFFD2, 0xFFD3, 0xFFD4, 0xFFD5, 0xFFD6,
0xFFD7, 0xFFD8, 0xFFD9, 0xFFDA, 0x01FA, 0xFFDB, 0xFFDC, 0xFFDD, 0xFFDE,
0xFFDF, 0xFFE0, 0xFFE1, 0xFFE2, 0xFFE3, 0x07F9, 0xFFE4, 0xFFE5, 0xFFE6,
0xFFE7, 0xFFE8, 0xFFE9, 0xFFEA, 0xFFEb, 0xFFEC, 0x3FE0, 0xFFED, 0xFFEE,
0xFFEF, 0xFFF0, 0xFFF1, 0xFFF2, 0xFFF3, 0xFFF4, 0xFFF5, 0x7FC3, 0xFFF6,
0xFFF7, 0xFFF8, 0xFFF9, 0xFFFA, 0xFFFB, 0xFFFC, 0xFFFD, 0xFFFE,
0x03FA
};
UINT16 chrominance_ac_size_table[] = {
0x0002, 0x0002, 0x0003, 0x0004, 0x0005, 0x0005, 0x0006, 0x0007, 0x0009,
0x000A, 0x000C, 0x0004, 0x0006, 0x0008, 0x0009, 0x000B, 0x000C, 0x0010,
0x0010, 0x0010, 0x0010, 0x0005, 0x0008, 0x000A, 0x000C, 0x000F, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010, 0x0005, 0x0008, 0x000A, 0x000C, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0006, 0x0009, 0x0010, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0006, 0x000A, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0007, 0x000B,
0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0007,
0x000B, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010,
0x0008, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010,
0x0010, 0x0009, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010,
0x0010, 0x0010, 0x0009, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010,
0x0010, 0x0010, 0x0010, 0x0009, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010, 0x0009, 0x0010, 0x0010, 0x0010, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x000B, 0x0010, 0x0010, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x000E, 0x0010, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x000F, 0x0010,
0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010,
0x000A
};
UINT8 bitsize[] = {
0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8
};
#if 0
#define PUTBITS { \
bits_in_next_word = (INT16) (bitindex + numbits - 32); \
if (bits_in_next_word < 0) \
{ \
lcode = (lcode << numbits) | data; \
bitindex += numbits; \
} \
else \
{ \
lcode = (lcode << (32 - bitindex)) | (data >> bits_in_next_word); \
if ((*output_ptr++ = (UINT8) (lcode >> 24)) == 0xff) \
*output_ptr++ = 0; \
if ((*output_ptr++ = (UINT8) (lcode >> 16)) == 0xff) \
*output_ptr++ = 0; \
if ((*output_ptr++ = (UINT8) (lcode >> 8)) == 0xff) \
*output_ptr++ = 0; \
if ((*output_ptr++ = (UINT8) lcode) == 0xff) \
*output_ptr++ = 0; \
lcode = data; \
bitindex = bits_in_next_word; \
} \
}
#endif
UINT8 * huffman (JPEG_ENCODER_STRUCTURE * jpeg_encoder_structure,
UINT16 component, UINT8 * output_ptr)
{
UINT16 i;
UINT16 * DcCodeTable, *DcSizeTable, *AcCodeTable, *AcSizeTable;
INT16 * Temp_Ptr, Coeff, LastDc;
UINT16 AbsCoeff, HuffCode, HuffSize, RunLength = 0, DataSize = 0, index;
INT16 bits_in_next_word;
UINT16 numbits;
UINT32 data;
Temp_Ptr = Temp;
Coeff = *Temp_Ptr++;
if (component == 1)
{
DcCodeTable = luminance_dc_code_table;
DcSizeTable = luminance_dc_size_table;
AcCodeTable = luminance_ac_code_table;
AcSizeTable = luminance_ac_size_table;
LastDc = jpeg_encoder_structure->ldc1;
jpeg_encoder_structure->ldc1 = Coeff;
}
else
{
DcCodeTable = chrominance_dc_code_table;
DcSizeTable = chrominance_dc_size_table;
AcCodeTable = chrominance_ac_code_table;
AcSizeTable = chrominance_ac_size_table;
if (component == 2)
{
LastDc = jpeg_encoder_structure->ldc2;
jpeg_encoder_structure->ldc2 = Coeff;
}
else
{
LastDc = jpeg_encoder_structure->ldc3;
jpeg_encoder_structure->ldc3 = Coeff;
}
}
Coeff -= LastDc;
AbsCoeff = (Coeff < 0) ? -Coeff-- : Coeff;
while (AbsCoeff != 0)
{
AbsCoeff >>= 1;
DataSize++;
}
HuffCode = DcCodeTable[DataSize];
HuffSize = DcSizeTable[DataSize];
Coeff &= (1 << DataSize) - 1;
data = (HuffCode << DataSize) | Coeff;
numbits = HuffSize + DataSize;
//PUTBITS
{
bits_in_next_word = (INT16) (bitindex + numbits - 32);
if (bits_in_next_word < 0)
{
lcode = (lcode << numbits) | data;
bitindex += numbits;
}
else
{
lcode = (lcode << (32 - bitindex)) | (data >> bits_in_next_word);
if ((*output_ptr++ = (UINT8) (lcode >> 24)) == 0xff)
*output_ptr++ = 0;
if ((*output_ptr++ = (UINT8) (lcode >> 16)) == 0xff)
*output_ptr++ = 0;
if ((*output_ptr++ = (UINT8) (lcode >> 8)) == 0xff)
*output_ptr++ = 0;
if ((*output_ptr++ = (UINT8) lcode) == 0xff)
*output_ptr++ = 0;
lcode = data;
bitindex = bits_in_next_word;
}
}
for (i = 63; i > 0; i--)
{
if ((Coeff = *Temp_Ptr++) != 0)
{
while (RunLength > 15)
{
RunLength -= 16;
data = AcCodeTable[161];
numbits = AcSizeTable[161];
//PUTBITS
{
bits_in_next_word = (INT16) (bitindex + numbits - 32);
if (bits_in_next_word < 0)
{
lcode = (lcode << numbits) | data;
bitindex += numbits;
}
else
{
lcode = (lcode << (32 - bitindex)) | (data >> bits_in_next_word);
if ((*output_ptr++ = (UINT8) (lcode >> 24)) == 0xff)
*output_ptr++ = 0;
if ((*output_ptr++ = (UINT8) (lcode >> 16)) == 0xff)
*output_ptr++ = 0;
if ((*output_ptr++ = (UINT8) (lcode >> 8)) == 0xff)
*output_ptr++ = 0;
if ((*output_ptr++ = (UINT8) lcode) == 0xff)
*output_ptr++ = 0;
lcode = data;
bitindex = bits_in_next_word;
}
}
}
AbsCoeff = (Coeff < 0) ? -Coeff-- : Coeff;
if (AbsCoeff >> 8 == 0)
DataSize = bitsize[AbsCoeff];
else
DataSize = bitsize[AbsCoeff >> 8] + 8;
index = RunLength * 10 + DataSize;
HuffCode = AcCodeTable[index];
HuffSize = AcSizeTable[index];
Coeff &= (1 << DataSize) - 1;
data = (HuffCode << DataSize) | Coeff;
numbits = HuffSize + DataSize;
// PUTBITS
{
bits_in_next_word = (INT16) (bitindex + numbits - 32);
if (bits_in_next_word < 0)
{
lcode = (lcode << numbits) | data;
bitindex += numbits;
}
else
{
lcode = (lcode << (32 - bitindex)) | (data >> bits_in_next_word);
if ((*output_ptr++ = (UINT8) (lcode >> 24)) == 0xff)
*output_ptr++ = 0;
if ((*output_ptr++ = (UINT8) (lcode >> 16)) == 0xff)
*output_ptr++ = 0;
if ((*output_ptr++ = (UINT8) (lcode >> 8)) == 0xff)
*output_ptr++ = 0;
if ((*output_ptr++ = (UINT8) lcode) == 0xff)
*output_ptr++ = 0;
lcode = data;
bitindex = bits_in_next_word;
}
}
RunLength = 0;
}
else
RunLength++;
}
if (RunLength != 0)
{
data = AcCodeTable[0];
numbits = AcSizeTable[0];
// PUTBITS
{
bits_in_next_word = (INT16) (bitindex + numbits - 32);
if (bits_in_next_word < 0)
{
lcode = (lcode << numbits) | data;
bitindex += numbits;
}
else
{
lcode = (lcode << (32 - bitindex)) | (data >> bits_in_next_word);
if ((*output_ptr++ = (UINT8) (lcode >> 24)) == 0xff)
*output_ptr++ = 0;
if ((*output_ptr++ = (UINT8) (lcode >> 16)) == 0xff)
*output_ptr++ = 0;
if ((*output_ptr++ = (UINT8) (lcode >> 8)) == 0xff)
*output_ptr++ = 0;
if ((*output_ptr++ = (UINT8) lcode) == 0xff)
*output_ptr++ = 0;
lcode = data;
bitindex = bits_in_next_word;
}
}
}
return output_ptr;
}
/* For bit Stuffing and EOI marker */
UINT8 * close_bitstream (UINT8 * output_ptr)
{
UINT16 i, count;
UINT8 * ptr;
if (bitindex > 0)
{
lcode <<= (32 - bitindex);
count = (bitindex + 7) >> 3;
ptr = (UINT8 *) & lcode + 3;
for (i = count; i > 0; i--)
{
if ((*output_ptr++ = *ptr--) == 0xff)
*output_ptr++ = 0;
}
}
// End of image marker
*output_ptr++ = 0xFF;
*output_ptr++ = 0xD9;
return output_ptr;
}
Jump to Line
Something went wrong with that request. Please try again.