Click here to Skip to main content
15,881,812 members
Articles / Programming Languages / C++
Article

Image Compressor

Rate me:
Please Sign up or sign in to vote.
2.79/5 (14 votes)
18 Jun 2009CPOL3 min read 45.7K   4K   17   11
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)


Written By
Pakistan Pakistan
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralMy vote of 1 Pin
Tomas Rapkauskas2-Jul-09 4:24
Tomas Rapkauskas2-Jul-09 4:24 
GeneralMy vote of 2 Pin
Niklas L28-Jun-09 23:05
Niklas L28-Jun-09 23:05 
GeneralMy vote of 1 Pin
Joe Woodbury28-Jun-09 10:06
professionalJoe Woodbury28-Jun-09 10:06 
GeneralNewbee problem i guess so Pin
Muhammad Hassan Haider28-Jun-09 11:57
Muhammad Hassan Haider28-Jun-09 11:57 
Thanks for all the points you brought out
1).Regarding your first 2 points i did it because thats what cximage class site mentioned in order to get the class to work.
2). I would look into the registry point you brought out and correct it.
3). Regarding the repeat code for Onclickedbrowsebutton1 and OnClickedBrowse2 thanks for the thing you pointed out. I intend making a class adding BROWSEINFO structure to it as a member. I think this would resolve the problem.
4). Manual entry should be looked into.
5). Start button point also noted and quite valid.
6). I am not getting your point regarding directory scan, told u a newbee.
7). I tried to rectify the problem after unresponsivenss but failed to do so. Any hint might be helpful. I am right now thinking of minimizing the application and performing the conversion process and maximizing it once the operations are done.
8). The progress bar also lacks because of this unresponsivenss.
9). I have tried to update the progress of each file but still working on it. It does not work. The fields somehow dont get updated.

Thanks for ur time and remarks.
Hopefully i would be able to put if not all somethings the right way.
Regards
Hassan
GeneralRe: Newbee problem i guess so Pin
Joe Woodbury28-Jun-09 17:39
professionalJoe Woodbury28-Jun-09 17:39 
GeneralRe: Newbee problem i guess so Pin
Muhammad Hassan Haider2-Jul-09 7:26
Muhammad Hassan Haider2-Jul-09 7:26 
GeneralMy vote of 1 Pin
f224-Jun-09 7:50
f224-Jun-09 7:50 
GeneralMy vote of 1 Pin
Gilad Novik22-Jun-09 11:34
Gilad Novik22-Jun-09 11:34 
AnswerRe: My vote of 1 Pin
Muhammad Hassan Haider22-Jun-09 12:39
Muhammad Hassan Haider22-Jun-09 12:39 
Questioncan you build this project in vs2005? Pin
xuplus18-Jun-09 14:21
xuplus18-Jun-09 14:21 
AnswerRe: can you build this project in vs2005? Pin
Muhammad Hassan Haider19-Jun-09 3:10
Muhammad Hassan Haider19-Jun-09 3:10 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.