Visit the Ultimate Toolbox main page for an overview and configuration guide to the Ultimate Toolbox library.
Contents
The Ultimate Toolbox Graphic Formats classes are primarily concerned with facilitating the display of bitmap and JPEG files.
The Ultimate Toolbox source code download contains source code for the building of the JPEG libraries. These files are copyright (c) 1991-1995, Thomas G. Lane, and form part of the Independent JPEG Group's software.
COXBMPFile
is derived from COXGraphicsFile
and encapsulates the reading and writing of bitmap (BMP) files.
It handles all the basic routines for reading/writing the BMP header and body, opening/closing BMP files, etc. These methods are all protected and so should not be used directly. They are all called by the Compressor/Decompressor classes.
All you have to specify is the filename or CFile
pointer (must already be open) that you need to use. There are two constructors provided for this purpose. The first takes a CString
filename:
COXBMPFile(CString sFullPath);
When using this form, the COXBMPFile
class takes care of opening and closing the BMP file.
The second takes a pointer to an open file:
COXBMPFile(CFile* pBMPFile);
When using this form, the COXBMPFile
class does not open and close the BMP file. The user must pass an already open CFile
to this constructor, and take care of additional file operations. It is irrelevant to COXBMPFile
whether it is a CFile
on disk or a CMemFile
.
COXJPEGException
handles all basic routines for reading/writing JPEG header and body, opening/closing JPEG files, etc. These methods are all protected and so should not be used directly. They are all called by the Compressor/Decompressor classes.
All you have to specify is the filename or CFile
pointer (must be open already) that you need to use. There are two constructors provided for this purpose:
COXJPEGFile(CString sFullPath);
When using this form, the COXJPEGFile
class takes care of opening and closing the JPEG file.
COXJPEGFile(CFile* pJPEGFile);
When using this form, the COXJPEGFile
class does not open and close the JPEG file. The user must pass an already open CFile
to this constructor, and handle additional file operations. It is irrelevant to the COXJPEGFile
whether it is a CFile
on disk or a CMemFile
.
Screenshot of the samples\graphics\JPGTest sample.
The COXJPEGCompressor
and COXJPEGDecompressor
classes implement JPEG image compression and decompression.
The JPGTest example shows the COXBMPFile
and COXJPEGFile
as well as COXJPEGCompressor
in action. The OnCompress
handler creates the objects, initializes the compression parameters and simply calls COXLPEGCompressor::DoCompress
:
void CJPGtestDlg::OnCompress()
{
if (!UpdateData(TRUE))
return;
BeginWaitCursor();
COXBMPFile BMPFile(m_sGraphicsFile);
COXJPEGFile JPGFile(m_sJPEGFile);
COXJPEGCompressor JCompr;
JCompr.SetGrayScale(m_bGray);
JCompr.SetBaseLine(m_bBase);
JCompr.SetProgressive(m_bProgr);
JCompr.SetOptimize(m_bOpt);
JCompr.SetQuality(m_nQuality);
if (m_nSmooth != 0)
JCompr.SetSmooth(m_nSmooth);
JCompr.SetMaxMemory(m_nMaxMem);
if (m_nDCT != -1)
JCompr.SetDisCosTranf((EDiscreteCosTransf)(m_nDCT + 1));
DWORD nBeginTicks, nEndTicks;
nBeginTicks = GetTickCount();
short nReturn(0);
TCHAR ErrorBuffer[SIZE_ERROR_BUF];
TRY
{
nReturn = JCompr.DoCompress(&BMPFile,
&JPGFile);
if (nReturn == 2)
AfxMessageBox(JCompr.GetWarningMessages());
}
CATCH(COXJPEGException, e)
{
e->GetErrorMessage(ErrorBuffer, SIZE_ERROR_BUF);
AfxMessageBox(CString("Exception : ") + ErrorBuffer);
TRACE((LPCTSTR)ErrorBuffer);
}
END_CATCH
nEndTicks = GetTickCount();
char buffer[20];
UTBStr::sprintf(buffer, 20, "%f",
(nEndTicks - nBeginTicks)/1000.0);
m_Time_Static.SetWindowText(buffer);
EndWaitCursor();
}
The OnUnCompress
routine is similar:
void CJPGtestDlg::OnUnCompress()
{
if (!UpdateData(TRUE))
return;
BeginWaitCursor();
COXBMPFile BMPFile(m_sGraphicsFile);
BMPFile.SetOS2Format(m_bOS2);
COXJPEGFile JPGFile(m_sJPEGFile);
COXJPEGDecompressor JDecompr;
JDecompr.SetGrayScale(m_bGrayScale2);
JDecompr.SetFast(m_bFast);
JDecompr.SetNoSmooth(m_bNoSmooth);
JDecompr.SetOnePass(m_bOnePass);
JDecompr.SetMaxMemory(m_nMaxMem2);
if (m_nDCT2 != -1)
JDecompr.SetDisCosTranf((EDiscreteCosTransf)(m_nDCT2 + 1));
if (m_nDither != -1)
JDecompr.SetDitherMethod((EDitherMethod)(m_nDither + 1));
if (m_nScale != -1)
JDecompr.SetScale((EDecompScale)(m_nScale + 1));
if (m_nColors != 0)
JDecompr.SetColors(m_nColors);
DWORD nBeginTicks, nEndTicks;
nBeginTicks = GetTickCount();
short nReturn(0);
TCHAR ErrorBuffer[SIZE_ERROR_BUF];
TRY
{
nReturn = JDecompr.DoDecompress(&JPGFile,
&BMPFile);
if (nReturn == 2)
AfxMessageBox(JDecompr.GetWarningMessages());
}
CATCH(COXJPEGException, e)
{
e->GetErrorMessage(ErrorBuffer, SIZE_ERROR_BUF);
AfxMessageBox(CString("Exception : ") + ErrorBuffer);
TRACE((LPCTSTR)ErrorBuffer);
}
END_CATCH
nEndTicks = GetTickCount();
char buffer[20];
UTBStr::sprintf(buffer, 20, "%f",
(nEndTicks - nBeginTicks)/1000.0);
m_Time_Static.SetWindowText(buffer);
EndWaitCursor();
}
See the COXJPEGCompressor
class reference in the compiled HTML documentation for more on the usage and effects of the various compression settings available.
Initial CodeProject release August 2007.
Color gif files are not the best input for JPEG. JPEG is really intended for compressing full-color (24-bit) images. Furthermore, don't try to convert cartoons, line drawings, and other images that have only a few distinct colors. gif works great on these but JPEG does not. If you want to convert a gif to JPEG, you should experiment with COXjpgCompressor
SetQuality
and SetSmooth
options until you get a satisfactory conversion. SetSmooth(10)
or so is often helpful.
Avoid running an image through a series of JPEG compression/decompression cycles. Image quality loss will accumulate and, after ten or so cycles, the image may have become noticeably worse than it was after just one. It's better to use a lossless format while manipulating an image, then convert to JPEG format when you are ready to file that image away.