B4J Library [B4X] [XUI] xResizeAndCrop

klaus

Expert
Licensed User
The xResizeAndCrop Class does now also exist as a B4X libary.
It works on all three platforms: B4A, B4i and B4J.
The xResizeAndCrop.b4xlib and the xResizeAndCrop.xml files are attached.
You need to copy the xResizeAndCrop.b4xlib file to the AdditionlLibraries\B4X folder!
Don’t copy thexResizeAndCrop.xml file to the AdditionalLibraries folder, copy it in another folder for all b4xlib xml files.
Example: AdditionlLibraries\B4XlibXMLFiles
The xResizeAndCrop.xml file is for help purposes and is useful with the B4X Help Viewer or the B4XObjectBrowser.
The xResizeAndCrop.xml was generated with this tool: b4xlib - XML generation

This is a cross-platform CustomView.
It allows to resize and crop images.
It works on all three platforms: B4A, B4i and B4J.

It is an evolution of the B4A project: Resize and crop image.
To make a B4X CustomView was inspired by this thread: [B4X] [XUI] CropView.

Demoprogramms for all three platforms.
Tested on PC, Android Samsung S6, iPhone 6.

EDIT: 2020.07.15 Version 1.4
Amended error with CroppedImage without a CroppedView.

EDIT: 2020.06.25 Version 1.3
Updated the Tag property according to Erels recommendation:
https://www.b4x.com/android/forum/t...lv-or-any-other-container.117992/#post-738358

EDIT: 2019.03.12 Version 1.2
Added WidthHeightRatio and WidthHeightRatioValue properties
defining fixed or custom Width / Height ratios for the cropped image
Added RotateImage method, original image rotation.

EDIT: 2019.01.30 Version 1.1
Added a Square property.
When Square = True then the resized image is always square.

upload_2018-12-5_19-49-13.gif


xResizeAndCrop

Author:
Klaus CHRISTL (klaus)
Version: 1.3
  • xResizeAndCrop
    • Events:
      • CropFinished
    • Functions:
      • Initialize (Callback As Object, EventName As String) As String
      • IsInitialized As Boolean
        Tests whether the object has been initialized.
      • LoadImage (Dir As String, FileName As String) As String
        loads the given image file to the xResizeAndCrop Customview
      • RotateImage(Degrees As Int)
    • Properties:
      • CroppedImage As B4XBitmap [read only]
        gets the cropped image as a B4XBitmap, read only
      • CroppedView
        sets the Panel / Pane view for the cropped image, write only
        the Panel / Pane view must be added in the main code and transmitted to the custom view as this property.
      • HandleColor As Int
        sets or gets the HandleColor property
        value must a xui color
        Example code: <code>xResizeAndCrop1.HandleColor = xui.Color_RGB(255, 215, 0)</code>
      • Height As Int
        sets or gets the Height property
      • Image As B4XBitmap
        sets the image (B4XBitmap) to the Customview, write only
      • Left As Int
        sets or gets the Left property
      • MinCroppedHeight As Int
        sets or gets the MinHeight property
        value in pixels, no dip value
        if Square = True, the min cropped width is set equal to this height value
      • MinCroppedWidth As Int
        sets or gets the MinWidth property
        value in pixels, no dip value
        if Square = True, the min cropped height is set equal to this width value
      • Top As Int
        sets or gets the Top property
      • Visible As Boolean
        sets or gets the Visible property
      • Width As Int
        sets or gets the Width property
      • WidthHeightRatio As String
        sets or gets the WidthHeightRatio property
        possible values: None Square 1.5 4/3 16/9 Custom
        None = any width and height
        Square = True means that the resized image is always square
        3/2 = ratio 1.5
        2/3 = ratio 0.6667
        4/3 = ratio 4/3
        3/4 = ratio 3/4
        16/9 = ratio 16/9
        9/16 = ratio 9/16
        Custom = user defined ratio set in the WidthHeightRatioValue property
      • WidthHeightRatio As Double
        sets or gets the WidthHeightRatioValue property
        only active if the WidthHeightRatio property is set to "Custom"
 

Attachments

Last edited:

klaus

Expert
Licensed User
The xResizeAndCrop class and B4X Library have been updated to version 1.1.
Added a Square property.
When Square = True then the resized image is always square.
Files updated in the first post.
 

viriato

Member
Licensed User
Hi,
Great example ..
But for a better alignment I would like to rotate the picture or the square.
Any idea how to do that ?
Thank you
 

klaus

Expert
Licensed User
But for a better alignment I would like to rotate the picture or the square.
Sorry, but I don't understand what exactly you want to do.
What do you want to rotate?
The reference image or the croped image?
What do you mean with: But for a better alignment... ?
 

viriato

Member
Licensed User
For example if you take a picture of a business card most of the time the picture is not squared
so the fact to rotate the picture help to have a squared cropped image

May be obtain the same result rotating the square will be also a solution.

merci
 

klaus

Expert
Licensed User
You can turn the device to better fit a rectangular image.
The program calculates the display of the origin image to occupy the max possible space.
If you have an image in portrait hold the device in portrait, if you have an image in landscape hold the device in landscape.
I suspect a problem with rotating the image that the cropped image needs a again a rotation.

upload_2019-1-31_19-15-18.png

upload_2019-1-31_19-15-58.png
 

viriato

Member
Licensed User
I have seen this possibility in some APP and it is really practical and convenient

Thanks
 

viriato

Member
Licensed User
HI,
I have another question, the pictures captured have a size of 3 M (Fidelity cards like Avis ; Hertz ..)
I would like to save the cropped picture with a minimum size (max 200 k)
How can i modify your program to do that ?

Thank you
 

klaus

Expert
Licensed User
Two solutions:
1: Play with the quality parameter WriteToStream(Out, 100, "JPEG":
B4X:
Private Sub btnSaveCroppedImage_Click
    Private Dir, FileName As String
   
    xui.SetDataFolder("xResizeAndCropDemo")
    Dir = xui.DefaultFolder
    Log(Dir)
    FileName = "image.jpg"
    Private Out As OutputStream
    Out = File.OpenOutput(Dir, FileName, False)
    xResizeAndCrop1.CroppedImage.WriteToStream(Out, 100, "JPEG")
    Out.Close
End Sub
2: Save the croped image in a temporary file and reload it resized and delete the temporary file.
Resize with: LoadBitmapResize(Dir, "temp.jpg", 100, 100, True).
B4X:
Private Sub btnSaveCroppedImage_Click
    Private Dir, FileName As String
   
    xui.SetDataFolder("xResizeAndCropDemo")
    Dir = xui.DefaultFolder
    Log(Dir)
    FileName = "image.jpg"
    Private Out As OutputStream
   
    Out = File.OpenOutput(Dir, "temp.jpg", False)
    xResizeAndCrop1.CroppedImage.WriteToStream(Out, 100, "JPEG")
    Out.Close
    Private bmpTemp As B4XBitmap
    bmpTemp = xui.LoadBitmapResize(Dir, "temp.jpg", 100, 100, True)
    Private Out As OutputStream
    Out = File.OpenOutput(Dir, FileName, False)
    bmpTemp.WriteToStream(Out, 100, "JPEG")
    Out.Close
    File.Delete(Dir, "temp.jpg")
End Sub
 

klaus

Expert
Licensed User
The xResizeAndCrop CustomView and b4xlib have been updated to version 1.2.

Added WidthHeightRatio and WidthHeightRatioValue properties
defining fixed or custom Width / Height ratios for the cropped image
Added RotateImage method, original image rotation.
 

ilan

Expert
Licensed User
hi klaus, thank you very much for this class.

i am trying to implement it in my app but for some reason i am getting an error that the resizecrop view is not initialized. i add the view in designer so i dont understand why i should initialized it. i tried to use the b4xlib and then the class but i get the same error.

Application_Start
Application_Active
Error occurred on line: 652 (xResizeAndCrop)
Object was not initialized (UIView)
Stack Trace: (
CoreFoundation AF42303F-57B6-3C11-8F18-8E80ABF7D886 + 1254164
libobjc.A.dylib objc_exception_throw + 60
CoreFoundation AF42303F-57B6-3C11-8F18-8E80ABF7D886 + 138856
The Resizer -[B4IObjectWrapper object] + 136
The Resizer -[b4i_xresizeandcrop _setcroppedview::] + 700
The Resizer -[ResumableSub_photopage_icam_Complete resume::] + 1544
CoreFoundation AF42303F-57B6-3C11-8F18-8E80ABF7D886 + 1281812
CoreFoundation AF42303F-57B6-3C11-8F18-8E80ABF7D886 + 8344
The Resizer +[B4I runDynamicMethod:method:throwErrorIfMissing:args:] + 1608
The Resizer -[B4IShell runMethod:] + 448
The Resizer -[B4IShell raiseEventImpl:method:args::] + 1648
The Resizer -[B4IShellBI raiseEvent:event:params:] + 1580
The Resizer -[B4IDelegatableResumableSub resume::] + 380
The Resizer __21-[B4ICommon Sleep:::]_block_invoke + 60
libdispatch.dylib CAFEEE86-4C94-3AC9-8853-BFE11F70C0F4 + 13116
libdispatch.dylib CAFEEE86-4C94-3AC9-8853-BFE11F70C0F4 + 23288
libdispatch.dylib CAFEEE86-4C94-3AC9-8853-BFE11F70C0F4 + 91684
libdispatch.dylib _dispatch_main_queue_callback_4CF + 560
CoreFoundation AF42303F-57B6-3C11-8F18-8E80ABF7D886 + 710320
CoreFoundation AF42303F-57B6-3C11-8F18-8E80ABF7D886 + 688840
CoreFoundation CFRunLoopRunSpecific + 480
GraphicsServices GSEventRunModal + 164
UIKitCore UIApplicationMain + 1944
The Resizer main + 128
libdyld.dylib E5E56A85-E4D6-332E-9F32-FED4B986AFE0 + 4828
)
i make sure that the layout is loaded before the code is executed.
when i use the class the debugger is pointing to this event

B4X:
Public Sub setCroppedView(CroppedView As B4XView)
    xpnlCropped = CroppedView
    xcvsCropped.Initialize(xpnlCropped)
    imvCroppedWidth = xpnlCropped.Width
    imvCroppedHeight = xpnlCropped.Height
    rectCroppedView.Initialize(0, 0, imvCroppedWidth, imvCroppedHeight)
    
    ExtractCroppedImage
End Sub
to the line: xcvsCropped.Initialize(xpnlCropped)

can you please tell me what i am doing wrong?

thank you
 

klaus

Expert
Licensed User
Sorry, but without having the whole code it's impossible to give a concrete advice.
Can't you post your project or better a smaller one that shows the problem?
So I could test it in the same conditions as you do.
 

ilan

Expert
Licensed User
Sorry, but without having the whole code it's impossible to give a concrete advice.
Can't you post your project or better a smaller one that shows the problem?
So I could test it in the same conditions as you do.
thank you for your answer klaus. i cannot post the whole code and if i try your example it does work but implementing it in my project does not work.
i dont do anything special just add the class, add the customview, load an image and set the CroppedView property the same as in your example.
the only difference is that i am using multiple pages in my project and this is loaded in page 2 but i dont think it has anything to do with it.
 

ilan

Expert
Licensed User
How do you expect me to help you without seeing any code nor knowing what exactly you have done.
i agree with you but not always it is possible to share the code or create a small example where i can reproduce it. anyway i found i mistake. i had to add an imageview to the designer that shows the cropped image (pnlCroppedImage).
so now it works fine, thank you :)

the only problem that i have now is that the overlay copping feature runs very slow, i guess it has something to do with the loaded size of the image so i will try to resize first the image and then load it to the customview.
 

klaus

Expert
Licensed User

Alexander Stolte

Expert
Licensed User
To get the cropped image i need a cropped panel, but why?
B4X:
xResizeAndCrop1.CroppedImage
I only want the cropped image, without adding a invisible panel to get a cropped image from it.
 
Top