Add support for single channel greyscale JPEGs
This commit is contained in:
parent
6ff1a1073a
commit
82f383cd77
3
README
3
README
|
@ -25,7 +25,7 @@ LIMITATIONS
|
||||||
|
|
||||||
Only JPEG files are supported, with the following limitations:
|
Only JPEG files are supported, with the following limitations:
|
||||||
|
|
||||||
- YUV/YCbCr colour format
|
- Greyscale or YUV/YCbCr colour formats
|
||||||
- Width and height must be a multiple of 16 (up to a resolution of 4080 x 4080)
|
- Width and height must be a multiple of 16 (up to a resolution of 4080 x 4080)
|
||||||
- Baseline DCT only
|
- Baseline DCT only
|
||||||
- The total number of MCU blocks must not exceed 65535
|
- The total number of MCU blocks must not exceed 65535
|
||||||
|
@ -38,5 +38,4 @@ TODO
|
||||||
|
|
||||||
* Allow the decoder to handle multiple images in the input stream.
|
* Allow the decoder to handle multiple images in the input stream.
|
||||||
* Experiment with adaptive or multiple huffman tables.
|
* Experiment with adaptive or multiple huffman tables.
|
||||||
* Quality setting (4 bit / 16 quality levels).
|
|
||||||
|
|
||||||
|
|
46
ssdv.c
46
ssdv.c
|
@ -569,8 +569,22 @@ static char ssdv_process(ssdv_t *s)
|
||||||
|
|
||||||
if(s->acpart >= 64)
|
if(s->acpart >= 64)
|
||||||
{
|
{
|
||||||
|
s->mcupart++;
|
||||||
|
|
||||||
|
if(s->greyscale && s->mcupart == s->ycparts)
|
||||||
|
{
|
||||||
|
/* For greyscale input images, pad the 2x1 MCUs with empty colour blocks */
|
||||||
|
for(; s->mcupart < s->ycparts + 2; s->mcupart++)
|
||||||
|
{
|
||||||
|
if(s->mcupart < s->ycparts) s->component = 0;
|
||||||
|
else s->component = s->mcupart - s->ycparts + 1;
|
||||||
|
s->acpart = 0; ssdv_out_jpeg_int(s, 0, 0); /* DC */
|
||||||
|
s->acpart = 1; ssdv_out_jpeg_int(s, 0, 0); /* AC */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Reached the end of this MCU part */
|
/* Reached the end of this MCU part */
|
||||||
if(++s->mcupart == s->ycparts + 2)
|
if(s->mcupart == s->ycparts + 2)
|
||||||
{
|
{
|
||||||
s->mcupart = 0;
|
s->mcupart = 0;
|
||||||
s->mcu_id++;
|
s->mcu_id++;
|
||||||
|
@ -722,10 +736,10 @@ static char ssdv_have_marker_data(ssdv_t *s)
|
||||||
return(SSDV_ERROR);
|
return(SSDV_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The image must have 3 components (Y'Cb'Cr) */
|
/* The image must have 1 or 3 components (Y'Cb'Cr) */
|
||||||
if(d[5] != 3)
|
if(d[5] != 1 && d[5] != 3)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Error: The image must have 3 components\n");
|
fprintf(stderr, "Error: The image must have 1 or 3 components\n");
|
||||||
return(SSDV_ERROR);
|
return(SSDV_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -745,7 +759,7 @@ static char ssdv_have_marker_data(ssdv_t *s)
|
||||||
|
|
||||||
/* TODO: Read in the quantisation table ID for each component */
|
/* TODO: Read in the quantisation table ID for each component */
|
||||||
// 01 22 00 02 11 01 03 11 01
|
// 01 22 00 02 11 01 03 11 01
|
||||||
for(i = 0; i < 3; i++)
|
for(i = 0; i < d[5]; i++)
|
||||||
{
|
{
|
||||||
uint8_t *dq = &d[i * 3 + 6];
|
uint8_t *dq = &d[i * 3 + 6];
|
||||||
if(dq[0] != i + 1)
|
if(dq[0] != i + 1)
|
||||||
|
@ -777,6 +791,14 @@ static char ssdv_have_marker_data(ssdv_t *s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(d[5] == 1)
|
||||||
|
{
|
||||||
|
/* Greyscale images are converted to 2x1 colour images */
|
||||||
|
s->greyscale = 1;
|
||||||
|
s->mcu_mode = 2;
|
||||||
|
s->ycparts = 2;
|
||||||
|
}
|
||||||
|
|
||||||
/* Calculate number of MCU blocks in this image */
|
/* Calculate number of MCU blocks in this image */
|
||||||
switch(s->mcu_mode)
|
switch(s->mcu_mode)
|
||||||
{
|
{
|
||||||
|
@ -801,14 +823,14 @@ static char ssdv_have_marker_data(ssdv_t *s)
|
||||||
case J_SOS:
|
case J_SOS:
|
||||||
fprintf(stderr, "Components: %i\n", d[0]);
|
fprintf(stderr, "Components: %i\n", d[0]);
|
||||||
|
|
||||||
/* The image must have 3 components (Y'Cb'Cr) */
|
/* The image must have 1 or 3 components (Y'Cb'Cr) */
|
||||||
if(d[0] != 3)
|
if(d[0] != 1 && d[0] != 3)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Error: The image must have 3 components\n");
|
fprintf(stderr, "Error: The image must have 1 or 3 components\n");
|
||||||
return(SSDV_ERROR);
|
return(SSDV_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(i = 0; i < 3; i++)
|
for(i = 0; i < d[0]; i++)
|
||||||
{
|
{
|
||||||
uint8_t *dh = &d[i * 2 + 1];
|
uint8_t *dh = &d[i * 2 + 1];
|
||||||
if(dh[0] != i + 1)
|
if(dh[0] != i + 1)
|
||||||
|
@ -824,14 +846,14 @@ static char ssdv_have_marker_data(ssdv_t *s)
|
||||||
/* 00 3F 00 */
|
/* 00 3F 00 */
|
||||||
|
|
||||||
/* Verify all of the DQT and DHT tables where loaded */
|
/* Verify all of the DQT and DHT tables where loaded */
|
||||||
if(!s->sdqt[0] || !s->sdqt[1])
|
if(!s->sdqt[0] || (d[0] > 1 && !s->sdqt[1]))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Error: The image is missing one or more DQT tables\n");
|
fprintf(stderr, "Error: The image is missing one or more DQT tables\n");
|
||||||
return(SSDV_ERROR);
|
return(SSDV_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!s->sdht[0][0] || !s->sdht[0][1] ||
|
if(!s->sdht[0][0] || (d[0] > 1 && !s->sdht[0][1]) ||
|
||||||
!s->sdht[1][0] || !s->sdht[1][1])
|
!s->sdht[1][0] || (d[0] > 1 && !s->sdht[1][1]))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Error: The image is missing one or more DHT tables\n");
|
fprintf(stderr, "Error: The image is missing one or more DHT tables\n");
|
||||||
return(SSDV_ERROR);
|
return(SSDV_ERROR);
|
||||||
|
|
1
ssdv.h
1
ssdv.h
|
@ -99,6 +99,7 @@ typedef struct
|
||||||
uint16_t marker_len; /* Length of data following marker */
|
uint16_t marker_len; /* Length of data following marker */
|
||||||
uint8_t *marker_data; /* Where to copy marker data too */
|
uint8_t *marker_data; /* Where to copy marker data too */
|
||||||
uint16_t marker_data_len; /* How much is there */
|
uint16_t marker_data_len; /* How much is there */
|
||||||
|
uint8_t greyscale; /* 0 = Normal (3 channels), 1 = Greyscale */
|
||||||
uint8_t component; /* 0 = Y, 1 = Cb, 2 = Cr */
|
uint8_t component; /* 0 = Y, 1 = Cb, 2 = Cr */
|
||||||
uint8_t ycparts; /* Number of Y component parts per MCU */
|
uint8_t ycparts; /* Number of Y component parts per MCU */
|
||||||
uint8_t mcupart; /* 0-3 = Y, 4 = Cb, 5 = Cr */
|
uint8_t mcupart; /* 0-3 = Y, 4 = Cb, 5 = Cr */
|
||||||
|
|
Loading…
Reference in New Issue