private bool JPEGPreDecode(short s)
{
TiffDirectory td = m_tif.m_dir;
const string module = "JPEGPreDecode";
int segment_width;
int segment_height;
int ci;
Debug.Assert(m_common.IsDecompressor);
/*
* Reset decoder state from any previous strip/tile,
* in case application didn't read the whole strip.
*/
if (!TIFFjpeg_abort())
return false;
/*
* Read the header for this strip/tile.
*/
if (TIFFjpeg_read_header(true) != ReadResult.JPEG_HEADER_OK)
return false;
/*
* Check image parameters and set decompression parameters.
*/
segment_width = td.td_imagewidth;
segment_height = td.td_imagelength - m_tif.m_row;
if (m_tif.IsTiled())
{
segment_width = td.td_tilewidth;
segment_height = td.td_tilelength;
m_bytesperline = m_tif.TileRowSize();
}
else
{
if (segment_height > td.td_rowsperstrip && td.td_rowsperstrip != -1)
segment_height = td.td_rowsperstrip;
m_bytesperline = m_tif.oldScanlineSize();
}
if (td.td_planarconfig == PlanarConfig.SEPARATE && s > 0)
{
/*
* For PC 2, scale down the expected strip/tile size
* to match a downsampled component
*/
segment_width = Tiff.howMany(segment_width, m_h_sampling);
segment_height = Tiff.howMany(segment_height, m_v_sampling);
}
if (m_decompression.Image_width < segment_width || m_decompression.Image_height < segment_height)
{
Tiff.WarningExt(m_tif, m_tif.m_clientdata, module,
"Improper JPEG strip/tile size, expected {0}x{1}, got {2}x{3}",
segment_width, segment_height, m_decompression.Image_width, m_decompression.Image_height);
}
if (m_decompression.Image_width > segment_width || m_decompression.Image_height > segment_height)
{
/*
* This case could be dangerous, if the strip or tile size has
* been reported as less than the amount of data jpeg will
* return, some potential security issues arise. Catch this
* case and error out.
*/
Tiff.ErrorExt(m_tif, m_tif.m_clientdata, module,
"JPEG strip/tile size exceeds expected dimensions, expected {0}x{1}, got {2}x{3}",
segment_width, segment_height, m_decompression.Image_width, m_decompression.Image_height);
return false;
}
if (m_decompression.Num_components != (td.td_planarconfig == PlanarConfig.CONTIG ? (int)td.td_samplesperpixel : 1))
{
Tiff.ErrorExt(m_tif, m_tif.m_clientdata, module, "Improper JPEG component count");
return false;
}
if (m_decompression.Data_precision != td.td_bitspersample)
{
Tiff.ErrorExt(m_tif, m_tif.m_clientdata, module, "Improper JPEG data precision");
return false;
}
if (td.td_planarconfig == PlanarConfig.CONTIG)
{
/* Component 0 should have expected sampling factors */
if (m_decompression.Comp_info[0].H_samp_factor != m_h_sampling ||
m_decompression.Comp_info[0].V_samp_factor != m_v_sampling)
{
Tiff.WarningExt(m_tif, m_tif.m_clientdata, module,
"Improper JPEG sampling factors {0},{1}\nApparently should be {2},{3}.",
m_decompression.Comp_info[0].H_samp_factor,
m_decompression.Comp_info[0].V_samp_factor, m_h_sampling, m_v_sampling);
/*
* XXX: Files written by the Intergraph software
* has different sampling factors stored in the
* TIFF tags and in the JPEG structures. We will
* try to deduce Intergraph files by the presense
* of the tag 33918.
*/
if (m_tif.FindFieldInfo((TiffTag)33918, TiffType.ANY) == null)
{
Tiff.WarningExt(m_tif, m_tif.m_clientdata, module,
"Decompressor will try reading with sampling {0},{1}.",
m_decompression.Comp_info[0].H_samp_factor,
m_decompression.Comp_info[0].V_samp_factor);
m_h_sampling = m_decompression.Comp_info[0].H_samp_factor;
m_v_sampling = m_decompression.Comp_info[0].V_samp_factor;
}
}
/* Rest should have sampling factors 1,1 */
for (ci = 1; ci < m_decompression.Num_components; ci++)
{
if (m_decompression.Comp_info[ci].H_samp_factor != 1 ||
m_decompression.Comp_info[ci].V_samp_factor != 1)
{
Tiff.ErrorExt(m_tif, m_tif.m_clientdata, module, "Improper JPEG sampling factors");
return false;
}
}
}
else
{
/* PC 2's single component should have sampling factors 1,1 */
if (m_decompression.Comp_info[0].H_samp_factor != 1 ||
m_decompression.Comp_info[0].V_samp_factor != 1)
{
Tiff.ErrorExt(m_tif, m_tif.m_clientdata, module, "Improper JPEG sampling factors");
return false;
}
}
bool downsampled_output = false;
if (td.td_planarconfig == PlanarConfig.CONTIG &&
m_photometric == Photometric.YCBCR &&
m_jpegcolormode == JpegColorMode.RGB)
{
/* Convert YCbCr to RGB */
m_decompression.Jpeg_color_space = J_COLOR_SPACE.JCS_YCbCr;
m_decompression.Out_color_space = J_COLOR_SPACE.JCS_RGB;
}
else
{
/* Suppress colorspace handling */
m_decompression.Jpeg_color_space = J_COLOR_SPACE.JCS_UNKNOWN;
m_decompression.Out_color_space = J_COLOR_SPACE.JCS_UNKNOWN;
if (td.td_planarconfig == PlanarConfig.CONTIG &&
(m_h_sampling != 1 || m_v_sampling != 1))
{
downsampled_output = true;
}
/* XXX what about up-sampling? */
}
if (downsampled_output)
{
// Need to use raw-data interface to LibJpeg.Net
m_decompression.Raw_data_out = true;
m_rawDecode = true;
}
else
{
// Use normal interface to LibJpeg.Net
m_decompression.Raw_data_out = false;
m_rawDecode = false;
}
/* Start JPEG decompressor */
if (!TIFFjpeg_start_decompress())
return false;
/* Allocate downsampled-data buffers if needed */
if (downsampled_output)
{
if (!alloc_downsampled_buffers(m_decompression.Comp_info, m_decompression.Num_components))
return false;
m_scancount = JpegConstants.DCTSIZE; /* mark buffer empty */
}
return true;
}