windows-nt/Source/XPSP1/NT/shell/shell32/tngen/jpegapi.cpp
2020-09-26 16:20:57 +08:00

392 lines
9.8 KiB
C++

/* jpegapi.cpp -- interface layer for painless JPEG compression of NIFty images.
* Written by Ajai Sehgal 3/10/96
* (c) Copyright Microsoft Corporation
*
* 08-27-1997 (kurtgeis) Pushed exception handling into library. Changed
* all entry points to return HRESULTs. Added width and heigth to parameters.
* 04-20-2001 (bobday) Removed exception handling. If we have problems, I
* say we fix the problems! (or check for the proper error conditions)
*/
#pragma warning(disable:4005)
#include "stdafx.h"
#include "jpegapi.h"
#include "jmemsys.h"
#define I_LIKE_CPP_EH 0 // turn this on if we ever find a reason for it
/********************************************************************************/
/* JPEGCompressHeader()
*
* Arguments:
* tuQuality "Quality" of the resulting JPEG (0..100, 100=best)
*
* Returns:
* HRESULT
*/
HRESULT JPEGCompressHeader(BYTE *prgbJPEGHeaderBuf, UINT tuQuality, ULONG *pcbOut, HANDLE *phJpegC, J_COLOR_SPACE ColorSpace)
{
HRESULT hr = S_OK;
jpeg_compress_struct *spjcs = NULL;
#if I_LIKE_CPP_EH
try
{
#endif
spjcs = new jpeg_compress_struct;
struct jpeg_error_mgr *jem = new jpeg_error_mgr;
spjcs->err = jpeg_std_error(jem); // Init the error handler
jpeg_create_compress(spjcs); // Init the compression object
if (ColorSpace == JCS_GRAYSCALE)
{
spjcs->in_color_space = JCS_GRAYSCALE;
spjcs->input_components = 1;
}
else
{
spjcs->in_color_space = JCS_RGBA;
spjcs->input_components = 4;
}
jpeg_set_defaults(spjcs); // Init the compression engine with the defaults
jpeg_set_quality(spjcs, tuQuality, TRUE);
jpeg_set_colorspace(spjcs,ColorSpace);
jpeg_mem_dest(spjcs, prgbJPEGHeaderBuf); // Init the "destination manager"
spjcs->comps_in_scan = 0;
spjcs->write_JFIF_header = FALSE;
jpeg_write_tables(spjcs);
jpeg_suppress_tables(spjcs, TRUE);
*pcbOut = spjcs->bytes_in_buffer;
*phJpegC = (HANDLE) spjcs;
#if I_LIKE_CPP_EH
}
catch( THROWN thrownHR )
{
hr = thrownHR.Hr();
}
catch( ... )
{
if ( spjcs ) delete spjcs;
hr = E_OUTOFMEMORY;
}
#endif
return hr;
}
/* JPEGDecompressHeader()
*
* Arguments:
* *prgbJPEGBuf : pointer to the JPEG header data as read from file
* *phJpegD: pointer to Handle of the JPEG decompression object returned
*
* Returns:
* HRESULT
*/
HRESULT JPEGDecompressHeader(BYTE *prgbJPEGHeaderBuf, HANDLE *phJpegD, ULONG ulBufferSize)
{
HRESULT hr = S_OK;
jpeg_decompress_struct * spjds = NULL;
#if I_LIKE_CPP_EH
try
{
#endif
spjds = new jpeg_decompress_struct;
struct jpeg_error_mgr *jem = new jpeg_error_mgr;
spjds->err = jpeg_std_error(jem); // Init the error handler
jpeg_create_decompress(spjds); // Init the decompression object
// Now we need to "read" it into the decompression object...
jpeg_mem_src(spjds, prgbJPEGHeaderBuf, ulBufferSize);
jpeg_read_header(spjds, FALSE);
spjds->out_color_space = JCS_RGBA;
*phJpegD = (HANDLE) spjds;
#if I_LIKE_CPP_EH
}
catch( THROWN thrownHR )
{
hr = thrownHR.Hr();
}
catch( ... )
{
if ( spjds ) delete spjds;
hr = E_OUTOFMEMORY;
}
#endif
return hr;
}
// DestroyJPEGCompress
//
// Release all the JPEG stuff from the handle we gave to the user
//
HRESULT DestroyJPEGCompressHeader(HANDLE hJpegC)
{
HRESULT hr = S_OK;
try
{
struct jpeg_compress_struct *pjcs = (struct jpeg_compress_struct *)hJpegC;
jpeg_destroy_compress(pjcs);
delete pjcs->err;
delete pjcs;
}
catch( THROWN thrownHR )
{
hr = thrownHR.Hr();
}
return hr;
}
// DestroyJPEGDecompressHeader
//
// Release all the JPEG stuff from the handle we gave to the user
//
HRESULT DestroyJPEGDecompressHeader(HANDLE hJpegD)
{
HRESULT hr = S_OK;
#if I_LIKE_CPP_EH
try
{
#endif
struct jpeg_decompress_struct *pjds = (struct jpeg_decompress_struct *)hJpegD;
jpeg_destroy_decompress(pjds);
delete pjds->err;
delete pjds;
#if I_LIKE_CPP_EH
}
catch( THROWN thrownHR )
{
hr = thrownHR.Hr();
}
#endif
return hr;
}
/* JPEGFromRGBA()
*
* Arguments:
* prgbImage A raw image buffer (4 bytes/pixel, RGBA order)
* cpxlAcross Width of the image, in pixels
* cpxlDown Height of the image, in pixels
* tuQuality "Quality" of the resulting JPEG (0..100, 100=best)
* A memory buffer containing the complete JPEG compressed version of the
* given image. NULL on error.
*
* Returns:
* HRESULT
*/
HRESULT JPEGFromRGBA(BYTE *prgbImage, BYTE *prgbJPEGBuf, UINT tuQuality, ULONG *pcbOut, HANDLE hJpegC, J_COLOR_SPACE ColorSpace, UINT nWidth, UINT nHeight )
{
HRESULT hr = S_OK;
#if I_LIKE_CPP_EH
try
{
#endif
struct jpeg_compress_struct *pjcs = (jpeg_compress_struct *)hJpegC;
JSAMPROW rgrow[1];
//
// On non X86 architectures use only C code
//
#if defined (_X86_)
pjcs->dct_method = JDCT_ISLOW;
#else
pjcs->dct_method = JDCT_FLOAT;
#endif
pjcs->image_width = nWidth;
pjcs->image_height = nHeight;
pjcs->data_precision = 8; /* 8 bits / sample */
pjcs->bytes_in_buffer = 0;
pjcs->write_JFIF_header = FALSE;
if (ColorSpace == JCS_GRAYSCALE)
{
pjcs->input_components = 1;
}
else
{
pjcs->input_components = 4;
}
jpeg_set_colorspace(pjcs,ColorSpace);
jpeg_set_quality(pjcs, tuQuality, TRUE);
jpeg_suppress_tables(pjcs, TRUE);
jpeg_mem_dest(pjcs, prgbJPEGBuf); // Init the "destination manager"
jpeg_start_compress(pjcs, FALSE);
rgrow[0] = (JSAMPROW)prgbImage;
while (pjcs->next_scanline < nHeight )
{
jpeg_write_scanlines(pjcs, rgrow, 1);
rgrow[0] += nWidth * pjcs->input_components; //input_components is the equivalent of # of bytes
}
jpeg_finish_compress(pjcs); // Finish up compressing
*pcbOut = pjcs->bytes_in_buffer;
#if I_LIKE_CPP_EH
}
catch( THROWN thrownHR )
{
hr = thrownHR.Hr();
}
#endif
return hr;
}
/* RGBAFromJPEG()
*
* Arguments:
* prgbJPEG: A JPEG data stream, as returned by JPEGFromRGBA()
* A memory buffer containing the reconstructed image in RGBA format.
* NULL on error.
*
* Returns:
* HRESULT
*/
HRESULT RGBAFromJPEG(BYTE *prgbJPEG, BYTE *prgbImage, HANDLE hJpegD, ULONG ulBufferSize, BYTE bJPEGConversionType, ULONG *pulReturnedNumChannels, UINT nWidth, UINT nHeight )
{
HRESULT hr = S_OK;
jpeg_decompress_struct * spjds = NULL;
#if I_LIKE_CPP_EH
try
{
#endif
struct jpeg_decompress_struct *pjds;
spjds = new jpeg_decompress_struct;
jpeg_error_mgr * spjem = new jpeg_error_mgr;
if ( hJpegD == NULL )
{
spjds->err = jpeg_std_error(spjem); // Init the error handler
jpeg_create_decompress(spjds); // Init the decompression object in the case
pjds = spjds; // that the headers are with the tiles.
}
else
{
pjds = (struct jpeg_decompress_struct *)hJpegD;
}
JSAMPROW rgrow[1];
// Set the various image parameters.
pjds->data_precision = 8;
pjds->image_width = nWidth;
pjds->image_height = nHeight;
jpeg_mem_src(pjds, prgbJPEG, ulBufferSize); // Init the "source manager"
jpeg_read_header(pjds, TRUE);
switch (bJPEGConversionType)
{
case 1:
pjds->out_color_space = JCS_RGBA;
if (pjds->jpeg_color_space != JCS_RGBA)
{
if ( 4 == pjds->num_components)
pjds->jpeg_color_space = JCS_YCbCrALegacy;
else
pjds->jpeg_color_space = JCS_YCbCr;
}
*pulReturnedNumChannels = 4;
break;
case 2:
pjds->out_color_space = JCS_RGBA;
if ( 4 == pjds->num_components)
pjds->jpeg_color_space = JCS_YCbCrA;
else
pjds->jpeg_color_space = JCS_YCbCr;
pjds->jpeg_color_space = JCS_YCbCrA;
*pulReturnedNumChannels = 4;
break;
default:
pjds->out_color_space = JCS_UNKNOWN;
pjds->jpeg_color_space = JCS_UNKNOWN;
*pulReturnedNumChannels = pjds->num_components;
}
//
// On non X86 architectures use only C code
//
#if defined (_X86_)
pjds->dct_method = JDCT_ISLOW;
#else
pjds->dct_method = JDCT_FLOAT;
#endif
jpeg_start_decompress(pjds);
rgrow[0] = (JSAMPROW)prgbImage;
while (pjds->output_scanline < pjds->output_height)
{
jpeg_read_scanlines(pjds, rgrow, 1);
rgrow[0] += pjds->output_width * *pulReturnedNumChannels;
}
jpeg_finish_decompress(pjds); // Finish up decompressing
if (hJpegD == NULL)
jpeg_destroy_decompress(pjds); //Destroy the decompression object if it
//was locally allocated as in when the header
//is part of the tile.
delete spjem;
delete spjds;
#if I_LIKE_CPP_EH
}
catch( THROWN thrownHR )
{
hr = thrownHR.Hr();
}
catch( ... )
{
if ( spjds ) delete spjds;
hr = E_OUTOFMEMORY;
}
#endif
return hr;
}