Solved

Image resizing

Posted on 2009-07-04
10
615 Views
Last Modified: 2012-05-07
I'm in serious need of advise on this one.

I have a code that resizes jpeg images to 200px wide or 150px high depending on portrait or landscape attributes, that I have accomplished without problems, now, obviously the target size should be 200px wide by 150px high. Therefore I need some space around the images to accomplish that requirement, meaning that I need every resulting image to be 200px wide by 150px high without cropping or distorting the originals.

It would be great if the space around the image could be of a color of choice.

Please help.

Thanks in advance.
0
Comment
Question by:jorgemgonzalez
  • 4
  • 3
  • 2
  • +1
10 Comments
 
LVL 12

Expert Comment

by:Ammar Gaffar
ID: 24777929
In ASP.NET or VB.NET Windows Application?
0
 
LVL 39

Expert Comment

by:abel
ID: 24777945
In the code below (I know, it is C#, I'll come to that) that I just created and tested, it does exactly what you want. The key is the PicureBox_Paint event and the drawScaledImage. The background color is done by the eraseImage method.

To make this work, create a form, place a button, a picturebox and a openfiledialog on it. On the buttonclick event you assign the filename of the image to a field, m_image_filename. The picturebox will be redrawn (.Invalidate()) and the drawScaledImage is called. The method DrawImage does the scaling for you, the hard part is actually the calculation of the various rectangles. I kept the code clean and simple as far as I could, the result is that it is not very optimized. But it should do for this basic task.

In my next post I'll give an update in VB code of the same.

-- Abel --

public partial class ResizeKeepRatio : Form

{

    private string m_image_filename = null;
 

    public ResizeKeepRatio()

    {

        InitializeComponent();

    }
 

    private void button1_Click(object sender, EventArgs e)

    {

        openFileDialog1.ShowDialog();

        m_image_filename = openFileDialog1.FileName;

        pictureBox1.Invalidate();

    }
 

    private void eraseImage(Graphics graph)

    {

        Rectangle rect = new Rectangle(0, 0, pictureBox1.Width, pictureBox1.Height);

        graph.DrawRectangle(new Pen(Brushes.Orange, (float) rect.Width), rect);

    }
 

    private void drawScaledImage(Graphics graph)

    {

        if(m_image_filename == null)

            return;
 

        Bitmap bmp = new Bitmap(m_image_filename);

        Rectangle sourceRect = new Rectangle(0, 0, bmp.Width, bmp.Height);

        Rectangle drawAreaRect = new Rectangle(0, 0, pictureBox1.Width, pictureBox1.Height);

        Rectangle targetRect;
 

        // determine whether to resize horizontally or vertically

        // based on the ratio width/height of source image and target rectangle

        double sourceRatio = (double)sourceRect.Height / (double)sourceRect.Width;

        double targetRatio = (double)drawAreaRect.Height / (double)drawAreaRect.Width;

        double drawRatio;

        if (sourceRatio > targetRatio)

            drawRatio = (double) drawAreaRect.Height / (double) sourceRect.Height;

        else

            drawRatio = (double) drawAreaRect.Width / (double) sourceRect.Width;
 

        // calculate target rectangle and center

        targetRect = new Rectangle(

            (int) ((drawAreaRect.Width - drawRatio * sourceRect.Width) / 2), 

            (int) ((drawAreaRect.Height - drawRatio * sourceRect.Height) / 2), 

            (int) (drawRatio * sourceRect.Width), 

            (int) (drawRatio * sourceRect.Height));
 

        // draw the image

        graph.DrawImage(bmp, targetRect);

    }
 

    private void pictureBox1_Paint(object sender, PaintEventArgs e)

    {

        eraseImage(e.Graphics);

        drawScaledImage(e.Graphics);

    }
 

}

Open in new window

0
 
LVL 39

Expert Comment

by:abel
ID: 24777957
The VB code is a bit less readable, as is often with calculation code (matter of taste, of course), but here you go (courtesy to http://www.developerfusion.com/tools/convert/csharp-to-vb/):

Public Partial Class ResizeKeepRatio

    Inherits Form

    Private m_image_filename As String = Nothing

    

    Public Sub New()

        InitializeComponent()

    End Sub

    

    Private Sub button1_Click(ByVal sender As Object, ByVal e As EventArgs)

        openFileDialog1.ShowDialog()

        m_image_filename = openFileDialog1.FileName

        pictureBox1.Invalidate()

    End Sub

    

    Private Sub eraseImage(ByVal graph As Graphics)

        Dim rect As New Rectangle(0, 0, pictureBox1.Width, pictureBox1.Height)

        graph.DrawRectangle(New Pen(Brushes.Orange, CSng(rect.Width)), rect)

    End Sub

    

    Private Sub drawScaledImage(ByVal graph As Graphics)

        If m_image_filename Is Nothing Then

            Exit Sub

        End If

        

        Dim bmp As New Bitmap(m_image_filename)

        Dim sourceRect As New Rectangle(0, 0, bmp.Width, bmp.Height)

        Dim drawAreaRect As New Rectangle(0, 0, pictureBox1.Width, pictureBox1.Height)

        Dim targetRect As Rectangle

        

        ' determine whether to resize horizontally or vertically '

        ' based on the ratio width/height of source image and target 'rectangle

        Dim sourceRatio As Double = CDbl(sourceRect.Height) / CDbl(sourceRect.Width)

        Dim targetRatio As Double = CDbl(drawAreaRect.Height) / CDbl(drawAreaRect.Width)

        Dim drawRatio As Double

        If sourceRatio > targetRatio Then

            drawRatio = CDbl(drawAreaRect.Height) / CDbl(sourceRect.Height)

        Else

            drawRatio = CDbl(drawAreaRect.Width) / CDbl(sourceRect.Width)

        End If

        

        ' calculate target rectangle and center '

        targetRect = New Rectangle(CInt(((drawAreaRect.Width - drawRatio * sourceRect.Width) / 2)), CInt(((drawAreaRect.Height - drawRatio * sourceRect.Height) / 2)), CInt((drawRatio * sourceRect.Width)), CInt((drawRatio * sourceRect.Height)))

        

        ' draw the image '

        graph.DrawImage(bmp, targetRect)

    End Sub

    

    Private Sub pictureBox1_Paint(ByVal sender As Object, ByVal e As PaintEventArgs)

        eraseImage(e.Graphics)

        drawScaledImage(e.Graphics)

    End Sub

    

End Class

Open in new window

0
 
LVL 39

Expert Comment

by:abel
ID: 24777991
In the screenshot you can see one of Window's Vista's sample pictures with a green border. It is a test with the VB code because I wasn't sure if would compile. Don't forget to add the click and paint events! (I did). You can use a ColorDialog for picking the color, which goes into line 17 above.

Happy coding with it! ;-)

ScreenShot419.png
0
 
LVL 85

Accepted Solution

by:
Mike Tomlinson earned 500 total points
ID: 24778184
I see from one your PAQs that you have VB2008.  You could "cheat" and just use a PictureBox with the SizeMode set to Zoom.

Simple example having a PictureBox and two Buttons.  Double click the PictureBox to change the color.  Click Button1 to open an image.  Click Button2 to save the Image.
Public Class Form1
 

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        PictureBox1.Size = New Size(200, 150)

        PictureBox1.BackColor = Color.DarkGreen

        PictureBox1.SizeMode = PictureBoxSizeMode.Zoom

    End Sub
 

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        Using ofd As New OpenFileDialog

            If ofd.ShowDialog = Windows.Forms.DialogResult.OK Then

                ofd.Title = "Open Image"

                ofd.Filter = "Image Files(*.BMP;*.JPG;*.GIF)|*.BMP;*.JPG;*.GIF|All files (*.*)|*.* "

                Try

                    Using fs As New System.IO.FileStream(ofd.FileName, IO.FileMode.Open)

                        PictureBox1.Image = Image.FromStream(fs)

                    End Using

                Catch ex As Exception

                    MessageBox.Show("File: " & ofd.FileName & vbCrLf & vbCrLf & ex.Message, "Error Opening Image", MessageBoxButtons.OK, MessageBoxIcon.Error)

                End Try

            End If

        End Using

    End Sub
 

    Private Sub PictureBox1_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles PictureBox1.DoubleClick

        Using cd As New ColorDialog

            If cd.ShowDialog = Windows.Forms.DialogResult.OK Then

                PictureBox1.BackColor = cd.Color

            End If

        End Using

    End Sub
 

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click

        If Not IsNothing(PictureBox1.Image) Then

            Using sfd As New SaveFileDialog

                sfd.Title = "Save Image"

                sfd.Filter = "JPEG (*.JPG)|*.JPG|Bitmap (*.BMP)|*.BMP|GIF (*.GIF)|*.GIF"

                If sfd.ShowDialog = Windows.Forms.DialogResult.OK Then

                    Dim bmp As New Bitmap(PictureBox1.ClientSize.Width, PictureBox1.ClientSize.Height)

                    PictureBox1.DrawToBitmap(bmp, PictureBox1.ClientRectangle)

                    Try

                        Select Case System.IO.Path.GetExtension(sfd.FileName).ToUpper

                            Case ".BMP"

                                bmp.Save(sfd.FileName, Drawing.Imaging.ImageFormat.Bmp)
 

                            Case ".JPG"

                                bmp.Save(sfd.FileName, Drawing.Imaging.ImageFormat.Jpeg)
 

                            Case ".GIF"

                                bmp.Save(sfd.FileName, Drawing.Imaging.ImageFormat.Gif)
 

                        End Select

                    Catch ex As Exception

                        MessageBox.Show("File: " & sfd.FileName & vbCrLf & vbCrLf & ex.Message, "Error Saving Image", MessageBoxButtons.OK, MessageBoxIcon.Error)

                    End Try

                End If

            End Using

        End If

    End Sub
 

End Class

Open in new window

0
What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 

Author Comment

by:jorgemgonzalez
ID: 24778554
Thank you experts for your fast reply.

I created a separate project for each solution and copied the code exactly as posted. For some reason Abel's one did not work at all after clicking button1. Is there something missing?

Idle Mind's (And I.ve always said that mind is whatever but idle) worked like a charm, I love the idea.

Now, what I missed in my question (my apologies) is that the code I have (And need) is for  resizing ingmultiple images, (For ---> Next) actually all the images in a folder via folder browser dialog, I have no picture boxes in my form!

Attached is part of the code so you can have a better idea.

Is there a way of getting the same result without the PicBox?

Otherwise please advise on how to load - unload the images on the PicBox for each file in directory.
Dim bp As New Bitmap(newSize.Width, newSize.Height)

                Dim g As Graphics = Graphics.FromImage(bp)
 

                ' Controls the quality of the image

                g.SmoothingMode = Drawing2D.SmoothingMode.HighQuality

                g.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBicubic

                g.PixelOffsetMode = Drawing2D.PixelOffsetMode.HighQuality
 

                Dim rect As New Rectangle(0, 0, newSize.Width, newSize.Height)

                g.DrawImage(currentImage, rect, 0, 0, currentImage.Width, currentImage.Height, GraphicsUnit.Pixel)
 

                ' Copy Meta from old image to new image

                For Each pItem As System.Drawing.Imaging.PropertyItem In currentImage.PropertyItems

                    bp.SetPropertyItem(pItem)

                Next

                newFileName = "Thumb_" & file.ToString

                ' Saves as jpeg

                bp.Save(NewDir & "\Thumbnails\" & newFileName, Imaging.ImageFormat.Jpeg)

Open in new window

0
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 24778692
You can actually use my concept with a dynamic PictureBox that is never even visible to the user...

    Dim pb As New PictureBox
    pb.Size = New Size(200, 150)    
    pb.BackColor = Color.DarkGreen
    pb.SizeMode = PictureBoxSizeMode.Zoom

Then iterate thru your files and use "pb" in code just like in my example above.
0
 

Author Comment

by:jorgemgonzalez
ID: 24778882
Thanks a million Idle_Mind!
0
 

Author Closing Comment

by:jorgemgonzalez
ID: 31599804
Thanks again!
0
 
LVL 39

Expert Comment

by:abel
ID: 24779277
> For some reason Abel's one did not work at all after clicking button1. Is there something missing?
You just needed to add the click event and the paint event in the properties of the button and the picture box.

> Is there a way of getting the same result without the PicBox?
you can draw on almost anything using my method, but I see you already chosen Idle's, which good, because it is simpler. I just didn't even thought of it while working the solution out. Was a nice exercise regardless ;-)

-- Abel --
0

Featured Post

Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

Join & Write a Comment

I think the Typed DataTable and Typed DataSet are very good options when working with data, but I don't like auto-generated code. First, I create an Abstract Class for my DataTables Common Code.  This class Inherits from DataTable. Also, it can …
Since .Net 2.0, Visual Basic has made it easy to create a splash screen and set it via the "Splash Screen" drop down in the Project Properties.  A splash screen set in this manner is automatically created, displayed and closed by the framework itsel…
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.
This video demonstrates how to create an example email signature rule for a department in a company using CodeTwo Exchange Rules. The signature will be inserted beneath users' latest emails in conversations and will be displayed in users' Sent Items…

705 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now