Better JPEG

BetterJPEG LIBRARY API

BJPEG27.dll


First step in using the library is the initialization of the library:

STDAPI InitBJPEGLibrary(char* strName, char* strKey) - initializes the library.

strName - registration name.
strKey - registration key.

It is possible to use the library for evaluation purpose within 30-days period using "Evaluation" as a registration name and "DMGCOLLGDIIEJD" as a registration key.


Example of the library initialization / termination code:

HMODULE m_HM;

CJPEGlib::CJPEGlib(HMODULE* pHM)
{
	*pHM = m_HM = LoadLibrary("BJPEG27.dll");

	typedef HRESULT(__stdcall *FPT_P)(char*, char*);
	FPT_P FP_P;
	if (m_HM)
	{
		FP_P = (FPT_P)GetProcAddress(m_HM,"InitBJPEGLibrary");
		if (FP_P)
			if ((FP_P)("Evaluation", "DMGCOLLGDIIEJD") != S_OK)
			{
				//
			}
	}

}

CJPEGlib::~CJPEGlib()
{
	if (m_HM) FreeLibrary(m_HM);
}

Next step is creation of an object supporting IBJPEG interface (BJPEG object). This object represents a single jpeg image. All further work with the image is performed via IBJPEG interface of the corresponding object. Multiple instances of such objects can be created if work on several images at the same time is required.

STDAPI CreateBJPEGObject(IBJPEG** ppObject) - creates a BJPEG object with IBJPEG interface.

ppObject - pointer to a variable that receives a pointer to the object.


Example of object creation / destruction code:

HMODULE m_JPEGlib;

IBJPEG* m_pJPG;

CImage::CImage()
{
	m_pJPG = NULL;
	
	typedef HRESULT(__stdcall *FPT_P)(IBJPEG**);
	FPT_P FP_P;
	if (m_JPEGlib)
	{
		FP_P = (FPT_P)GetProcAddress(m_JPEGlib,"CreateBJPEGObject");
		if (FP_P)
			if ((FP_P)(&m_pJPG) != S_OK)
			{
				///
			}
	}
}

CImage::~CImage()
{
	if (m_pJPG) m_pJPG->Release();
}

IBJPEG INTERFACE METHODS


BOOL ReadImage(WCHAR* pwsFileName, ETypeOfReadImage iTypeOfRead) - reads JPEG file from file.

pwsFileName - full path to the JPEG file.
iTypeOfRead - indicates whether the whole image or just the EXIF information should be read. Set to IBJPEG::eReadWholeImage to read the whole image. Set to IBJPEG::eReadExifOnly to read the EXIF only.

returns TRUE in case of success.

Usually this is the first method called for a JPEG file. Can be called many times on the BJPEG object - call it each time you need to load a new image into the library.


BOOL ReadImageFromMemory(BYTE* pBuf, int iSize, ETypeOfReadImage iTypeOfRead) - reads JPEG file from memory.

pBuf - pointer to a buffer containing JPEG image.
iSize - size of the image in bytes.
iTypeOfRead - indicates whether the whole image or just the EXIF information should be read. Set to IBJPEG::eReadWholeImage to read the whole image. Set to IBJPEG::eReadExifOnly to read the EXIF only.

returns TRUE in case of success.


void ReleaseImage() - finishes work with the currently loaded image, releases memory.

Not required before ReadCoefficients.


BOOL IsLoaded()

returns TRUE if image is loaded (should return TRUE after successful call to ReadCoefficients up until ReleaseImage).


int GetWidth()
int GetHeight()

return picture dimensions in pixels.

After manipulations on the image, such as rotation, crop, etc. these methods return updated dimensions (correct).


int GetMCUWidth()
int GetMCUHeight()

return MCU (minimum coded unit) dimensions for current image in pixels.

MCUs can have 8x8, 8x16, 16x8, and 16x16 dimensions. After rotation this method returns updated dimensions.


BOOL Reconstruct(int iPasses, PFNPROGRESS pfnProgress) - attempts to improve the quality of JPEG decoding by using an improved method of dequantization on DCT coefficients.

iPasses - the number of passes.
pfnProgress - optional pointer to a callback progress tracking function. If NULL, no callback function is called during reconstruction.

returns TRUE in case of success.


BOOL GetBitmap(BYTE* pScan0, int iStride, BOOL bWholeMCUs) - decodes the jpeg image into an external bitmap buffer.

pScan0 - address in an external buffer, points to where the first scan line of the image should go.
iStride - the absolute value of the stride is equal to the width of a single row of pixels in the target bitmap. The sign of the stride defines the orientation of the bitmap output. If the stride is negative the bitmap output is in upside down sequence.
bWholeMCUs - if TRUE, the resulting bitmap will have dimensions rounded up to whole MCU boundaries.

returns TRUE in case of success.

Output is in BGR sequence. Grayscale jpegs are converted to BGR as well.


Sample code:

BOOL CImage::CreateBitmap()
{
	// Get image dimensions
	int iBitmapWidth = m_pJPG->GetWidth();
	int iBitmapHeight = m_pJPG->GetHeight();

	// Fill in bitmap info
	m_iBMPRowSize = (((iBitmapWidth * 3) + 3) & 0xfffffffc);
	m_bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	m_bmi.bmiHeader.biCompression = BI_RGB;
	m_bmi.bmiHeader.biBitCount = 24;
	m_bmi.bmiHeader.biPlanes = 1;
	m_bmi.bmiHeader.biWidth = iBitmapWidth;
	m_bmi.bmiHeader.biHeight = iBitmapHeight;
	m_bmi.bmiHeader.biSizeImage = m_iBMPRowSize * iBitmapHeight;
	m_bmi.bmiHeader.biXPelsPerMeter = 0;
	m_bmi.bmiHeader.biYPelsPerMeter = 0;
	m_bmi.bmiHeader.biClrUsed = 0;
	m_bmi.bmiHeader.biClrImportant = 0;

	// Create new bitmap
	if (!(m_hBitmap = CreateDIBSection(NULL, &m_bmi, DIB_RGB_COLORS, (PVOID*)&m_pBits, NULL, 0))) return FALSE;

	m_pJPG->GetBitmap(m_pBits + m_iBMPRowSize * (iBitmapHeight-1), -m_iBMPRowSize, FALSE);

	return TRUE;
}

In many cases decoding of the bitmap is not required, lossless operations can be performed on jpeg coefficients, without having to decode.


int GetImageSize() - calculates the size of the JPEG image.

returns size of the JPEG image in bytes.


BOOL Save(WCHAR* pwsFileName, save_params* pParams) - saves changed JPEG image to file.

pwsFileName - full path to the target file (if blank, the file is saved with the original name).
pParams - pointer to save_params structure.

returns TRUE in case of success.

struct save_params
{
  int iCompressionMode;    // Whether to recompress the whole image or changes only.
                           // eCompressChangesOnly - lossless/nearly lossless mode, only
                           //     changed blocks are recompressed.
                           // eCompressAll - lossy mode, the whole image is recompressed.

  int iQuality;            // Defines the image quality (0-100) when the iCompressionMode
                           // parameter is set to eCompressAll.

  int iColorSampling;      // Defines the sampling factors for color components when the
                           // iCompressionMode parameter is set to eCompressAll.
                           // eSampling1 - 1,1 - better quality
                           // eSampling1 - 2,2 - smaller size (default).

  BOOL bRetainOriginalTime // Retain original file date / time
  BOOL bOptimizeHuffman    // Optimize Huffman tables (smaller size without loss in quality)
  BOOL bSaveComments       // Do not discard comments (metadata)
  BOOL bSaveEXIF           // Do not discard EXIF

  // Thumbnail
  int iGenerateEXIFThumb   // EXIF thumbnail refresh mode
                           // eThumbNever - remove EXIF thumbnail
                           // eThumbKeepExisting - keep existing EXIF thumbnail
                           // eThumbRegenerateExisting - refresh EXIF thumbnail (if the one exists)

  int iEXIFThumbSize       // Max thumbnail dimension in pixels (32-256)

  // Bitmap
  BYTE* pScan0  // If not NULL, pScan0 points to the first scan line of an external bitmap,
                // the bitmap is compared to JPEG coefficients and all the changed
                // coefficients get recompressed on DCT level rather than on MCU
                // which results in minimal possible recompression (can be used for red-eye
                // removal, text imprint, paste, watermark, frames, etc without full
                // recompression). The bitmap provided should match the current state of
                // the image - if the image has been rotated, the bitmap should have
                // corresponding orientation, if the image has been cropped, the bitmap
                // should have corresponding dimensions, etc. Calling Save method does
                // not change coefficients in memory, it only saves changes to file.
                // pScan0 can be NULL if bitmap is not required (rotation, flip, crop)

  int iStride         // Bitmap row size

  // Statistics (returned values)
  int iMCUsTotal      // total number of MCUs
  int iDCTsTotal      // total number of DCTs
  int iMCUsChanged    // number of MCUs changed
  int iDCTsChanged    // number of DCTs changed
};


BOOL SaveToMemory(BYTE* pBuf, int iSize) - saves changed JPEG image to memory.

pBuf - pointer to an output buffer.
iSize - size of the buffer in bytes.

returns TRUE in case of success.


BOOL Crop(int iLeft, int iTop, int iRight, int iBottom) - performs lossless crop.

returns TRUE in case of success.


BOOL FlipH(BOOL bPreservePartial) - flips horizontally (lossless).

bPreservePartial - if FALSE, partial MCUs will be discarded.

returns TRUE in case of success.


BOOL FlipV(BOOL bPreservePartial) - flips vertically (lossless).

bPreservePartial - if FALSE, partial MCUs will be discarded.

returns TRUE in case of success.


BOOL RotateLeft(BOOL bPreservePartial) - rotates clockwise (lossless).

bPreservePartial - if FALSE, partial MCUs will be discarded.

returns TRUE in case of success.


BOOL RotateRight(BOOL bPreservePartial) - rotates counter-clockwise (lossless).

bPreservePartial - if FALSE, partial MCUs will be discarded.

returns TRUE in case of success.


BOOL ConvertGrayscale() - converts to grayscale by discarding chroma components and without recompressing the luminosity component.

returns TRUE in case of success.


BOOL CanConvertGrayscale() - determines whether the image can be converted to grayscale without recompression.

returns TRUE if the lossless conversion to grayscale is possible.


BOOL IsGrayscale() - reports whether the image is grayscale or not.

returns TRUE if the image is grayscale.


BOOL Undo() - undoes previous operation.

returns TRUE in case of success.

Undo buffer is not limited.


BOOL CreatePreview(WCHAR* pwsFileName, BYTE* pBits, int iThumbWidth, int iThumbHeight, int iStride, BYTE iR, BYTE iG, BYTE iB, int* piImageWidth, int* piImageHeight, int iExtFlags) - generates a quick scaled down preview.

pwsFileName - file name,
pBits - pointer to an external bitmap buffer,
iThumbWidth, iThumbHeight - preview bitmap dimensions,
iStride - the absolute value of the stride is the bitmap width (can be >= iThumbWidth*3), the sign defines the output direction,
iR, iG, iB - background color,
piImageWidth, piImageHeight - pointers to variables that receive original picture dimensions (not scaled down),
iExtFlags - flags, indicating whether a border/shadow around the preview should be drawn. Possible values are 0, eThumbDrawWhiteBorder, eThumbDrawDarkBorder, eThumbDrawShadow, the values can be combined.

returns TRUE in case of success.

This method is used by BetterJPEG to generate thumbnails for the folder browser pane.

CreatePreview is an independent method that does not require calling ReadCoefficients and ReleaseImage. CreatePreview can be called on any BJPEG object without affecting the state of the object.


LPCSTR Format(LPCSTR szFormat, BOOL bUseFileTime, LCID iLocale, LPCSTR szDateFormat, LPCSTR szTimeFormat) - returns formatted EXIF parameters string.

szFormat - format string, can contain text and the following parameters:

Mask   Parameter   Output example
%C Copyright sign ©
%c Comment Fred's Dog
%d Date (in format defined in preferences) May 04, 2004
%e Exposure time 1/61s
%f F-number F2.6
%i ISO speed ratings ISO100
%L Focal length in 35mm film equivalent 38mm
%l Focal length 7.9mm
%M Make NIKON
%m Model E4500
%t Time (in format defined in preferences) 12:52
%u User comment Fred's Dog
%V Source file name (the name with which the file was open) DSCN0475
%v Source file name and extension DSCN0475.jpg
%W Destination file name (the name under which the file was last saved) dog2
%w Destination file name and extension dog2.jpg
%% Percent sign %

bUseFileTime - use file time if no EXIF is present.

iLocale - locale (for correct date / time format).

szDateFormat - date format string can contain the following parameters:

Element Meaning
d Day of month as digits with no leading zero for single-digit days.
dd Day of month as digits with leading zero for single-digit days.
ddd Day of week as a three-letter abbreviation.
dddd Day of week as its full name.
M Month as digits with no leading zero for single-digit months.
MM Month as digits with leading zero for single-digit months.
MMM Month as a three-letter abbreviation.
MMMM Month as its full name.
y Year as last two digits, but with no leading zero for years less than 10.
yy Year as last two digits, but with leading zero for years less than 10.
yyyy Year represented by full four digits.

szTimeFormat - time format string:

Element Meaning
h Hours with no leading zero for single-digit hours; 12-hour clock.
hh Hours with leading zero for single-digit hours; 12-hour clock.
H Hours with no leading zero for single-digit hours; 24-hour clock.
HH Hours with leading zero for single-digit hours; 24-hour clock.
m Minutes with no leading zero for single-digit minutes.
mm Minutes with leading zero for single-digit minutes.
s Seconds with no leading zero for single-digit seconds.
ss Seconds with leading zero for single-digit seconds.
t One character time-marker string, such as A or P.
tt Multicharacter time-marker string, such as AM or PM.


USHORT GetOrientation() - gets EXIF image orientation flag.

returns EXIF image orientation flag.


void SetOrientation(USHORT iOrientation) - sets EXIF image orientation flag.

iOrientation - EXIF image orientation flag.


thumbnail_info GetThumbnailInfo() - gets EXIF thumbnail image dimentions.

returns thumbnail_info structure.

struct thumbnail_info {
  USHORT iWidth;   // thumbnail image width
  USHORT iHeight;  // thumbnail image height
};


BetterJPEG library is based in part on the work of the Independent JPEG Group.