Resize pictures

This forum is meant for examples of X# code.

User avatar
Horst
Posts: 327
Joined: Tue Oct 13, 2015 3:27 pm

Resize pictures

Post by Horst »

Hallo
I need a tool to reduce the size of a picture and i found one in C#.
Now i translated it to xSharp and it works. But i am not sure if i realy did it well or if i will run into troubles. Because C# has many things i dont understand.
Can one of you check it ? The prg includes the c# code also is in the attachement.

Thanks Horst
Attachments
ScaleAndSave.txt
(1.93 KiB) Downloaded 84 times
User avatar
SHirsch
Posts: 284
Joined: Tue Jan 30, 2018 8:23 am

Resize pictures

Post by SHirsch »

Hello Horst,

you just ignored the using statement.

BEGIN USING oImage ....
  BEGIN USING  oNewImage ....
     oNewImage:Save....
  END USING
END USING

BEGIN USING oGraphics ....
   oGraphics:Draw....
END USING

Otherwise the native resources will not be freed. So you built a classic memory leak.
You could also call oImage:Dispose at the end (and for oImage and oGrahics).

Stefan
User avatar
Horst
Posts: 327
Joined: Tue Oct 13, 2015 3:27 pm

Resize pictures

Post by Horst »

Hello Stefan
Yes, because of this Using i wasnt sure and scared. So i changed it to :

FUNCTION ScaleAndSave(cFileIn AS STRING, cFileOut AS STRING) AS VOID
    LOCAL oImage        AS Image
    LOCAL oNewImage        AS Image
    
    BEGIN USING    oImage         := Image:FromFile(cFileIn)
        BEGIN USING oNewImage     := ScaleImage(oImage, 350, 350)
            oNewImage:Save(cFileOut , ImageFormat.Jpeg)
        END USING
    END USING
                           
    RETURN NIL

FUNCTION ScaleImage(oImage AS Image, maxWidth AS FLOAT, maxHeight AS FLOAT)
    LOCAL oGraphics        AS Graphics
    LOCAL oNewImage     AS Bitmap
    LOCAL newWidth        AS INT
    LOCAL newHeight        AS INT
    LOCAL ratioX        AS FLOAT
    LOCAL ratioY        AS FLOAT
    LOCAL ratio         AS USUAL

    ratioX         := maxWidth / oImage:Width
    ratioY         := maxHeight / oImage:Height
    ratio         := Math.Min(ratioX, ratioY)
    newWidth     := Integer (oImage:Width * ratio)
    newHeight     := Integer (oImage:Height * ratio)
    oNewImage     := Bitmap{newWidth, newHeight}

    BEGIN USING oGraphics     := Graphics.FromImage(oNewImage)
        oGraphics:DrawImage(oImage, 0, 0, newWidth, newHeight)
    END USING

    RETURN oNewImage

i will use it with USING, so i have a example in my code. But i prefere the Dispose() like
Aclass := yx{parameter}
Aclass:Do()
Aclass:Dispose()
For me its more readable.

Thanks a lot
 
User avatar
Horst
Posts: 327
Joined: Tue Oct 13, 2015 3:27 pm

Resize pictures

Post by Horst »

Still a little worried  about Local
Once i learned a local variable will be removed after the return statement of a function .
So this is not allways true ?

Horst
User avatar
SHirsch
Posts: 284
Joined: Tue Jan 30, 2018 8:23 am

Resize pictures

Post by SHirsch »

What do you mean?
In ScaleAndSave you cannot access the local variable oGraphics whichs is using in ScaleImage. You can use oNewImage which is created in ScaleImage because this is your return value. The name of the variable in ScaleAndSave does not have to be oNewImage (which is the same as in ScaleImage). This could be called oScaledImage. So the reference of oNewImage in ScaleImage and oScaledImage (or in your case also oNewImage) in ScaleAndSave is the same.
Maybe this was your question?

Stefan
FFF
Posts: 1532
Joined: Fri Sep 25, 2015 4:52 pm
Location: Germany

Resize pictures

Post by FFF »

 LOCAL oImage        AS Image
 LOCAL oNewImage        AS Image
....
Return
I think he expected both locals to be destroyed after the Return by GC
Regards
Karl
(on Win8.1/64, Xide32 2.19, X#2.19.0.2.)
User avatar
Horst
Posts: 327
Joined: Tue Oct 13, 2015 3:27 pm

Resize pictures

Post by Horst »

Hi FFF
Yes thats what i expect
User avatar
SHirsch
Posts: 284
Joined: Tue Jan 30, 2018 8:23 am

Resize pictures

Post by SHirsch »

Horst,

the object is not destroyed because the reference is returned and still used in the calling method. When the calling method returns  the object will be destroyed. Objects will be destroyed if it is not referenced any more. 

Stefan
FFF
Posts: 1532
Joined: Fri Sep 25, 2015 4:52 pm
Location: Germany

Resize pictures

Post by FFF »

Stefan,
the locals ARE in the calling method, so after leaving the caller, they should be destroyed. If so, why the need for Using in ScaleAndSave()?
Regards
Karl
(on Win8.1/64, Xide32 2.19, X#2.19.0.2.)
User avatar
SHirsch
Posts: 284
Joined: Tue Jan 30, 2018 8:23 am

Resize pictures

Post by SHirsch »

Than I did not understand the question.

A managed object is removed from memory when it's not referenced anymore.
This is the case for both variables in ScaleAndSave (oImage and oNewImage).
BUT in ScaleImage the object 'oNewImage' is NOT destroyed after returning to ScaleAndSave. Otherwise it could'nt be used in ScaleAndSave.

BEGIN USING ensures that 'Dispose' is called at the end of the USING block (even if an error is thrown). You can call Dispose manually as Horst has written. But the managed object still remains in memory until it is not referenced anymore. Dispose just frees all unmanaged resources that are used internally. In ScaleAndSave the object oNewImage will be destroyed after returning to the calling method.
Post Reply