Page 1 of 1

Manipulate Images In Memory Using Arraylists Rate Topic: -----

#1 ricardosms  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 73
  • View blog
  • Posts: 301
  • Joined: 02-April 10

Posted 05 December 2011 - 01:45 PM

Manipulate Images In Memory Using Arraylists

Hello!

I like Arraylists. They are wonderful. You can feed them anything and they will digest it without complaining. You can add, delete, insert elements or ranges of elements without any complain and without even needing to re-dimension them. They take objects, and the objects can be of any class, images, sounds, controls, filenames..., even you can add different kinds of objects one after the other or at least a refference to it.

Don't believe me? Just press the button "Believe" and see what happens.

Anyway the purpose of this post is to highlight a situation on another program I made:

On that program I did extract the frames from a gif animation to files in a folder and then manipulated them reading and writting to disk. That was wasteful and slow. So I modified my program to do everything in memory. What do I use? Three arraylists.

This is just a sample project that won't do too much, but will give you a hint of what other things can be done.

Attached Image

Here I open a gif animation and dissassemble it intro frames(bitmaps). Convert them to a readable format (jpeg) and save them in an arraylist. From there I read them to show the individual frames on a picturebox. And change frames by pushing a couple of buttons, controlled by a timer, so it gives the impression of an animation.

The bitmaps in the arraylist are objects that don't have a text or name property and they have the same dimensions, so they can't easily be reordered without creating a class to use some other property. But, by using another arraylist they can be reverted in order.

My layout has a panel set to autoscroll and a picturebox set to autosize, so the image comes at normal size, but can be scrolled.

I added a subroutine for saving one frame to disk but you have to take care of the names if you want to save more frames.

Form load will create the tooltips and arraylists needed:

Imports System.IO
Imports System.Collections
Imports System.Drawing.Imaging
Imports System.Drawing.Drawing2D

Public Class Form1
    Dim OriginalGif As Image
    Dim PicArray1, PicArray2 As ArrayList
    Dim N As Integer = 0
    Dim Forward As Boolean = True


    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        ToolTip1.SetToolTip(btnReverse, "Will Reverse Images In The Arraylist")
        ToolTip1.SetToolTip(btnBack, "Will Show Images In Reverse Sequence" & vbNewLine & "Keep It Down For Animation")
        ToolTip1.SetToolTip(btnBack, "Will Show Images In Forward Sequence" & vbNewLine & "Keep It Down For Animation")
        PicArray1 = New ArrayList
        PicArray2 = New ArrayList
    End Sub




And Menu->File->Open will open and load an animation.

    Private Sub OpenToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles OpenToolStripMenuItem.Click
        Dim f As New OpenFileDialog
        Try
            With f
                .Filter = "Gif Files|*.gif"

                If .ShowDialog = DialogResult.OK Then
                    OriginalGif = Image.FromFile(.FileName)
                    Rip()
                    pbOutput.Image = PicArray1(0)
                    btnBack.Enabled = True
                    btnForward.Enabled = True
                    btnReverse.Enabled = True

                End If

            End With

        Catch ex As Exception
            MessageBox.Show(ex.ToString)

        Finally
            If Not f Is Nothing Then
                f.Dispose()
                f = Nothing
            End If
        End Try
    End Sub



Enable the controls and call the "Rip" function to dissassemble the animation and extract the frames:

    Public Sub Rip()

        PicArray1.Clear()

        ' Dim Picture As Image
        Dim OrigDim As New FrameDimension(OriginalGif.FrameDimensionsList(0))
        Dim FrameCount As Integer = OriginalGif.GetFrameCount(OrigDim)
        ' Dim MemStr As Bitmap
        For i As Integer = 0 To FrameCount - 1
            OriginalGif.SelectActiveFrame(OrigDim, i)
            Using Frames As New Bitmap(OriginalGif)
                PicArray1.Add(ConvertToRGB(Frames.Clone)) ' To avoid external code error in gdi
            End Using

        Next

    End Sub



The "Rip" function will call the function "ConvertToRGB" that will change the format of the frames to "RGB", so they can be manipulated without getting "External error code in GDI":

    Public Shared Function ConvertToRGB(ByVal original As Bitmap) As Bitmap
        Dim newImage As New Bitmap(original.Width, original.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb)
        newImage.SetResolution(original.HorizontalResolution, original.VerticalResolution)
        Dim g As Graphics = Graphics.FromImage(newImage)
        g.DrawImageUnscaled(original, 0, 0)
        g.Dispose()
        Return newImage
    End Function




Now we have the bitmaps in an arraylist. What can we do with them? That is up to you.

I am only viewing them in this program and saving one individual frame. But you can do so many other things as your imagination may allow.

For viewing, the first frame is shown on the picturebox, by clicking the chevrons you could advance or reverse on the frames. If you press down and keep it down then you will see a pseudo animation, in forward or reverse, controlled by the timer:

    Private Sub btnForward_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnForward.Click
        'View Jpg Files in Directory
        If PicArray1.Count = 1 Then Exit Sub
        N += 1
        If N > PicArray1.Count - 1 Then
            N = 0
        End If
        If PicArray1(N) IsNot Nothing Then
            pbOutput.Image = PicArray1(N)
        End If
    End Sub


    Private Sub btnBack_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnBack.Click
        'View Jpg Files in Directory
        If PicArray1.Count = 1 Then Exit Sub

        N = N - 1
        If N < 0 Then
            N = PicArray1.Count - 1

        End If
        If PicArray1(N) IsNot Nothing Then
            pbOutput.Image = PicArray1(N)
        End If

    End Sub


    Private Sub btnForward_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles btnForward.MouseDown, btnBack.MouseDown
        If sender Is btnForward Then Forward = True
        If sender Is btnBack Then Forward = False
        Timer1.Enabled = True
    End Sub

    Private Sub btnForward_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles btnForward.MouseUp, btnBack.MouseUp
        Timer1.Enabled = False
    End Sub


    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        If Forward = True Then btnForward.PerformClick()
        If Forward = False Then btnBack.PerformClick()
    End Sub




And for saving:
    Private Sub SaveToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SaveToolStripMenuItem.Click

        Dim Str As String = "MyFile.jpg"
        If Not System.IO.File.Exists(Str) Then
            Try
                pbOutput.Image.Save(Str, System.Drawing.Imaging.ImageFormat.Jpeg)
                'PictureBox1.Image.Save(str, System.Drawing.Imaging.ImageFormat.Png)
            Catch Ex As Exception
                MessageBox.Show("Could Not Write To Location " & Ex.ToString)
            End Try

        End If

    End Sub



It will create a file in your program directory.

I also added a subroutine to revert the order of the frames. So when yo press the chevron to advance, the animation will reverse, and so will the other button. Here you see how I reversed the frames:

    Private Sub btnReverse_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnReverse.Click
        PicArray2.Clear()
        For i As Integer = PicArray1.Count - 1 To 0 Step -1
            PicArray2.Add(PicArray1(i))
        Next
        PicArray1.Clear()
        For Each obj As Object In PicArray2
            PicArray1.Add(obj)
        Next
        pbOutput.Image = PicArray1(0)
        pbOutput.Refresh()
    End Sub



That is it. Please check the attached project sample.

The code for the believe button is in the project.

Thank you.

Attached File(s)



Is This A Good Question/Topic? 2
  • +

Replies To: Manipulate Images In Memory Using Arraylists

#2 TechKid  Icon User is offline

  • D.I.C Head
  • member icon

Reputation: 3
  • View blog
  • Posts: 82
  • Joined: 04-September 10

Posted 25 November 2012 - 09:26 AM

You make awesome stuff, keep it up! :)
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1