menu
  Home  ==>  papers  ==>  graphic  ==>  delphi_image_resizing   

Delphi Image Resizing - Felix John COLIBRI.

  • abstract : resizing JPG images using the Graphics32 library. Load the JPEG, possibly rotate it, scale it, save it as a .PNG
  • key words : .JPG, .JPEG, .PNG, image resizing, image rotation, .JPEG to .PNG conversion, Graphics32, tKernelResampler, tImage32, tBitmap32
  • hardware used : intel i3-8100, 3.6 gHz, 8GB memory, 128 G and 1 T hard disc
  • software used : Windows 10 64 bit, Delphi 7
  • scope : Delphi 1 to 7, 2006 to 2010, Xe, Seattle, Tokyo, Berlin, 10.3
  • level : Delphi developer
  • plan :


1 - Resizing Jpeg Images

Writing a small .HTML report about a vacation trip, I wanted to resize the .JPG files. We used 3 different devices (a Panasonic camera, a Huawei Smartphone, an iPhone6), and the image sizes were too big and of different sizes.

Using Delphi tBitMap.StretchDraw is quite easy, but the result is poor. So, looking at StackOverflow, the best solutions presented was to use Graphics32 library.

This article simply presents an application which uses this library to resize images




2 - Delphi Image Resizing App

2.1 - Graphics32 image library

We downloaded both the basic Graphics32 library and the PNG library (since for our web pages, all images are .PNG files)



2.2 - The Delphi Application

The Delphi project simply imports both Graphics32 directories using the SearchPathes options (no need to add components to the palette)

The overall project structure is the usual tDirectoryListBox / tFileListBox combination.

Clicking on a .JPG file in the tFileListBox

  • loads the .JPG in a tImage32 object and computes the destination width and height which matches a 500 pixel width best

    Procedure _load_image_32;
      Begin
        g_c_image_32.Free;
        g_c_image_32:= TImage32.Create(Nil);

        With Form1 Do
        Begin
          g_c_image_32.Bitmap.LoadFromFile(g_pathg_file_name);

          With Image1.Picture.Bitmap Do
          Begin
            Width:= 0;
            Height:= 0;
          End// with Image1.Picture.Bitmap

          Image1.Picture.Bitmap.Assign(g_c_image_32.Bitmap);

          With Image1.Picture.Bitmap Do
          Begin
            g_original_width:= Width;
            g_original_height:= Height;

            l_ratio:= 500 / Width;
            l_power:= 1;
            For l_index:= 1 To 10 Do
            Begin
              If 1/ l_powerl_ratio
                Then Begin
                    g_destination_width:= Round(Width / l_power);
                    g_destination_height:= Round(Heightl_power);
                    Break;
                  End;

              l_power:= l_power* 2;
            End// for l_index
          End// with Image1.Picture.Bitmap
        End// with Form1
      End// _load_image_32

    the g_ being obvious global variables you will find in the .ZIP

  • then clicking on a Button resizes the bitmap and, if save_ is Checked, saves the result in the parent directory:

    Procedure resize_image32_3;

      Procedure _set_high_quality_stretch_filter(p_c_bitmap_32TBitmap32);
        Var l_c_kernel_resamplerTKernelResampler;
        Begin
          If Not (p_c_bitmap_32.Resampler Is TKernelResampler)
            Then
              Begin
                l_c_kernel_resampler:= TKernelResampler.Create(p_c_bitmap_32);
                l_c_kernel_resampler.Kernel:= TLanczosKernel.Create;
              End
            Else
              Begin
                l_c_kernel_resampler:= p_c_bitmap_32.Resampler As TKernelResampler;
                If Not (l_c_kernel_resampler.Kernel Is TLanczosKernel)
                  Then
                    Begin
                      l_c_kernel_resampler.Kernel.Free;
                      l_c_kernel_resampler.Kernel:= TLanczosKernel.Create;
                    End;
              End;
        End// _set_high_quality_stretch_filter

      Var l_c_source_bitmap_32l_c_destination_bitmap_32TBitmap32;
          l_file_nameString;

      Begin // resize_image32_3
        With Form1 Do
        Begin
          size_label_.Caption:= Format('%4d  %4d',
              [g_destination_widthg_destination_height]);

          l_c_source_bitmap_32:= tBitMap32.Create;

          l_c_source_bitmap_32.Assign(Image1.Picture.Bitmap);

          _set_high_quality_stretch_filter(l_c_source_bitmap_32);

          l_c_destination_bitmap_32:= TBitmap32.Create;
          l_c_destination_bitmap_32.SetSize(g_destination_widthg_destination_height);

          l_c_source_bitmap_32.DrawTo(l_c_destination_bitmap_32,
              Rect(0, 0, g_destination_widthg_destination_height),
              Rect(0, 0, l_c_source_bitmap_32.Widthl_c_source_bitmap_32.Height));

          FreeAndNil(l_c_source_bitmap_32);

          With l_c_destination_bitmap_32 Do
          Begin
            If _90.Checked
              Then Rotate90 Else
            If _180.Checked
              Then Rotate180 Else
            If _270.Checked
              Then Rotate270;

            Image2.Picture.Bitmap.Assign(l_c_destination_bitmap_32);

            If save_.Checked
              Then Begin
                  l_file_name:= ChangeFileExt(g_file_name'.png');
                  SaveBitmap32ToPNG(l_c_destination_bitmap_32g_path'..\'l_file_name);
                  ClipBoard.AsText:= l_file_name;
                End
              Else ClipBoard.AsText:= '';

            Free// l_c_destination_bitmap_32
          End// with l_c_destination_bitmap_32
        End// with Form1
      End// resize_image32_3




2.3 - Mini HowTo

Here is the snapshot of the project

delphi_image_resiing

and

  • create a directory for the resulting resized .PNG
  • create a sub-directory and place all your .JPG in this directory

  • start delphi_resize_images.exe
  • in the DirectoryListBox1, select the .JPG directory
  • for as many images as you like
    • select a .JPG in the FileListBox1
    • if the image is not upright, rotate it by clicking _90, _180 or _190
    • click one of the resizing button: size_ for the computed sizes, size_15_ for 1.5 size and size_2_ for double target size
    • if the result is satisfactory, check save_, click one of the size_ buttons, and
      • the result will be saved in the parent directory
      • the file name will bs stored in the ClipBoard (for inserting in the .HTML <IMG tag)



3 - Comments and links

3.1 - Comments

  • we only computed the resizing based on a hard coded 500 pixel width. This could be placed in an Edit, and the computations could take the Width or Height, depending on the portrait or landscape display of the image
  • the 500 pixel value is a self imposed limit: we want to avoid scrolling of the .HTML page, and for 778 width screen pages, this is a reasonable figure.
  • I basically assumed that dividing the image size by powers of 2 would result in better compression (less artifacts), but did not check. If the Graphics 32 algorithm is not sensible to this factor, we could avoid the power of 2 computations and resize exactly to fit the target size (500 pixel width in our case)
  • the procedures should also be parameterized instead of using globals
  • there still remains an update problem (which we also had with our StretchDraw program): when size_ is clicked, the image is not always displayed. Selecting the display_ tabsheet and the resized_ tabs again forces a refresh and solves the problem, in a somehow unsatisfactory way


3.2 - Links




4 - Download the Sources

Here are the source code files: You MUST download the Graphics32 libraries (link above) and replace the SearchPathes accordingly

The .ZIP file(s) contain:

  • the main program (.DPR, .DOF, .RES), the main form (.PAS, .DFM), and any other auxiliary form
  • any .TXT for parameters, samples, test data
  • all units (.PAS) for units
Those .ZIP
  • are self-contained: you will not need any other product (unless expressly mentioned).
  • for Delphi 6 projects, can be used from any folder (the pathes are RELATIVE)
  • will not modify your PC in any way beyond the path where you placed the .ZIP (no registry changes, no path creation etc).
To use the .ZIP:
  • create or select any folder of your choice
  • unzip the downloaded file
  • using Delphi, compile and execute
To remove the .ZIP simply delete the folder.

The Pascal code uses the Alsacian notation, which prefixes identifier by program area: K_onstant, T_ype, G_lobal, L_ocal, P_arametre, F_unction, C_lass etc. This notation is presented in the Alsacian Notation paper.



As usual:

  • please tell us at fcolibri@felix-colibri.com if you found some errors, mistakes, bugs, broken links or had some problem downloading the file. Resulting corrections will be helpful for other readers
  • we welcome any comment, criticism, enhancement, other sources or reference suggestion. Just send an e-mail to fcolibri@felix-colibri.com.
  • or more simply, enter your (anonymous or with your e-mail if you want an answer) comments below and clic the "send" button
    Name :
    E-mail :
    Comments * :
     

  • and if you liked this article, talk about this site to your fellow developpers, add a link to your links page ou mention our articles in your blog or newsgroup posts when relevant. That's the way we operate: the more traffic and Google references we get, the more articles we will write.



5 - The author

Felix John COLIBRI works at the Pascal Institute. Starting with Pascal in 1979, he then became involved with Object Oriented Programming, Delphi, Sql, Tcp/Ip, Html, UML. Currently, he is mainly active in the area of custom software development (new projects, maintenance, audits, BDE migration, Delphi Xe_n migrations, refactoring), Delphi Consulting and Delph training. His web site features tutorials, technical papers about programming with full downloadable source code, and the description and calendar of forthcoming Delphi, FireBird, Tcp/IP, Web Services, OOP  /  UML, Design Patterns, Unit Testing training sessions.
Created: jan-2020. Last updated: feb-2020 - 105 articles, 240 .ZIP sources, 1295 figures
Contact : Felix COLIBRI - Phone: (33)1.42.83.69.36 / 06.87.88.23.91 - email:fcolibri@felix-colibri.com
Copyright © Felix J. Colibri   http://www.felix-colibri.com 2004 - 2020. All rigths reserved
Back:    Home  Papers  Training  Delphi developments  Links  Download
the Pascal Institute

Felix J COLIBRI

+ Home
  + articles_with_sources
    + database
    + web_internet_sockets
    + rest_services
    + oop_components
    + uml_design_patterns
    + debug_and_test
    + graphic
      – delphi_3d_designer
      – write_a_flash_player
      – delphi_video_player
      – delphi_image_resizing
    + controls
    + colibri_utilities
    + colibri_helpers
    + delphi
    + IDE
    + firemonkey
    + compilers
    + vcl
  + delphi_training
  + delphi_developments
  + sweet_home
  – download_zip_sources
  + links
Contacts
Site Map
– search :

RSS feed  
Blog