Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

560 lines
12 KiB

/***********************************************************************
*
* JPEG decompression utility functions
*
* Implement (1) JPEG memory data source
* (2) JPEG error manager using setjmp/longjmp
*
* Author : Indy Zhu [indyz]
* Date : 5/20/98
*
***********************************************************************/
#include "pch.h"
#include <setjmp.h>
//
// Workaround for redefinition of INT32
//
#define XMD_H 1
//
// Header file for JPEG library
//
extern "C"
{
#include "jpeglib.h"
}
#include "utils.h"
//
// Buf source manager definition
//
typedef struct _buf_source_mgr
{
struct jpeg_source_mgr pub;
//
// Fields specific to buf_source_mgr
//
LPBYTE pJPEGBlob;
DWORD dwSize;
} buf_source_mgr;
//
// Jump error manager definition
//
typedef struct _jmp_error_mgr
{
struct jpeg_error_mgr pub;
//
// Private fields for jump error manager
//
jmp_buf stackContext;
} jmp_error_mgr;
/******************************************************************************\
*
* init_source()
*
* Arguments:
*
* Return Value:
*
* Status
*
* History:
*
* 11/4/1998 Original Version
*
\******************************************************************************/
static void __cdecl
init_source(
j_decompress_ptr pDecompInfo)
{
//
// No working necessary here
//
}
/******************************************************************************\
*
* fill_input_buffer()
*
* Arguments:
*
* Return Value:
*
* Status
*
* History:
*
* 11/4/1998 Original Version
*
\******************************************************************************/
static boolean __cdecl
fill_input_buffer(
j_decompress_ptr pDecompInfo)
{
buf_source_mgr *pBufSrcMgr;
//
// Recover buf source manager itself
//
pBufSrcMgr = (buf_source_mgr *)pDecompInfo->src;
//
// buf_source_mgr can only fire one shot
//
pBufSrcMgr->pub.next_input_byte = pBufSrcMgr->pJPEGBlob;
pBufSrcMgr->pub.bytes_in_buffer = pBufSrcMgr->dwSize;
return(TRUE);
}
/******************************************************************************\
*
* skip_input_data()
*
* Arguments:
*
* Return Value:
*
* Status
*
* History:
*
* 11/4/1998 Original Version
*
\******************************************************************************/
static void __cdecl
skip_input_data(
j_decompress_ptr pDecompInfo,
long lBytes)
{
buf_source_mgr *pBufSrcMgr;
//
// For buf source manager, it is very easy to implement
//
if (lBytes > 0)
{
pBufSrcMgr = (buf_source_mgr *)pDecompInfo->src;
pBufSrcMgr->pub.next_input_byte += lBytes;
pBufSrcMgr->pub.bytes_in_buffer -= lBytes;
}
}
/******************************************************************************\
*
* term_source()
*
* Arguments:
*
* Return Value:
*
* Status
*
* History:
*
* 11/4/1998 Original Version
*
\******************************************************************************/
static void __cdecl
term_source(
j_decompress_ptr pDecompInfo)
{
}
/******************************************************************************\
*
* jpeg_buf_src()
*
* Arguments:
*
* Return Value:
*
* Status
*
* History:
*
* 11/4/1998 Original Version
*
\******************************************************************************/
static void __cdecl
jpeg_buf_src(
j_decompress_ptr pDecompInfo,
LPBYTE pJPEGBlob,
DWORD dwSize)
{
buf_source_mgr *pBufSrcMgr;
//
// Allocate memory for the buf source manager
//
pBufSrcMgr = (buf_source_mgr *)
(pDecompInfo->mem->alloc_small)((j_common_ptr)pDecompInfo,
JPOOL_PERMANENT,
sizeof(buf_source_mgr));
//
// Record the pJPEGBlob
//
pBufSrcMgr->pJPEGBlob = pJPEGBlob;
pBufSrcMgr->dwSize = dwSize;
//
// Fill in the function pointers
//
pBufSrcMgr->pub.init_source = init_source;
pBufSrcMgr->pub.fill_input_buffer = fill_input_buffer;
pBufSrcMgr->pub.skip_input_data = skip_input_data;
pBufSrcMgr->pub.resync_to_restart = jpeg_resync_to_restart;
pBufSrcMgr->pub.term_source = term_source;
//
// Initialize the pointer into the buffer
//
pBufSrcMgr->pub.bytes_in_buffer = 0;
pBufSrcMgr->pub.next_input_byte = NULL;
//
// Ask the decompression context to remember it
//
pDecompInfo->src = (struct jpeg_source_mgr *)pBufSrcMgr;
}
/******************************************************************************\
*
* jmp_error_exit()
*
* Arguments:
*
* Return Value:
*
* Status
*
* History:
*
* 11/4/1998 Original Version
*
\******************************************************************************/
static void __cdecl
jmp_error_exit(
j_common_ptr pDecompInfo)
{
jmp_error_mgr *pJmpErrorMgr;
//
// Get the jump error manager back
//
pJmpErrorMgr = (jmp_error_mgr *)pDecompInfo->err;
//
// Display the error message
//
#ifdef _DEBUG
(pDecompInfo->err->output_message)(pDecompInfo);
#endif
//
// Recover the original stack
//
longjmp(pJmpErrorMgr->stackContext, 1);
}
/******************************************************************************\
*
* jpeg_jmp_error()
*
* Arguments:
*
* Return Value:
*
* Status
*
* History:
*
* 11/4/1998 Original Version
*
\******************************************************************************/
struct jpeg_error_mgr *
jpeg_jmp_error(
jmp_error_mgr *pJmpErrorMgr)
{
//
// Initialize the public part
//
jpeg_std_error(&pJmpErrorMgr->pub);
//
// Set up jump error manager exit method
//
pJmpErrorMgr->pub.error_exit = jmp_error_exit;
return((jpeg_error_mgr *)pJmpErrorMgr);
}
/******************************************************************************\
*
* GetJpegDimensions
*
* Arguments:
* pJpeg -- jpeg file in memory. It could be in JFIF and EXIF
* format
* JpegSize -- the jpeg file size
* pWidth -- to return the image width in pixels
* pHeight -- to return the image height in pixels
* pBitDepth -- to return the image bit depth.
*
* Return Value:
*
* HRESULT
*
* History:
*
* 11/4/1998 Original Version
*
\******************************************************************************/
HRESULT
WINAPI
GetJpegDimensions(
BYTE *pJpeg,
UINT JpegSize,
UINT *pWidth,
UINT *pHeight,
UINT *pBitDepth
)
{
struct jpeg_decompress_struct decompInfo;
jmp_error_mgr jpegErrMgr;
int ret;
//
// Step 1 : Initialize JPEG session data-structure
//
decompInfo.err = jpeg_jmp_error(&jpegErrMgr);
jpeg_create_decompress(&decompInfo);
//
// Reserve the state of the current stack
//
if (setjmp(jpegErrMgr.stackContext))
{
//
// JPEG lib will longjump here when there is an error
//
jpeg_destroy_decompress(&decompInfo);
return(E_FAIL);
}
//
// Step 2 : Specify the source of the compressed data
//
jpeg_buf_src(&decompInfo, pJpeg, JpegSize);
//
// Step 3 : Read JPEG file header information
//
ret = jpeg_read_header(&decompInfo, TRUE);
//
// Release the decompression context
//
jpeg_destroy_decompress(&decompInfo);
//
// Fill in the dimension info for the caller
//
*pWidth = decompInfo.image_width;
*pHeight = decompInfo.image_height;
*pBitDepth = 24;
if (ret != JPEG_HEADER_OK)
{
return(E_FAIL);
}
return S_OK;
}
//
// This function converts a jpeg file in memory to DIB bitmap
//
// Input:
// pJpeg -- jpeg file in memory. JFIF or EXIF are supported
// JpegSize -- the jpeg file size
// DIBBmpSize -- DIB bitmap buffer size
// pDIBBmp -- DIB bitmap buffer
// LineSize -- desitnation scanline size in bytes
// MaxLines -- maximum scanlines per transfer
//
HRESULT
WINAPI
Jpeg2DIBBitmap(
BYTE *pJpeg,
UINT JpegSize,
BYTE *pDIBBmp,
UINT DIBBmpSize,
UINT LineSize,
UINT MaxLines
)
{
struct jpeg_decompress_struct decompInfo;
jmp_error_mgr jpegErrMgr;
//
// Parameter checking
//
if (!pJpeg || !JpegSize || !DIBBmpSize || !pDIBBmp || !LineSize)
return E_INVALIDARG;
//
// Step 1 : Initialize JPEG session data-structure
//
decompInfo.err = jpeg_jmp_error(&jpegErrMgr);
jpeg_create_decompress(&decompInfo);
//
// Reserve the state of the current stack
//
if (setjmp(jpegErrMgr.stackContext))
{
//
// JPEG lib will longjump here when there is an error
//
jpeg_destroy_decompress(&decompInfo);
return(E_FAIL);
}
//
// Step 2 : Specify the source of the compressed data
//
jpeg_buf_src(&decompInfo, pJpeg, JpegSize);
//
// Step 3 : Read JPEG file header information
//
if (jpeg_read_header(&decompInfo, TRUE) != JPEG_HEADER_OK)
{
jpeg_destroy_decompress(&decompInfo);
return(E_FAIL);
}
//
// Step 4 : Set parameter for decompression
// Defaults are OK for this occasssion
// Specify the JCS_BGR output colorspace so that the returned
// decompressed image has the same format as DIB. Also, it forces
// the decompressor to return a 24-bits RGB colors image
//
decompInfo.out_color_space = JCS_BGR;
//
// Calculate DIB scan line size, assuming 24bits color.
//
HRESULT hr;
hr = S_OK;
//
// Step 5 : Start the real action
//
jpeg_start_decompress(&decompInfo);
//
// Step 6 : Acquire the scan line
//
while (S_OK == hr &&
decompInfo.output_scanline < decompInfo.output_height)
{
if (DIBBmpSize >= LineSize)
{
//
// Decompress line by line. Ignore the MaxLines since
// we do not do more than one line at a time.
//
jpeg_read_scanlines(&decompInfo, &pDIBBmp, 1);
pDIBBmp -= LineSize;
DIBBmpSize -= LineSize;
}
else
{
//
// The provided buffer is too small.
//
hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
}
}
//
// Step 7 : Finish the job
//
if (SUCCEEDED(hr))
{
jpeg_finish_decompress(&decompInfo);
}
else
{
jpeg_abort_decompress(&decompInfo);
}
//
// Step 8 : Garbage collection
//
jpeg_destroy_decompress(&decompInfo);
return hr;
}