Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C++

Image Compressor

2.79/5 (14 votes)
18 Jun 2009CPOL3 min read 46.8K   4.1K  
Compressing Images the easiest way
ImageCompressor_source

Introduction

It is very often that one needs to send pictures by email. Because of the size of the image files it takes very long to upload these images, especially if one has a slow internet connection. I have been using MS Paint to open the files and used its Save As function to save the image files in JPEG format. The problem was the time it takes to open each file, Save As, and enter file name. This little program addresses this problem in that it uses MFC built in classes plus the very reliable CxImage class to perform compression. The user just needs to add the source folder and destination folder and all the image files are loaded and saved without any other user input.

Background

The conversion all takes place using the CxImage class. The class is available both in a lite version and the complete one. The CodeProject site also has detailed article on how to use the CxImage class. It's not really required but it would give you some idea of what actually is going on.

Using the Code

It’s a very simple dialog based application. The source directory is selected by the user and then the destination directory is selected by the user. The files are read from the source directory and then converted in a while loop. The files which are to be converted have to be of the extension JPEG, BMP, JPG, or TIFF (this all is done via if statements). A progress control bar is added and based on the number of files converted it progresses file by file. The files that are successfully converted are displayed in a window, while all the files which are not converted are marked as errors and then displayed in the second window. A slider control selects the ratio of compression to achieve. All the conversion takes place with the help of the CxImage class which loads the image, sets the JPEG quality and then saves the file in the directory selected by the user. Two Listboxes are also added with one displaying the result of the files successfully converted and the later filenames which have not been converted.

The source and destination directories are selected using BROWSEINFO structure as:

C++
BROWSEINFO bi = { 0 };
bi.lpszTitle = _T("Select path for Source Directory");
bi.ulFlags = BIF_USENEWUI;
LPITEMIDLIST pidl = SHBrowseForFolder ( &bi );
if ( pidl != 0 )
{
    // get the name of the folder
    TCHAR path[MAX_PATH];
    if ( SHGetPathFromIDList ( pidl, path ) )
    {
        _tprintf ( _T("Selected Folder: %s\n"), path );
    }
    m_SourceDir = path;
    UpdateData(FALSE);

    // free memory used
    IMalloc * imalloc = 0;
    if ( SUCCEEDED( SHGetMalloc ( &imalloc )) )
    {
        imalloc->Free ( pidl );
        imalloc->Release ( );
    }

On clicking the Start Button the number of files to be converted are first calculated and based on the number of files calculated, and file names are generated using the code. The file names generated are stored in a CStringArray object.

C++
CString numb;
CStringArray filenames;
CString add = "\\image";
CString add1 = ".jpg";
for (int x=1;x<=n;x++)
{
    numb.Format("%d",x);
    CString fname = m_DestDir+add+numb+add1;
    filenames.Add(fname);
}

Using a CFileFind class object the directory selected as source directory is then used in a while loop to iterate through each file and based on the filenames already generated, file names are given. The progress bar moves file by file and eventually any error generated is listed in the list box alongside the file names successfully converted.

C++
int no = filenames.GetCount();      // getting total number of file names from CStringArray object
CString filename;                   // making sure a valid file extension is selected
m_ProgressBar.SetRange(0,n);
m_ProgressBar.SetStep(1);
BOOL bS1 = finder.FindFile(_T(m_SourceDir+CString("\\*.*")));
int num=0;
m_Slider = m_SliderValue.GetPos();
while(bS1)
{
    bS1 = finder.FindNextFile();
    if(finder.IsDots() || finder.IsDirectory())
        continue;
    filename = finder.GetFileTitle();   // getting the filename used in the following if statement
    if(num==no)                         // if true we have converted all the files
        break;      
    if ((filename+CString(".jpg") == finder.GetFileName()) || 
        (filename+CString(".bmp") == finder.GetFileName()) ||
        (filename+CString(".jpeg") == finder.GetFileName()) || 
        (filename+CString(".tiff") == finder.GetFileName()))
    {                 
        image.Load(finder.GetFilePath(),0); // loading file into memory using CxImage Class
        image.SetJpegQuality(m_Slider);           // setting the compression ratio
        image.Save(filenames.GetAt(num),CXIMAGE_FORMAT_JPG);  // saving the file using
                                                              // already generated filename
        m_ConvFiles.AddString(filename+CString(" -->> Converted successfully"));
        m_ProgressBar.StepIt();
        ++num;
    }
    else
    {
        m_Errors.AddString(finder.GetFileName()+CString(" -->> File format Invalid"));
        continue;
    }
}

Points of Interest

The application uses CxImage class for achievement the desired compression.

History

Version 1.0.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)