// ** JPEG.CPP, the code used to wrap IJL
#include "..\stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "dibapi.h"
#include "jpegWrap.h"
//############################################################################
//## ##
//## JPEG.CPP ##
//## ##
//## Wrapper class to load a jpeg from a block of memory. ##
//## ##
//## OpenSourced 2/4/2000 by John W. Ratcliff ##
//## ##
//## No warranty expressed or implied. Released as part of the triangle ##
//## throughput testbed project. ##
//############################################################################
//## ##
//## Contact John W. Ratcliff at jratcliff@verant.com ##
//############################################################################
//## ##
//## Added HBitmap routine, can do a scaling and adding text at top of jpg ##
//## edgar@cyberpoint.nl
//############################################################################
#include "ijl.h" // intel jpeg library header file.
bool Jpeg::GetBitmapBits( TCHAR* StrText,
HBITMAP hbm,
unsigned char ** ppPicture,
unsigned long * pnPictureBytes,
int iW,
int iH,
int iQ)
{
bool ret = false;
BITMAP bitmapOrg;
HBITMAP bmpUseThisOne = hbm;
int iOrgX = 1;
int iOrgY = 1;
// When we have a text, increase height of destination bmp with 16 ( must be multiple of 16 )
int iOffsetY = ( StrText && _tcslen(StrText)) ? 16 : 0;
if ( sizeof(BITMAP) == ::GetObject( hbm, sizeof(BITMAP), &bitmapOrg ) )
{
iOrgX = bitmapOrg.bmWidth;
iOrgY = bitmapOrg.bmHeight;
iW = abs(iW?iW:iOrgX);
iH = abs(iH?iH:iOrgY);
iH += iOffsetY;
// Allways multiple of 16
iW = (iW/16)*16;
iH = (iH/16)*16;
// Create a bitmap compatible to the screen
HDC hdcOrg = CreateCompatibleDC( NULL );
HDC hdcSize = CreateCompatibleDC( NULL );
HBITMAP hbmSized = NULL;
HBITMAP hBmpSized = NULL;
if ( hdcSize )
{
HGDIOBJ pOrg = SelectObject ( hdcOrg, hbm );
hBmpSized = ::CreateCompatibleBitmap (hdcOrg,iW,iH);
if ( hBmpSized )
{
HGDIOBJ p = SelectObject ( hdcSize, hBmpSized );
CRect DCRect(0,0,iW,iH);
CRect DibRect(0,0,iOrgX,iOrgY);
::SetStretchBltMode ( hdcSize, COLORONCOLOR );
::SetStretchBltMode ( hdcOrg, COLORONCOLOR );
::StretchBlt ( hdcSize, 0,iOffsetY,iW,iH-iOffsetY,hdcOrg,0,0,iOrgX,iOrgY,SRCCOPY);
// Draw text at top of bitmap
// Only needed when we have set an offset
if ( iOffsetY )
{
::SetBkColor ( hdcSize, RGB ( 0,0,0 ) );
::SetTextColor ( hdcSize, RGB( 255,255,255));
::DrawText ( hdcSize, StrText,-1,&DCRect,DT_TOP|DT_EXPANDTABS );
}
SelectObject ( hdcSize, p );
bmpUseThisOne = hBmpSized;
}
SelectObject ( hdcOrg, pOrg );
DeleteDC ( hdcSize );
DeleteDC ( hdcOrg );
}
// Changes a HBITMAP to a 24 bit DIB
HDIB hDib = BitmapToDIB ( bmpUseThisOne, NULL );
::DeleteObject ( hBmpSized );
if ( hDib )
{
LPSTR lpDIBHdr, lpDIBBits; // pointer to DIB header, pointer to DIB bits
/* if invalid handle, return NULL */
/* lock memory block and get a pointer to it */
lpDIBHdr = (char *)GlobalLock(hDib);
if ( lpDIBHdr )
{
/* get a pointer to the DIB bits */
lpDIBBits = FindDIBBits(lpDIBHdr);
int iLen = 0;
void* p = Jpeg::Compress( lpDIBBits,iW,iH,3/*24bit=3Byte*/,iLen,iQ );
if ( p )
{
// JetJPG as return
*ppPicture = (unsigned char *)p;
*pnPictureBytes = iLen;
ret = true;
}
GlobalUnlock(hDib);
}
else
{
delete[] *ppPicture;
*ppPicture = NULL;
*pnPictureBytes = 0;
}
}
DestroyDIB ( hDib );
}
return ret;
}
// read image into this buffer.
void * Jpeg::ReadImage(int &width,
int &height,
int &nchannels,
const void *buffer,
int sizebytes)
{
JPEG_CORE_PROPERTIES jcprops;
if ( ijlInit(&jcprops) != IJL_OK )
{
ijlFree(&jcprops);
return 0;
}
jcprops.JPGBytes = (unsigned char *) buffer;
jcprops.JPGSizeBytes = sizebytes;
jcprops.jquality = 100;
if ( ijlRead(&jcprops,IJL_JBUFF_READPARAMS) != IJL_OK )
{
ijlFree(&jcprops);
return 0;
}
width = jcprops.JPGWidth;
height = jcprops.JPGHeight;
IJLIOTYPE mode;
mode = IJL_JBUFF_READWHOLEIMAGE;
nchannels = jcprops.JPGChannels;
unsigned char * pixbuff = new unsigned char[width*height*nchannels];
if ( !pixbuff )
{
ijlFree(&jcprops);
return 0;
}
jcprops.DIBWidth = width;
jcprops.DIBHeight = height;
jcprops.DIBChannels = nchannels;
jcprops.DIBPadBytes = 0;
jcprops.DIBBytes = (unsigned char *)pixbuff;
if ( jcprops.JPGChannels == 3 )
{
jcprops.DIBColor = IJL_RGB;
jcprops.JPGColor = IJL_YCBCR;
jcprops.JPGSubsampling = IJL_411;
jcprops.DIBSubsampling = (IJL_DIBSUBSAMPLING) 0;
}
else
{
jcprops.DIBColor = IJL_G;
jcprops.JPGColor = IJL_G;
jcprops.JPGSubsampling = (IJL_JPGSUBSAMPLING) 0;
jcprops.DIBSubsampling = (IJL_DIBSUBSAMPLING) 0;
}
if ( ijlRead(&jcprops, mode) != IJL_OK )
{
ijlFree(&jcprops);
return 0;
}
if ( ijlFree(&jcprops) != IJL_OK ) return 0;
return (void *)pixbuff;
}
void * Jpeg::Compress(const void *source,
int width,
int height,
int bpp,
int &len,
int quality)
{
JPEG_CORE_PROPERTIES jcprops;
jcprops.jprops.processor_type = IJL_PENTIUM_III_PROC;
jcprops.jprops.upsampling_type = IJL_TRIANGLE_FILTER;
if ( ijlInit(&jcprops) != IJL_OK )
{
ijlFree(&jcprops);
return false;
}
jcprops.DIBWidth = width;
jcprops.DIBHeight = -height;
jcprops.JPGWidth = width;
jcprops.JPGHeight = height;
jcprops.DIBBytes = (unsigned char *) source;
jcprops.DIBPadBytes = 0;
jcprops.DIBChannels = bpp;
jcprops.JPGChannels = bpp;
if ( bpp == 3 )
{
jcprops.DIBColor = IJL_BGR;
jcprops.JPGColor = IJL_YCBCR;
jcprops.JPGSubsampling = IJL_422;
jcprops.DIBSubsampling = (IJL_DIBSUBSAMPLING) 0;
}
else
{
jcprops.DIBColor = IJL_G;
jcprops.JPGColor = IJL_G;
jcprops.JPGSubsampling = (IJL_JPGSUBSAMPLING) 0;
jcprops.DIBSubsampling = (IJL_DIBSUBSAMPLING) 0;
}
int size = width*height*bpp;
unsigned char * buffer = new unsigned char[size];
jcprops.JPGSizeBytes = size;
jcprops.JPGBytes = buffer;
jcprops.jquality = quality;
IJLERR errWrite = ijlWrite(&jcprops,IJL_JBUFF_WRITEWHOLEIMAGE);
if ( errWrite != IJL_OK )
{
ijlFree(&jcprops);
delete buffer;
return 0;
}
if ( ijlFree(&jcprops) != IJL_OK )
{
delete buffer;
return 0;
}
len = jcprops.JPGSizeBytes;
return buffer;
}