Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

The Ultimate Toolbox Graphic Format Classes

0.00/5 (No votes)
25 Aug 2007 1  
The Ultimate Toolbox contains classes for dealing with Bitmap and JPEG files.

Visit the Ultimate Toolbox main page for an overview and configuration guide to the Ultimate Toolbox library.

Contents

Introduction

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.

Bitmaps

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.

JPEG

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.

JPEG Compression and Decompression

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);    // save BMP as JPG...


        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);              // save JPG as BMP


        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.

History

Initial CodeProject release August 2007.

Comments

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.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here