📄 jpeg.c
字号:
{
out[((by+iy)*o2)/2 + (bx/2) + (ix/2)] = (unsigned char)(((unsigned int)blockBase[(iy*16) + ix] + (unsigned int)blockBase[(iy*16) + ix+ 1])/2) + 0x7F;
}
}
for (iy=0; iy<8; iy++)
{
for (ix=0; ix<8; ix++)
{
out[oo + ((by/2) +iy)*(o2) + (bx/2) + ix] = blockBase[256 + (iy*8) + ix] + 0x7F;
}
}
for (iy=0; iy<8; iy++)
{
for (ix=0; ix<8; ix++)
{
out[(oo*2) + ((by/2) +iy)*(o2) + (bx/2) + ix] = blockBase[320 + (iy*8) + ix] + 0x7F;
}
}
/* YUV decode for 4:2:0 components
unsigned int oo = outWidth * outHeight;
unsigned int o2 = outWidth / 2;
for (iy=0; iy<16; iy++)
{
for (ix=0; ix<16; ix++)
{
out[((by+iy)*outWidth) + bx + ix] = blockBase[(iy*16) + ix] + 0x7F;
}
}
for (iy=0; iy<8; iy++)
{
for (ix=0; ix<8; ix++)
{
out[oo + ((by/2) +iy)*(o2) + (bx/2) + ix] = blockBase[256 + (iy*8) + ix] + 0x7F;
}
}
for (iy=0; iy<8; iy++)
{
for (ix=0; ix<8; ix++)
{
out[(oo + (oo>>2)) + ((by/2) +iy)*(o2) + (bx/2) + ix] = blockBase[320 + (iy*8) + ix] + 0x7F;
}
}
*/
/* Handle the restart interval. */
if (decoder->restartInterval && --restartInterval == 0)
{
restartInterval = decoder->restartInterval;
JPEG_BITS_REWIND ();
if (((data [0] << 8) | data [1]) == JPEG_Marker_EOI)
goto finish;
for (c = 0; c < JPEG_MAXIMUM_COMPONENTS; c ++)
dcLast [c] = 0;
data += 2;
}
}
}
finish:
/* Make sure we read an EOI marker. */
JPEG_BITS_REWIND ();
data += 2;
/* Clear up and return success. */
*dataBase = data;
return 1;
}
/* Read an JPEG_Marker_SOFn marker into frame. This expects to start
* processing immediately after the marker.
*/
int JPEG_FrameHeader_Read (JPEG_FrameHeader *frame, const unsigned char **dataBase, JPEG_Marker marker)
{
const unsigned char *data = *dataBase;
unsigned short length = (data [0] << 8) | data [1];
int index;
(void) length;
data += 2; /* Skip the length. */
frame->marker = marker;
frame->encoding = (marker >= 0xFFC0 && marker <= 0xFFC7) ? 0 : 1;
frame->differential = !(marker >= 0xFFC0 && marker <= 0xFFC3 && marker >= 0xFFC8 && marker <= 0xFFCB);
frame->precision = *data ++;
frame->height = (data [0] << 8) | data [1]; data += 2;
frame->width = (data [0] << 8) | data [1]; data += 2;
frame->componentCount = *data ++;
/* Read the frame components. */
for (index = 0; index < frame->componentCount; index ++)
{
JPEG_FrameHeader_Component *c = &frame->componentList [index];
unsigned char pair;
c->selector = *data ++;
pair = *data ++;
c->horzFactor = pair >> 4;
c->vertFactor = pair & 15;
c->quantTable = *data ++;
}
*dataBase = data;
return 1;
}
/* Read a JPEG_Marker_SOS marker into scan. This expects to start processing
* immediately after the marker.
*/
int JPEG_ScanHeader_Read (JPEG_ScanHeader *scan, const unsigned char **dataBase)
{
const unsigned char *data = *dataBase;
unsigned short length = (data [0] << 8) | data [1];
JPEG_ScanHeader_Component *c, *cEnd;
unsigned char pair;
(void) length;
data += 2; /* Skip the length. */
scan->componentCount = *data ++;
/* Read the scan components. */
for (c = scan->componentList, cEnd = c + scan->componentCount; c < cEnd; c ++)
{
c->selector = *data ++;
pair = *data ++;
c->dcTable = pair >> 4;
c->acTable = pair & 15;
}
/* Read the spectral and approximation footers, which are used for
* progressive.
*/
scan->spectralStart = *data ++;
scan->spectralEnd = *data ++;
pair = *data ++;
scan->successiveApproximationBitPositionHigh = pair >> 4;
scan->successiveApproximationBitPositionLow = pair & 15;
*dataBase = data;
return 1;
}
/* Read all headers from the very start of the JFIF stream to right after the
* SOS marker.
*/
int JPEG_Decoder_ReadHeaders (JPEG_Decoder *decoder, const unsigned char **dataBase)
{
const unsigned char *data = *dataBase;
JPEG_Marker marker;
int c;
/* Initialize state and assure that this is a JFIF file. */
decoder->restartInterval = 0;
data += 2;
/* Start reading every marker as it comes in. */
while (1)
{
marker = (JPEG_Marker) ((data [0] << 8) | data [1]);
data += 2;
switch (marker)
{
/* This block is just skipped over. */
case JPEG_Marker_APP0:
case JPEG_Marker_APP1:
case JPEG_Marker_APP2:
case JPEG_Marker_APP3:
case JPEG_Marker_APP4:
case JPEG_Marker_APP5:
case JPEG_Marker_APP6:
case JPEG_Marker_APP7:
case JPEG_Marker_APP8:
case JPEG_Marker_APP9:
case JPEG_Marker_APP10:
case JPEG_Marker_APP11:
case JPEG_Marker_APP12:
case JPEG_Marker_APP13:
case JPEG_Marker_APP14:
case JPEG_Marker_APP15:
case JPEG_Marker_COM:
data += (data [0] << 8) | data [1];
break;
case JPEG_Marker_DHT: /* Define Huffman table. We just skip it for later decompression. */
{
unsigned short length = (data [0] << 8) | data [1];
const unsigned char *end = data + length;
data += 2;
while (data < end)
{
unsigned char pair, type, slot;
pair = *data ++;
type = pair >> 4;
slot = pair & 15;
if (type == 0)
decoder->dcTables [slot] = data;
else
decoder->acTables [slot] = data;
if (!JPEG_HuffmanTable_Skip (&data))
return 0;
}
break;
}
case JPEG_Marker_DQT: /* Define quantization table. */
{
unsigned short length = (data [0] << 8) | data [1];
const unsigned char *end = data + length;
int col, row;
JPEG_FIXED_TYPE *s;
data += 2;
while (data < end)
{
int pair, slot, precision;
pair = *data ++;
precision = pair >> 4;
slot = pair & 15;
s = decoder->quantTables [slot];
for (c = 0; c < JPEG_DCTSIZE2; c ++)
s [c] = JPEG_ITOFIX (*data ++);
/* Multiply against the AAN factors. */
for (row = 0; row < JPEG_DCTSIZE; row ++)
for (col = 0; col < JPEG_DCTSIZE; col ++)
{
JPEG_FIXED_TYPE *item = &s [col + row * JPEG_DCTSIZE];
*item = JPEG_FIXMUL (*item, JPEG_AANScaleFactor [JPEG_ToZigZag [row * JPEG_DCTSIZE + col]]);
}
}
break;
}
case JPEG_Marker_DRI: /* Define restart interval. */
decoder->restartInterval = (data [2] << 8) | data [3];
data += 4;
break;
case JPEG_Marker_SOF0: /* Start of Frame: Baseline Sequential Huffman. */
if (!JPEG_FrameHeader_Read (&decoder->frame, &data, marker))
return 0;
break;
case JPEG_Marker_SOS: /* Start of scan, immediately followed by the image. */
if (!JPEG_ScanHeader_Read (&decoder->scan, &data))
return 0;
*dataBase = data;
return 1;
default: /* No known marker of this type. */
break;
}
}
}
/* Perform the two steps necessary to decompress a JPEG image.
* Nothing fancy about it.
*/
int JPEG_DecompressImage (const unsigned char *data, signed char *out, int outWidth, int outHeight)
{
static JPEG_Decoder decoder;
if (!JPEG_Decoder_ReadHeaders (&decoder, &data))
return 0;
if (!JPEG_Decoder_ReadImage (&decoder, &data, out, outWidth, outHeight))
return 0;
return 1;
}
/* Return whether this code is a JPEG file. Unfortunately it will incorrectly
* match variants such as JPEG 2000 and JPEG-LS. A better function would
* skip known markers until it reaches an unknown marker or a handled
* SOFn.
*/
int JPEG_Match (const unsigned char *data, int length)
{
if (length == 0) return 0;
if (data [0] != 0xFF) return 0;
if (length == 1) return 1;
if (data [1] != 0xD8) return 0;
if (length == 2) return 1;
return 1;
if (data [2] != 0xFF) return 0;
if (length == 3) return 1;
if (data [3] < 0xC0 || data [3] > 0xCF) return 0;
if (data [3] == 0xC0) return 1;
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -