821 views
in Platform Packages by

1. Can I call another method from a slot method?

2. I know how to manipulate the pixels in a native C code, but, not sure how to do it in the  Prototyper in Chora. I want to modify the pixels in a Bitmap I get from and ExternalBitmap that reads the image from a .bmp file. I'm thinking of writing a method something like this below, but I'm not sure of the proper Chora Syntax.

 

   Bitmap* EwLoadExternBitmap( XString aName ):

   FrameSize  = EwGetBitmapFrameSize ( Bitmap);

    pure Width = FrameSize.x;
    pure Height = FrameSize.y;

    XRect         lockArea;
    XBitmapLock*  lock;

    lockArea.Point1.X = 0;
    lockArea.Point1.Y = 0;
    lockArea.Point2.X = Wdith;
    lockArea.Point2.Y = Height;
    lock = EwLockBitmap( bitmap, 0, lockArea, 0, 1 );
    unsigned short* dest   = (unsigned short*)lock->Pixel1;

    for ( y = 0; y < height; y++, dest += ofs )

       for ( x = 0; x < width; x++, dest++ )

    {

        ... Some Code that reads the pixels and makes modifications.

     }

      EwUnlockBitmap( lock );
      

     this.Image.Bitmap = Bitmap;  ???? I want to point the modified Bitmap to the Image View.
 


Thanks,

1 Answer

0 votes
by

Hello,

1. Can I call another method from a slot method?

Slot methods are like regular methods. You can invoke other methods from slot methods. There are no limitations.

2. I know how to manipulate the pixels in a native C code, but, not sure how to do it in the  Prototyper in Chora. I want to modify the pixels in a Bitmap I get from and ExternalBitmap that reads the image from a .bmp file. I'm thinking of writing a method something like this below, but I'm not sure of the proper Chora Syntax.

Accessing pixel memory in Chora is not possible. Concrete, Chora has no pointers you can evaluate in order to access its memory. The operation has to be implemented in native code. If you want this code to be executed at the Prototyping time, you have to enclose the code within an Intrinsic Module for this purpose. See also:

Integrating with the device

Implementing Prototyper intrinsics

Extern Bitmap and Prototyping

Does it help you further?

Best regards

Paul Banach

by

Hi Paul,

I was able to pass a Bitmap pointer to Chora by:

 ExternalBitmap had this Load{} Slot method :

$if !$prototyper && ( $platform != *.WebGL.* )
  var string name   = pure Name;
  var handle handle = null;

  native ( name, handle )
  {
    extern XBitmap* EwLoadExternBitmap( XString aName );
    handle = (XHandle)EwLoadExternBitmap( name );
  }

  bitmap = handle;
$endif

 

In Inline native code, it was possible to create an empty bitmap frame, put data in it's pixels and pass it to Chora:




#include "ewrte.h"
#include "ewgfxdriver.h"
#include "ewextgfx.h"
#include "ewgfxdefs.h"

#include "ewextpxl_RGB565.h"
#include <string.h> 
#include "ew_bsp_spi2_ar.h"
#include "ew_bsp_i2c_ar.h"
#include "ew_arducam_main_ar.h"
#include "ew_bsp_uart1_ar.h"



XBitmap* EwLoadExternBitmap( XString aName )
{
  char          name[32];
  int           width;
  int           height;
  
  XUInt8  
  clr_red, clr_green, clr_blue, clr_alpha;
  XBitmap*      bitmap;
  XPoint        frameSize;
  XRect         lockArea;
  XBitmapLock*  lock;
  //unsigned int* dest;
  XUInt16*        dest;
  int           ofs;
  int           x, y;

  /* STEP 1 */
  
  /* Convert the 16-bit wide character string in 8-bit ANSI string */

  EwStringToAnsi( aName, name, sizeof( name ), 0 );

  /* STEP 1 and 2 */


  if (!strcmp( name, "EXT_SAME 320x240" )) 
  {
    width      = 320;
    height     = 240;
    clr_red    = 0;
    clr_green  = 255;
    clr_blue   = 0;
    clr_alpha  = 128;
    }

  else if (!strcmp( name, "EXT_BMP 320x240" ))
  {
    width      = 320;
    height     = 240;
    clr_red    = 0;
    clr_green  = 255;
    clr_blue   = 0;
    clr_alpha  = 128;
  }
  /* The requested image is not available */  
  else
    return NULL;

  /* STEP 3 */

  /* Create a new bitmap with the previously determined size */
  frameSize.X = width;
  frameSize.Y = height;
  
  bitmap = EwCreateBitmap( EW_PIXEL_FORMAT_RGB565, frameSize, 0, 1 );
  
  
  /* Enough memory to create the bitmap? */
  if ( bitmap == NULL )
    return NULL;
  
  /* STEP 4 */
  
  /* Lock the entire bitmap for write operation */
  lockArea.Point1.X = 0;
  lockArea.Point1.Y = 0;
  lockArea.Point2.X = width;
  lockArea.Point2.Y = height;
  lock              = EwLockBitmap( bitmap, 0, lockArea, 0, 1 );
  
  /* STEP 5 */
  
     
     dest   = (XUInt16*)lock->Pixel1;
     ofs    = ( lock->Pitch1Y / 2 ) - width;  // For RGB565

   if (!strcmp( name, "EXT_BMP 320x240" ))
  {
           ArduCam_Get_Bitmap(dest, ofs);

  } else if (!strcmp( name, "EXT_SAME 320x240" )) 
    {

         ArduCam_Get_Bitmap(dest, ofs);
  } 

 
  /* STEP 6 */

  /* Don't forget to unlock the bitmap when you are done! */
  EwUnlockBitmap( lock );
  
  /* STEP 8 */
  
  /* Return the bitmap */
  return bitmap;
}

 

Since you mentioned there is no pointer in Chora for bitmap manipulation, Is there something that sends a pre-loaded Bitmap frame from Chora to Native code, just like there was a way to pass a Bitmap frame to Chora as shown in the above code snippet?

Thanks,

mmd

 

by

Hello mmd,

Is there something that sends a pre-loaded Bitmap frame from Chora to Native code, just like there was a way to pass a Bitmap frame to Chora as shown in the above code snippet?

You want a bitmap existing in Chora to be passed to native code and modify it there, right? Generally, bitmap existing within Embedded Wizard are not intended to be modified by external code. Usually this is done in the opposite direction. You create a bitmap in the native code and return it to Chora so it can be used there.

Can you explain your application case?

Best regards

Paul Banach

by
Hi Paul,

My application case is:

1. Read a bitmap image from External sensor and diplay in EW (Done)

2. Images read in from Native code need to be store in SD card as .bmp

3. Stored images from SD card need to be read back in to EW

4. Imaged in EW need to be passed on to Native code for processing.

5. Read back processed images back into EW. (This is similar to item 1. Done)

Thanks

mmd
by

Hello mmd,

I'm still not quite sure what you intend to do. Are you developing a camera application with a function to store and playback the video/images on an SD card? If yes, I would handle all the camera and SD card operations in C code, outside of Embedded Wizard. Only the images you want to present to the user would be passed to Embedded Wizard by using e.g. the extern bitmap interface.

2. Images read in from Native code need to be store in SD card as .bmp

This could be handled directly in the Native code. Just in the moment when the image is processed you could also store it in a BMP file.

3. Stored images from SD card need to be read back in to EW

This could be implemented using the Extern Bitmap Interface you already explored.

4. Imaged in EW need to be passed on to Native code for processing.

This is problematic although not impossible. Finally it depends on what you mean with 'processing'. Generally, to solve this task more detailed understanding of how bitmaps are managed in Embedded Wizard is needed. I will try to explain it:

1. Within Embedded Wizard, bitmaps are represented by objects of a Resources::Bitmap class. Such object encapsulates the bitmap. It is, however, not the bitmap itself.

2. The real bitmap is managed by the Graphics Engine. This is a native code library existing in the target system. Within the Graphics Engine, bitmaps are represented by XBitmap structures. You learned this already when adapting the EwLoadExternBitmap() function.

3. The Resources::Bitmap object refers an XBitmap structure existing within the Graphics Engine. This connection is established by the internal variable bitmap of Resources::Bitmap class.

Following Chora code snippet shows how you access the internal variable bitmap and then invoke an external C function and pass the bitmap to it for processing:

var Resources::Bitmap choraBitmapObject = ...
var handle            theRealBitmap     = choraBitmapObject.bitmap;

native ( theRealBitmap )
{
  extern void ProcessBitmap( XBitmap* aBitmap );

  ProcessBitmap((XBitmap*)theRealBitmap );
}

Now, you implement a C module with a C function ProcessBitmap(). There you lock the bitmap and so access its pixel, similarly to how you created the bitmap in EwLoadExternBitmap():

void ProcessBitmap( XBitmap* aBitmap )
{
  XRect           lockArea;
  XBitmapLock*    lock;
  int             width;
  int             height;
  unsigned short* dest;
  int             ofs;
  int             x, y;

  width  = aBitmap->FrameSize.X;
  height = aBitmap->FrameSize.Y;
  
  /* Lock the entire bitmap for write/read operation */
  lockArea.Point1.X = 0;
  lockArea.Point1.Y = 0;
  lockArea.Point2.X = width;
  lockArea.Point2.Y = height;
  lock              = EwLockBitmap( bitmap, 0, lockArea, 1, 1 );
  
  dest   = (unsigned short*)lock->Pixel1;
  ofs    = ( lock->Pitch1Y / 2 ) - width;

  /* Iterate through the pixel within the locked area. Do this
     row-by-row and column-by-column. */
  for ( y = 0; y < height; y++, dest += ofs )
    for ( x = 0; x < width; x++, dest++ )
  {
    ... use 'dest' to read/write pixel data
  }

  /* Don't forget to unlock the bitmap when you are done! */
  EwUnlockBitmap( lock );
}

When processing bitmaps, be careful:

A. If the bitmap is a resource (e.g. some icon used in the GUI) you should not modify the bitmap. Don't write to such bitmap. Resources are managed in a bitmap cache. Your modification may have an impact on the GUI or it may be lost when the bitmap is discarded from the cache.

B. The reading bitmaps may not work for some target systems. For example, OpenGL manages the bitmaps in its internal texture memory. Once the bitmap is stored there, it is not possible to access its pixel data and read it retrospectively. You can only write to the bitmap. In such case, you have to manage the bitmap by yourself within 'your' memory.

5. Read back processed images back into EW. (This is similar to item 1. Done)

This could be implemented using the Extern Bitmap Interface you already explored.

Does it help you further?

Best regards

Paul Banach

by

 Hi Paul,

Thanks for your detailed insight.

>  I'm still not quite sure what you intend to do. Are you developing a camera application with a function to store and playback the video/images on an SD card? 

Answer:  I want to store multiple bitmap images from a camera sensor on an SD card. The user looks at each Image on the SD card and and chooses an image processing method on the selected image. To modify an existing image, we send the Image bitmap to the Native code for it to process and store the modified image on the SD card. 


I will follow your recommendation of putting the SD card and FATFS driver in the Native code. But I wanted to pass to the native code which Image in Resource Bitmap to do the image processing on. Hence, it brings me to your response to the question of Item 4. "Images in EW need to be passed on to Native code for processing ."

Here is how I understand your responset:

1. put a bitmap resource in EW

In my case:

2. Created a Slot Method to pass the Bitmap Resource to Native Code:

#include "ewrte.h"
#include "ewgfxdriver.h"
#include "ewextgfx.h"
#include "ewgfxdefs.h"
//#include "ewextpxl_RGBA8888.h"
#include "ewextpxl_RGB565.h"

void ProcessBitmap( XBitmap* aBitmap )
{
  XRect           lockArea;
  XBitmapLock*    lock;
  int             width;
  int             height;
  unsigned short* dest;
  int             ofs;
  int             x, y;

  width  = aBitmap->FrameSize.X;
  height = aBitmap->FrameSize.Y;
  
  /* Lock the entire bitmap for write/read operation */
  lockArea.Point1.X = 0;
  lockArea.Point1.Y = 0;
  lockArea.Point2.X = width;
  lockArea.Point2.Y = height;
  lock              = EwLockBitmap( bitmap, 0, lockArea, 1, 1 );
  
  dest   = (unsigned short*)lock->Pixel1;
  ofs    = ( lock->Pitch1Y / 2 ) - width;

  /* Iterate through the pixel within the locked area. Do this
     row-by-row and column-by-column. */
  for ( y = 0; y < height; y++, dest += ofs )
    for ( x = 0; x < width; x++, dest++ )
  {
    *dest = x; ... use 'dest' to read/write pixel data
  }

  /* Don't forget to unlock the bitmap when you are done! */
  EwUnlockBitmap( lock );
}

3. When the Native code processes the resource image, EW should display the processed image. If it is not good idea to process the Image Resource I could copy it in memory and put it in a blank bitmap pointer passed by ExternalBitmapLoad() method.

In the slot method I put the code snippet as shown below. Is this the correct way of passing a bitmap resource to choraBitmapObject?

var Resources::Bitmap choraBitmapObject = Application::IMG_19;

 

Thanks,

mmd

 

 

 

by

Hello mmd,

yes, with the following code you get access to the bitmap resource named Application::IMG_19:

var Resources::Bitmap choraBitmapObject = Application::IMG_19;

Then you can evaluate its bitmap variable to get the 'real' bitmap and pass this 'real' bitmap as XBitmap pointer to some native code. This has been explained in the preceding answer above. When using this approach, please avoid the modification of the bitmap. Since it is a resource, it is considered as containing constant, immutable data.

Answer:  I want to store multiple bitmap images from a camera sensor on an SD card. The user looks at each Image on the SD card and and chooses an image processing method on the selected image. To modify an existing image, we send the Image bitmap to the Native code for it to process and store the modified image on the SD card. 

I would avoid the step with sending the bitmap (from GUI?) to Native code. Instead:

1. The entire image processing should be implemented in C code (native). This includes the access to the camera sensor, SD card operations, processing of bitmaps, etc.

2. To present the user the available images you use the extern bitmap interface (EwLoadExternBitmap).

3. The user can select a bitmap for further processing. In such case, you don't pass the selected bitmap back to Native code. Instead, pass the name of the bitmap file or its number, etc. to identify the bitmap.

4. The bitmap processing code uses the name (or the number of the bitmap, etc.) and loads this bitmap from the SD card, processes it, stores the results again on the SD card, etc.

5. Once the processing is done, you can again load the new content of the bitmap and present it in the GUI. Here the extern bitmap interface is used again.

With this approach you can eliminate the step of sending the bitmap to Native code.

Does it help you further?

Best regards

Paul Banach

by

Hi Paul,

Thank you for the clarification. I was able to pass the bitmap resource to the native code and modify it. I do see the modified display on the STM32F746G platform screen, where I pass a bitmap resource and just put random data for test in it and the display looked random on the hardware device screen.

#include <stdio.h>
#include <stdlib.h>
#include "ewrte.h"
#include "ewgfxdriver.h"
#include "ewextgfx.h"
#include "ewgfxdefs.h"
#include "ewextpxl_RGB565.h"

void ProcessBitmap( XBitmap* aBitmap )
{
  XRect           lockArea;
  XBitmapLock*    lock;
  int             width;
  int             height;
  unsigned short* dest;
  int             ofs;
  int             x, y;

  width  = 2* aBitmap->FrameSize.X;
  height = aBitmap->FrameSize.Y;
  
  /* Lock the entire bitmap for write/read operation */
  lockArea.Point1.X = 0;
  lockArea.Point1.Y = 0;
  lockArea.Point2.X = width;
  lockArea.Point2.Y = height;
  lock              = EwLockBitmap( aBitmap, 0, lockArea, 1, 1 );
  
  dest   = (unsigned short*)lock->Pixel1;
  ofs    = ( lock->Pitch1Y / 2 ) - width;

  /* Iterate through the pixel within the locked area. Do this
     row-by-row and column-by-column. */
  for ( y = 0 ; y < height; y++, dest += ofs )
    for ( x = 0; x < width; x++, dest++ )
  {
    *dest = rand() % 0xffff; // use 'dest' to read/write pixel data
  }

  /* Don't forget to unlock the bitmap when you are done! */
  EwUnlockBitmap( lock );
}

I had to mess around with the width "width  = 2* aBitmap->FrameSize.X;" in the code to get access to the full image, but this could be bitmap image related.

As you mentioned, it is something you don't recommend since the bitmap resource contains constant immutable data.

I have started the code to have the native c code do the bitmap SD read write and modification on the STM32F746G platform and controlling the image selections by passing the file names through ExternalBitmap.name property. Will let you know how it goes after I put all the hooks in the code.

Thanks, your answers were helpful.

mmd

by

Hello mmd,

thank you for the information. Concerning width = 2* aBitmap->FrameSize.X, this is surely  because the bitmap is in RGB565 format. Please note the data field Pitch1X (and Pitch1Y) in the XBitmapLock data structure. Pitch1X corresponds to the number of bytes used for a single pixel. In case of RGB565, 2 bytes (16 bit) are used for a single pixel. See also Bitmap color format EW_PIXEL_FORMAT_RGB565 (optional).

Best regards

Paul Banach

by

 

Hi Paul, bitmap resource passed from EW to native code looks like RGB888. I had to look at the pixel RGB data  stored in a 32 bit integer using 24 bits of it in the native C code.

See code below where I modified the bitmap to gray scale (actually the gray scale was not done to the proper formula where it should have been using: grayValue = (BYTE)(0.299*redValue + 0.587*greenValue + 0.114*blueValue)). I just changed the "dest" pointer to : unsigned int* dest; and took the width = 2* aBitmap->FrameSize.X back to its original width = aBitmap->FrameSize.X

Also I had to modify the for loop. Did not use the "ofs" 

//for ( y = 0 ; y < height; y++, dest += ofs )
  for ( y = 0 ; y < height; y++, dest++ )
    for ( x = 0; x < width; x++, dest++ )
  { ..

This way I could see the modified image in its entirety

Here is the "Inline" code below:

 

#include <stdio.h>
#include <stdlib.h>
#include "ewrte.h"
#include "ewgfxdriver.h"
#include "ewextgfx.h"
#include "ewgfxdefs.h"
#include "ewextpxl_RGB565.h"

void ProcessBitmap( XBitmap* aBitmap )
{
  XRect           lockArea;
  XBitmapLock*    lock;
  int             width;
  int             height;
  //unsigned short* dest;
  unsigned int* dest;
  unsigned short red, green, blue;
  unsigned int sum_color;
  int             ofs;
  int             x, y;

  width  = aBitmap->FrameSize.X;
  height = aBitmap->FrameSize.Y;
  
  /* Lock the entire bitmap for write/read operation */
  lockArea.Point1.X = 0;
  lockArea.Point1.Y = 0;
  lockArea.Point2.X = width;
  lockArea.Point2.Y = height;
  lock              = EwLockBitmap( aBitmap, 0, lockArea, 1, 1 );
  
  dest   = (unsigned short*)lock->Pixel1;
  ofs    = ( lock->Pitch1Y / 2 ) - width;

  /* Iterate through the pixel within the locked area. Do this
     row-by-row and column-by-column. */
  //for ( y = 0 ; y < height; y++, dest += ofs )
  for ( y = 0 ; y < height; y++, dest++ )
    for ( x = 0; x < width; x++, dest++ )
  {
 
    red =   (*dest & 0xff0000) >> 16;
    green = (*dest & 0x00ff00) >> 8;
    blue =  (*dest & 0x0000ff)  ;

    sum_color = red + green + blue;
    sum_color = sum_color/3;  

   // Actually this values should be calculated as
   // grayValue = (BYTE)(0.299*redValue + 0.587*greenValue + 0.114*blueValue);

    if (sum_color >   0xff)
        sum_color = 0xff;  //cieling sqrt(pow(Gx,2.0)
        
     
        *dest =  (sum_color << 16 ) | (sum_color << 8)  | sum_color;
        
  }

  /* Don't forget to unlock the bitmap when you are done! */
  EwUnlockBitmap( lock );
}

 

The Platform STM32F746 is set for RGB565.

by

Hello mmd,

Embedded Wizard supports and uses several bitmap formats. This is controlled by the Format attribute of the affected bitmap resource. If you want the bitmap to be stored in RGB565 format, change its attribute accordingly. I suppose, the bitmap is configured with the format Native. It represents the RGBA8888 format even on the STM32.RGB565 target system. This is essential to support transparency within the bitmap. RGB565 does not contain any alpha channel.

Best regards

Paul Banach

by

Hi Paul,

Thanks for the clarification. I will change the Bitmap Resource Format from Native to RGB565.

Thanks!

mmd

Ask Embedded Wizard

Welcome to the question and answer site for Embedded Wizard users and UI developers.

Ask your question and receive answers from the Embedded Wizard support team or from other members of the community!

Embedded Wizard Website | Privacy Policy | Imprint

...