• AVR Freaks

Helpful ReplyHot!Harmony v3: A way to have a "Clean" blit?

Page: 12 > Showing page 1 of 2
Author
KTrenholm
Super Member
  • Total Posts : 787
  • Reward points : 0
  • Joined: 2012/08/08 14:04:23
  • Location: Connecticut, USA
  • Status: online
2019/12/03 12:18:22 (permalink)
0

Harmony v3: A way to have a "Clean" blit?

Hello!
 
I have a question regarding blitting an image/color to a display using Harmony in such a way where I can cleanly transition from one image/color to the next.  The problem is a little tough to describe in words so bear with me:
 
MPLAB X v5.30
XC32 v2.30
PIC32MZ DA Starter Kit (Non-Crypto, Internal DDR)
MEBII Display Kit
Aria Graphics Library
 
My graphics are configured to have Layer0 dedicated to an image or flat color, images are loaded from a bitmap and blitted out to the display using n2d_blit(), or in the case of a flat color, painted using n2d_fill().  This is done upon button press.  Layer1 is nothing but a text label widget that displays a description of the image/color currently on screen.
 
The strangeness I'm seeing is when I blit a screen (or fill a color) to a layer, I will sometimes get a visual artifact of the new image/color "sliding" in from the side (from about 1/3 of the display area, right to left) rather than cleanly painting. There's a couple funnies about the behavior:
- The leftmost 1/3 of the display seems to already show the image that is currently sliding in which is rather strange.  Like the image has already been put onto the display before the sliding occurs. [EDIT] I confirmed it's the same image, but wrapped around the displayIt looks like it's correcting itself to align the image properly from being wrapped around by at most about 1/3 of the display area.
- The behavior includes the currently visible widget on a Layer1, which also appears to move in from the side even though that layer is not being painted.
 
Does anyone know what might be causing this?  I thought it might get resolved by enabling Double Buffer Mode or by checking to make sure no layers are currently drawing (using laLayer_IsDrawing()) before executing the blit/fill but neither of those things have fixed the issue.
 
My function to write a bitmap to the display is below.  It can probably be improved, but it does work to put an image on the display:

 
static void WriteBitmapToDisplay (BITMAP_DATA * bmp_info){
    uint32_t line;
    uint32_t px;
    uint32_t fileindex = bmp_info->px_index;
    uint8_t linedata[IMAGE_WIDTH * BMP_BYTES_PER_PX];
    
    SYS_FS_FileSeek(bmp_info->fs_handle, fileindex, SYS_FS_SEEK_SET); /*Set file pointer to first pixel of image data after header*/
    
    /*Image is 24bpp, outgoing display format is 32bpp (RGBA)*/
    /*Read in each horizontal line and insert an Alpha byte for each pixel*/
    for (line = 1; line <= IMAGE_HEIGHT; line++){
        
        SYS_FS_FileRead(bmp_info->fs_handle, &linedata, IMAGE_WIDTH * BMP_BYTES_PER_PX);
        
        for (px = 0; px < IMAGE_WIDTH; px++){
            /*Image was upside-down when painted to display, so start writing pixel data at the end of the image data to flip it*/
            ptrImageData[((IMAGE_WIDTH * IMAGE_HEIGHT) - (IMAGE_WIDTH * line)) + px] =
                    JOIN_UINT32(
                    linedata[(px * BMP_BYTES_PER_PX) + 2],
                    linedata[(px * BMP_BYTES_PER_PX) + 1],
                    linedata[(px * BMP_BYTES_PER_PX)],
                    0x00);
        }
        
    }

    /*Set up image buffer for our bitmap*/
    imgbuffer.format = N2D_RGBA8888;
    imgbuffer.gpu = KVA_TO_PA(IMAGE_DATA_ADDR);
    imgbuffer.memory = (void*)IMAGE_DATA_ADDR;
    imgbuffer.height = IMAGE_HEIGHT;
    imgbuffer.width = IMAGE_WIDTH;
    imgbuffer.orientation = N2D_0;
    imgbuffer.stride = imgbuffer.width * 32 / 8;
    
    while (laContext_IsDrawing() == LA_TRUE);

    n2d_blit(&layer0buffer, N2D_NULL, &imgbuffer, N2D_NULL, N2D_BLEND_NONE);
}
 

 
 
Any suggestions for things to try would be appreciated.  I'll see if I can maybe catch the problem on video to make it a little easier to visualize.
 
 
post edited by KTrenholm - 2019/12/03 12:56:50
#1
automate
Junior Member
  • Total Posts : 109
  • Reward points : 0
  • Joined: 2014/11/10 09:58:57
  • Location: 0
  • Status: offline
Re: Harmony v3: A way to have a "Clean" blit? 2019/12/03 13:55:29 (permalink)
0
@KTrenholm
Yes, there is a way to have a clean blit.
 
For images, you can you the ImageWidget. It contains APIs to set (update) images.
 
For example: laImageWidget_SetImage().  Sets a new image asset pointer for the widget.
 
For fill color (rectangles) and image examples, you can reference the aria_benchmark application at: <Harmony3>\gfx_apps\apps\aria_benchmark
 
Note: The use of the ImageWidget is preferred. However, it appears you are using libnano2d APIs directly. Please attempt to use ImageWidget and respond if you do not overcome your issue.
 
 
 
#2
KTrenholm
Super Member
  • Total Posts : 787
  • Reward points : 0
  • Joined: 2012/08/08 14:04:23
  • Location: Connecticut, USA
  • Status: online
Re: Harmony v3: A way to have a "Clean" blit? 2019/12/03 14:51:52 (permalink)
0
automate
@KTrenholm
Yes, there is a way to have a clean blit.
 
For images, you can you the ImageWidget. It contains APIs to set (update) images.
 
For example: laImageWidget_SetImage().  Sets a new image asset pointer for the widget.
 
For fill color (rectangles) and image examples, you can reference the aria_benchmark application at: <Harmony3>\gfx_apps\apps\aria_benchmark
 
Note: The use of the ImageWidget is preferred. However, it appears you are using libnano2d APIs directly. Please attempt to use ImageWidget and respond if you do not overcome your issue.



Thanks for the tip!
 
I mostly ended up using n2d_blit because that was what was used in the aria_image_viewer example, which is what I used as a reference to try and get my own similar program going.  Maybe they should update their example projects if this isn't the preferred way to do things.  I will say though that the aria_image_viewer project does not exhibit this issue when swapping between images.
 
If I want to use the ImageWidget component, looks like I need to create a GFXU_ImageAsset, and the examples look like they're made mostly by pre-processing images loaded into the graphics composer.  Since I'm using images being read at runtime, it looks like I'll have to assemble it myself.  Might take a little bit since I've been reading and parsing the image under the assumption of using n2d_blit(), but I'll check back in once I get it sorted out.
 
 
 
 
#3
automate
Junior Member
  • Total Posts : 109
  • Reward points : 0
  • Joined: 2014/11/10 09:58:57
  • Location: 0
  • Status: offline
Re: Harmony v3: A way to have a "Clean" blit? 2019/12/03 15:11:12 (permalink) ☄ Helpfulby KTrenholm 2019/12/04 09:33:31
0
...images being read at runtime,...
 
We know that bliting with image_viewer successfully reads from DDR extremely fast, but we want to know more about runtime streaming with your application. The CPU read activity could be starving display refreshing performance.
 
Before moving on to ImageWidget, you can attempt to stage your images to DDR. That is, read 2 or more images at initialization time and write them to well-known DDR addresses similar to image_viewer.  Iterate over these images to see if previous artifacts are observed. This approach will isolate your problem to bliting or runtime reading.
 
 
#4
KTrenholm
Super Member
  • Total Posts : 787
  • Reward points : 0
  • Joined: 2012/08/08 14:04:23
  • Location: Connecticut, USA
  • Status: online
Re: Harmony v3: A way to have a "Clean" blit? 2019/12/04 07:05:05 (permalink)
0
automate
...images being read at runtime,...
 
We know that bliting with image_viewer successfully reads from DDR extremely fast, but we want to know more about runtime streaming with your application. The CPU read activity could be starving display refreshing performance.
 
Before moving on to ImageWidget, you can attempt to stage your images to DDR. That is, read 2 or more images at initialization time and write them to well-known DDR addresses similar to image_viewer.  Iterate over these images to see if previous artifacts are observed. This approach will isolate your problem to bliting or runtime reading.



I am currently staging images to DDR before writing them out to the screen (ptrImageData in the WriteBitmapToDisplay() function above is in DDR), but I am doing it (Reading bitmap, parsing the pixel data, writing to DDR) all in a single state.   I'm thinking that perhaps splitting it between two states, the first reading the bitmap and copying the pixel data to DDR, and the second part actually performing the blit to the display on the next APP_Tasks call may make things a little bit smoother:
 

case USB_STATE_OPEN_FILE:   //USB MSD Connected and list of bitmap image names has been populated
            
            if(usbData.deviceIsConnected == false)
            {
                LED1_Off();
                appData.usb_state = USB_STATE_WAIT_FOR_DEVICE_ATTACH;
                laLabelWidget_SetText((laLabelWidget *)lbl_imgName, laString_CreateFromCharBuffer("USB REMOVED", &NotoSans_Regular));
                Layer1_ResetFade();
            }
            
            if (AdvanceImage){  //true when button pressed
                
                strcpy(BitmapPath, USB_IMAGE_PATH);
                strcat(BitmapPath, BitmapFileList[BitmapIndex]);
                usbData.fileHandle = SYS_FS_FileOpen(BitmapPath, (SYS_FS_FILE_OPEN_READ));

                if(usbData.fileHandle == SYS_FS_HANDLE_INVALID)
                {
                    /* Could not open the file. Error out*/
                    appData.usb_state = USB_STATE_ERROR;
                }
                else
                {
                    /* File opened successfully.*/
                    BitmapInfo = GetBitmapData(usbData.fileHandle);
                    /*Load bitmap data into DDR*/
                    SetupBitmapData(&BitmapInfo);
                    appData.usb_state = USB_STATE_DISPLAY_FILE;
                }
                
                AdvanceImage = false;
            }
            
            break;
            
        case USB_STATE_DISPLAY_FILE:    //Bitmap data has been loaded to DDR from USB MSD, write image out to display
            /*Write bitmap data in DDR to display*/
            n2d_blit(&layer0buffer, N2D_NULL, &imgbuffer, N2D_NULL, N2D_BLEND_NONE);
            laLabelWidget_SetText((laLabelWidget *)lbl_imgName, laString_CreateFromCharBuffer(BitmapFileList[BitmapIndex], &NotoSans_Regular));
            Layer1_ResetFade();  //begin to fade in the filename widget
            
            /*Done, close the file and set state to load next one when button pressed*/
            SYS_FS_FileClose(usbData.fileHandle);
            appData.usb_state = USB_STATE_OPEN_FILE;
            break;

 
This unfortunately didn't seem to help matters at all as far as the strange wraparound/sliding behavior is concerned.
I have a couple more things to try though, like doing as you initially suggested and using the imagewidget or loading multiple images from USB to DDR.  I'll check back in once I have some results.
 
Thanks again for the tips!
#5
KTrenholm
Super Member
  • Total Posts : 787
  • Reward points : 0
  • Joined: 2012/08/08 14:04:23
  • Location: Connecticut, USA
  • Status: online
Re: Harmony v3: A way to have a "Clean" blit? 2019/12/04 09:04:00 (permalink)
0
Question regarding how the image should be placed in DDR when using GFXU_ImageAsset + Widget to display an image:
 
When using blit I was just reading the pixel data bytes (with an extra alpha byte added, RGB->RGBA).  I would assemble the data into a 32-bit word and copy it to each successive location in DDR.
 
When using GFXU_ImageAsset and the image widget, I assume I am meant to copy the entire bitmap file including the header to DDR and that parsing of the header/image data will be handled by the library.
 
The problem I'm having now is I'm getting nothing but white screens for my bitmap images.
The dataAddress member of the GFXU_AssetHeader is set to the address in DDR of my staged image data, but I'd imagine the dataLocation member should to be set to something other than GFXU_ASSET_LOCATION_ID_INTERNAL (internal flash).  
 
Is there something I need to set in Harmony to generate a GFXU_ASSET_LOCATION_ID_DDR (or something similar) macro?
 
post edited by KTrenholm - 2019/12/04 09:46:47
#6
automate
Junior Member
  • Total Posts : 109
  • Reward points : 0
  • Joined: 2014/11/10 09:58:57
  • Location: 0
  • Status: offline
Re: Harmony v3: A way to have a "Clean" blit? 2019/12/04 09:56:26 (permalink)
0
Referencing image_viewer app is ideal when working with images residing in flash. These are essentially preprocessed images. For applications using external media we recommend referencing our external resource demonstrations.
 
New in MPLAB Harmony Graphics Suite v3.5.1 are the aria_quickstart_ext_res and aria_flash applications. These directly communicate how images can be read and process using external media. You have options: USB Mass storage, SD Card, USB Media. You can also store assets to SQI for persistence if required. It supports not only images, but strings and fonts as well.
 
See: https://microchip-mplab-harmony.github.io/gfx/00050.html.
 
You should be able to run the demonstration without much work on your part. It currently has a image resource (Images.bin). Once you are successful, you can carry the knowledge to your custom application. note: DDR is not used in these examples, but the goal is for you to first establish successful communication.
 
For your custom application, you will need to use MHGC to read and then write your assets to a ".bin" file on a media device. The ".bin" file can be used at run time or stored to SQI.
 
#7
KTrenholm
Super Member
  • Total Posts : 787
  • Reward points : 0
  • Joined: 2012/08/08 14:04:23
  • Location: Connecticut, USA
  • Status: online
Re: Harmony v3: A way to have a "Clean" blit? 2019/12/04 10:29:57 (permalink)
0
What you're describing doesn't really sound like the requirement I need to fulfill.  I actually started from the aria_quickstart_mzda_intddr project.  End goal is I need to be able to load images (bitmaps for now, maybe jpg/png later if I can swing it) onto a USB MSD and cycle through the images on the display when it is plugged into the host PIC.  Preprocessing the images into a custom binary file isn't really an acceptable solution (I think this is what you're describing?  Or do you mean the PIC will process the images and generate a bin file at runtime?).
 
Reading the image from external storage (USB MSD) and putting it onto the display isn't really a problem, and I've done it successfully with bitmaps.  As it stands I am meeting the customer requirement with my read+blit solution, but I'm just hoping I can make the cycling of images nicer and free of any artifacts when going from one image to another.
 
Surely it should be possible to point a GFXU_ImageAsset to DDR rather than internal flash?
 
I had thought that the following:

ImageAsset.header.dataAddress = (void *)ptrImageData; //Points to image data in DDR

would point to DDR to read the image data, but it seems like it's at odds with:

ImageAsset.header.dataLocation = GFXU_ASSET_LOCATION_ID_INTERNAL;  //This denotes image asset is in Internal Flash

 
  I feel like it shouldn't be too hard since the PIC should just be reading the DDR as an extension of it's own memory.  I'm able to read/write it by just creating a pointer with an address in DDR range, 0xA8000000 onward, I just need to determine how to properly set up my GFXU_ImageAsset to go there for the image data
#8
automate
Junior Member
  • Total Posts : 109
  • Reward points : 0
  • Joined: 2014/11/10 09:58:57
  • Location: 0
  • Status: offline
Re: Harmony v3: A way to have a "Clean" blit? 2019/12/04 16:54:27 (permalink) ☄ Helpfulby KTrenholm 2019/12/05 08:17:58
0
I have included an example:
 
 
/****** exampleImage ******/

const uint8_t exampleImage_data[4229] =
{
    0x89,0x50,0x4E,0x47,0x0D,0x0A,0x1A,....
0x15,0x82,0x00,0x00,0x00,0x00,0x49,0x45
};
 
GFXU_ImageAsset exampleImage =
{
    {
        GFXU_ASSET_TYPE_IMAGE, // asset type
        GFXU_ASSET_LOCATION_ID_INTERNAL, // data location id
        (void*)exampleImage_data, // data address pointer
        4229, // data size
    },    
    GFXU_IMAGE_FORMAT_PNG, // image format type
    64, // image width
    64, // image height
    64, // buffer width
    64, // buffer height
    GFX_COLOR_MODE_ARGB_8888, // image color mode
    GFXU_IMAGE_COMPRESSION_NONE, // image compression type (raw only)
    0, // image flags
    0x0, // image mask color
    GFX_NULL // no palette
};

See: libaria_init.c for aria_image_viewer application. at: \gfx_apps\apps\aria_image_viewer\firmware\src\config\glcd_gpu_rgba8888_mxt_mzda_sk\gfx\libaria

laUtils_PreprocessImage(&exampleImage ,0xA83FC000, GFX_COLOR_MODE_RGBA_8888, GFX_FALSE, &laContext_GetActive()->memIntf);
#9
KTrenholm
Super Member
  • Total Posts : 787
  • Reward points : 0
  • Joined: 2012/08/08 14:04:23
  • Location: Connecticut, USA
  • Status: online
Re: Harmony v3: A way to have a "Clean" blit? 2019/12/05 08:17:11 (permalink)
0
automate
I have included an example:
...



Thanks for the example, I didn't see that laUtils_PreprocessImage() was a part of the library.  Now it begins to make a little more sense.  I tried to work this into my design, but I'm still just getting white screens with a couple scattered colored pixels.  The few colored pixels do not change location when different images are loaded.  Here is how I am loading in the images:
 

#define IMAGE_WIDTH 480
#define IMAGE_HEIGHT 272
#define IMAGE_DATA_ADDR 0xA817E800  //Processed image is placed here by laUtils_PreprocessImage()
#define IMAGE_TEMP_ADDR 0xA827E000  //Image is loaded from USB to this address in DDR
 
uint32_t * ptrImageData = (uint32_t *)IMAGE_DATA_ADDR;
uint32_t * ptrImageTemp = (uint32_t *)IMAGE_TEMP_ADDR;
 
GFXU_ImageAsset ImageAsset;
 
void SetupBitmapData (BITMAP_DATA * bmp_info){
    uint32_t size = SYS_FS_FileSize(bmp_info->fs_handle);
    
    SYS_FS_FileRead(bmp_info->fs_handle, ptrImageTemp, size);    //Read entire file from USB into DDR
    
    ImageAsset.header.type = GFXU_ASSET_TYPE_IMAGE;
    ImageAsset.header.dataLocation = GFXU_ASSET_LOCATION_ID_INTERNAL;
    ImageAsset.header.dataAddress = (void *)ptrImageData;
    ImageAsset.header.dataSize = size;
    
    ImageAsset.format = GFXU_IMAGE_FORMAT_RAW;          //bitmap - raw pixel data
    ImageAsset.width = IMAGE_WIDTH;
    ImageAsset.height = IMAGE_HEIGHT;
    ImageAsset.bufferWidth = IMAGE_WIDTH;
    ImageAsset.bufferHeight = IMAGE_HEIGHT;
    ImageAsset.colorMode = GFX_COLOR_MODE_RGB_888;      //24-bit bitmap
    ImageAsset.compType = GFXU_IMAGE_COMPRESSION_NONE;
    ImageAsset.flags = 0;
    ImageAsset.mask = 0x0;
    ImageAsset.palette = GFX_NULL;

    /*Process image to IMG_DATA_ADDR in DDR as ARGB8888*/
    laUtils_PreprocessImage(&ImageAsset, IMAGE_DATA_ADDR, GFX_COLOR_MODE_ARGB_8888, GFX_FALSE, NULL);
}

 
The image is written to the img_backImage widget by:

laImageWidget_SetImage((laImageWidget*)img_backImage, &ImageAsset);

 
Does this look proper?
If this all looks fine then I'll probably have to look for something elsewhere in my code (it's admittedly a little messy after experimenting with it for the past couple weeks).
 
[EDIT] Interesting note, it appears that writing the image in this way also prevents n2d_fill() from working, it does not seem to change anything on the display when called to fill w/ black.
 
Again, the help is very much appreciated.
post edited by KTrenholm - 2019/12/05 09:04:09
#10
KTrenholm
Super Member
  • Total Posts : 787
  • Reward points : 0
  • Joined: 2012/08/08 14:04:23
  • Location: Connecticut, USA
  • Status: online
Re: Harmony v3: A way to have a "Clean" blit? 2019/12/05 09:49:45 (permalink)
0
I think I found at least one problem with my code in the previous post, I forgot to change the address of the Image Asset:

ImageAsset.header.dataAddress = (void *)ptrImageData;

I think should be:

ImageAsset.header.dataAddress = (void *)ptrImageTemp;

 
If I'm not mistaken, that address should be where the image is read from for preprocessing.
So with this info, wouldn't this mean that I need to have adjust (or have a separate) GFXU_ImageAsset for the write to the image widget?  Like so:
 

static void SetupBitmapData (BITMAP_DATA * bmp_info){
    uint32_t size = SYS_FS_FileSize(bmp_info->fs_handle);
    
    SYS_FS_FileRead(bmp_info->fs_handle, ptrImageTemp, size);
    
    /*ImageAsset_Pre describes the image read in from USB MSD at ptrImageTemp*/
    ImageAsset_Pre.header.type = GFXU_ASSET_TYPE_IMAGE;
    ImageAsset_Pre.header.dataLocation = GFXU_ASSET_LOCATION_ID_INTERNAL;
    ImageAsset_Pre.header.dataAddress = (void *)ptrImageTemp;
    ImageAsset_Pre.header.dataSize = size;
    
    ImageAsset_Pre.format = GFXU_IMAGE_FORMAT_RAW;          //bitmap - raw pixel data
    ImageAsset_Pre.width = IMAGE_WIDTH;
    ImageAsset_Pre.height = IMAGE_HEIGHT;
    ImageAsset_Pre.bufferWidth = IMAGE_WIDTH;
    ImageAsset_Pre.bufferHeight = IMAGE_HEIGHT;
    ImageAsset_Pre.colorMode = GFX_COLOR_MODE_RGB_888;      //24-bit bitmap
    ImageAsset_Pre.compType = GFXU_IMAGE_COMPRESSION_NONE;
    ImageAsset_Pre.flags = 0;
    ImageAsset_Pre.mask = 0x0;
    ImageAsset_Pre.palette = GFX_NULL;
   
    /*Process image to IMG_DATA_ADDR in DDR as ARGB8888*/
    laUtils_PreprocessImage(&ImageAsset_Pre, IMAGE_DATA_ADDR, GFX_COLOR_MODE_ARGB_8888, GFX_FALSE, NULL);
   
    /*ImageAsset_Post describes our new converted image located at ptrImageData*/
    ImageAsset_Post.header.type = GFXU_ASSET_TYPE_IMAGE;
    ImageAsset_Post.header.dataLocation = GFXU_ASSET_LOCATION_ID_INTERNAL;
    ImageAsset_Post.header.dataAddress = (void *)ptrImageData;
    ImageAsset_Post.header.dataSize = size;
    
    ImageAsset_Post.format = GFXU_IMAGE_FORMAT_RAW;          //bitmap - raw pixel data
    ImageAsset_Post.width = IMAGE_WIDTH;
    ImageAsset_Post.height = IMAGE_HEIGHT;
    ImageAsset_Post.bufferWidth = IMAGE_WIDTH;
    ImageAsset_Post.bufferHeight = IMAGE_HEIGHT;
    ImageAsset_Post.colorMode = GFX_COLOR_MODE_ARGB_8888;      //Process should have made image data ARGB8888
    ImageAsset_Post.compType = GFXU_IMAGE_COMPRESSION_NONE;
    ImageAsset_Post.flags = 0;
    ImageAsset_Post.mask = 0x0;
    ImageAsset_Post.palette = GFX_NULL;
}

 
This didn't work, but I don't have scattered colored pixels on the display anymore, just white screens for all my images.  I do wonder, Is there a way to determine the size of the post-processed image for the image asset header?  Going from RGB888 to ARGB8888 would just be a size increase of the number of pixels in the image but how would I determine the size of, say, a conversion from JPG to ARGB8888?
 
Am I on the right track here or am I running down the wrong path?
 
 
 
 
#11
automate
Junior Member
  • Total Posts : 109
  • Reward points : 0
  • Joined: 2014/11/10 09:58:57
  • Location: 0
  • Status: offline
Re: Harmony v3: A way to have a "Clean" blit? 2019/12/05 10:30:35 (permalink)
0
It is preferred to use MPLAB Harmony Graphics Composer to process your images. See aria_quickstart_ext_res. Using the Image Assets panel you will observe that the project contains 5 images with memory location "Images" and not Internal memory.  Using "memory configuration" panel, you will notice that Images are written to ".bin" file. The ".bin" file can then be written to a external media device of your choice. Your application can use these images during runtime using a unpacking algorithm.  Note: There is a unpacking performance cost if Images remain on external media such as USB drive. Better performance would be to store them to SQI memory.
 
Test...
One recommendation is test that you are able to iterate/cycle a few images written in flash. Then move the images to external media and perform the same test. This process will help expose any issues.
 
Info....
New in MPLAB Harmony Graphics Suite v3.5.1 are the aria_quickstart_ext_res and aria_flash applications. These directly communicate how images can be read and processed using external media. You have options: USB Mass storage, SD Card, USB Media. You can also store assets to SQI for persistence, if required. This solution supports not only images, but strings and fonts as well.
#12
KTrenholm
Super Member
  • Total Posts : 787
  • Reward points : 0
  • Joined: 2012/08/08 14:04:23
  • Location: Connecticut, USA
  • Status: online
Re: Harmony v3: A way to have a "Clean" blit? 2019/12/06 08:48:54 (permalink)
0
A new fun note, it looks like I do NOT need a 2nd image asset for the "post" processed image data. looking at the code for laUtils_PreprocessImage() shows that it actually modifies the Image Asset that you pass in a reference to, to reflect the new location in memory as well as the new formatting of the image:

 
laResult laUtils_PreprocessImage(GFXU_ImageAsset* img,
                                uint32_t destAddress,
                                GFX_ColorMode destMode,
                                GFX_Bool padBuffer,
                                GFXU_MemoryIntf * memIntf){

/*snip*/
img->header.dataAddress = (void*)destAddress;
    img->header.dataLocation = 0;
    img->header.dataSize = buf.buffer_length;
    img->bufferWidth = buf.size.width;
    img->bufferHeight = buf.size.height;
    img->format = GFXU_IMAGE_FORMAT_RAW;
    img->compType = GFXU_IMAGE_COMPRESSION_NONE;
}

 

 
So to answer my own question:
No, I do not need a seperate ImageAsset for the "post process" image data, the library takes care of it for you by modifying what's passed in.
 
Is this mentioned in the docs for this function?  Of course not! wink: wink
 
I'd put a image of the function docs here, but evidently that' just TOO MUCH for the forum to handle.
#13
KTrenholm
Super Member
  • Total Posts : 787
  • Reward points : 0
  • Joined: 2012/08/08 14:04:23
  • Location: Connecticut, USA
  • Status: online
Re: Harmony v3: A way to have a "Clean" blit? 2019/12/06 09:16:18 (permalink)
0
Oh, I forgot to mention I also thought maybe the bitmap header information needed to be removed, and it was maybe just looking for pixel data.  Of course, nowhere in the docs that I can find does it mention if header information should be kept or removed for laUtils_PreprocessImage() to properly parse the data.  This also looks to be a path to nowhere, same result as before, just white screens:
 

static void SetupBitmapData (BITMAP_DATA * bmp_info){
    uint32_t size = SYS_FS_FileSize(bmp_info->fs_handle) - bmp_info->px_index;
    
    SYS_FS_FileSeek(bmp_info->fs_handle, bmp_info->px_index, SYS_FS_SEEK_SET); /*Set file pointer to first pixel of image data after header*/
    
    SYS_FS_FileRead(bmp_info->fs_handle, ptrImageTemp, size-bmp_info->px_index);
    
    ImageAsset.header.type = GFXU_ASSET_TYPE_IMAGE;
    ImageAsset.header.dataLocation = GFXU_ASSET_LOCATION_ID_INTERNAL;
    ImageAsset.header.dataAddress = (void *)ptrImageTemp;
    ImageAsset.header.dataSize = size-bmp_info->px_index;
    
    ImageAsset.format = GFXU_IMAGE_FORMAT_RAW;          //bitmap - raw pixel data
    ImageAsset.width = IMAGE_WIDTH;
    ImageAsset.height = IMAGE_HEIGHT;
    ImageAsset.bufferWidth = IMAGE_WIDTH;
    ImageAsset.bufferHeight = IMAGE_HEIGHT;
    ImageAsset.colorMode = GFX_COLOR_MODE_RGB_888;      //24-bit bitmap
    ImageAsset.compType = GFXU_IMAGE_COMPRESSION_NONE;
    ImageAsset.flags = 0;
    ImageAsset.mask = 0x0;
    ImageAsset.palette = GFX_NULL;
    
    
    /*Process image to IMG_DATA_ADDR in DDR as ARGB8888*/
    laUtils_PreprocessImage(&ImageAsset, IMAGE_DATA_ADDR, GFX_COLOR_MODE_ARGB_8888, GFX_FALSE, NULL);

}

 
I'm also curious as to why running this code and setting the image via laImageWidget_SetImage() seems to prevent n2d_fill() from working.  it seems to have no effect on the display when I call it after laImageWidget_SetImage(), whereas if I use n2d_blit() to write the image like I did originally n2d_fill() works just as expected.
 
#14
automate
Junior Member
  • Total Posts : 109
  • Reward points : 0
  • Joined: 2014/11/10 09:58:57
  • Location: 0
  • Status: offline
Re: Harmony v3: A way to have a "Clean" blit? 2019/12/06 10:13:38 (permalink)
0
laUtils_PreprocessImage() will write RAW pixels to DDR.
 
laImageWidget_SetImage() operates on a widget. Once the widget changes state, its draw function will be envoked and override its rect area. This could affect n2d_fill() and n2d_blit() when used outside of the library task machine.
#15
KTrenholm
Super Member
  • Total Posts : 787
  • Reward points : 0
  • Joined: 2012/08/08 14:04:23
  • Location: Connecticut, USA
  • Status: online
Re: Harmony v3: A way to have a "Clean" blit? 2019/12/06 10:34:59 (permalink)
0
automate
laUtils_PreprocessImage() will write RAW pixels to DDR.

Right, I can see that it's just pixel data that comes out, but is it expecting nothing but pixel data in?  Basically when I give it a bitmap, does it want the header info retained or stripped out?
 
automate
laImageWidget_SetImage() operates on a widget. Once the widget changes state, its draw function will be envoked and override its rect area. This could affect n2d_fill() and n2d_blit() when used outside of the library task machine.


aha!  I didn't realize that.
I find that peculiar though, because laImageWidget_SetImage() is being called on boot as part of the creation of the bootup screen (which is to say, the only screen).  I'm displaying a company logo image (pre-processed by MHC) as part of the default starting screen (and this starting screen displays with no problem), and n2d_blit/fill both work after that call, but not my call from inside my application state machine?
 
With this new info I thought maybe my setting up and initializing layers for blitting/fill was maybe "overriding" the widget, so I tried removing these lines from my APP_Initialize:

    /*Initialize Layer 0 (image)*/
    PLIB_GLCD_LayerGlobalAlphaSet(  0, 0xFF );
    PLIB_GLCD_LayerDestBlendFuncSet( 0, GLCD_LAYER_DEST_BLEND_BLACK );
    PLIB_GLCD_LayerSrcBlendFuncSet( 0, GLCD_LAYER_SRC_BLEND_WHITE );
    PLIB_GLCD_LayerBaseAddressSet( 0, (uint32_t)GFX_GLCD_LAYER0_BASEADDR);

    /* initialize gui layer */
    PLIB_GLCD_LayerGlobalAlphaSet(  1, 0x00 );
    PLIB_GLCD_LayerBaseAddressSet( 1, (uint32_t)GFX_GLCD_LAYER1_BASEADDR);
   
    layer0buffer.format = N2D_RGBA8888;
    layer0buffer.gpu = KVA_TO_PA(GFX_GLCD_LAYER0_BASEADDR);
    layer0buffer.memory = (void*)GFX_GLCD_LAYER0_BASEADDR;
    layer0buffer.width = scr_rect.width;
    layer0buffer.height = scr_rect.height;
    layer0buffer.orientation = N2D_0;
    layer0buffer.stride = layer0buffer.width * 32 / 8;
    
    /*Set up image buffer for our bitmap*/
    imgbuffer.format = N2D_RGBA8888;
    imgbuffer.gpu = KVA_TO_PA(IMAGE_DATA_ADDR);
    imgbuffer.memory = (void*)IMAGE_DATA_ADDR;
    imgbuffer.height = IMAGE_HEIGHT;
    imgbuffer.width = IMAGE_WIDTH;
    imgbuffer.orientation = N2D_0;
    imgbuffer.stride = imgbuffer.width * 32 / 8;

 
Unfortunately still no luck.
 
I also tried writing my MHC processed image asset back to the display in my app state machine (on USB disconnect) and it gives the same result of a white screen as my runtime processed images do, so something is getting messed up somewhere.  Do I need to maybe do some sort of re-initializing of the layer/widget before writing an image to it?
 
 
post edited by KTrenholm - 2019/12/06 11:32:50
#16
automate
Junior Member
  • Total Posts : 109
  • Reward points : 0
  • Joined: 2014/11/10 09:58:57
  • Location: 0
  • Status: offline
Re: Harmony v3: A way to have a "Clean" blit? 2019/12/06 13:31:59 (permalink)
0
MPLAB Harmony Graphics Suite v3.5 has a working 3 layer example called: aria_radial_menu. Please reference this example for your efforts. The main_screen, contains an imagewidget which displays an image as the background. It also contains a radialMenuWidget on Layer1. It also has a Layer2 with a user UI button. The images are not from external USB. You should be able to leverage this application now and add USB external media image access later.
#17
KTrenholm
Super Member
  • Total Posts : 787
  • Reward points : 0
  • Joined: 2012/08/08 14:04:23
  • Location: Connecticut, USA
  • Status: online
Re: Harmony v3: A way to have a "Clean" blit? 2019/12/06 14:32:51 (permalink)
0
I have uploaded my current version of the project here.  Probably more insightful than explaining how everything works and potentially missing something critical.  Maybe something will get noticed that I'm missing when all the code is here.  Do pardon the mess of the code in places, I've been doing quite a bit of tinkering with this for a bit trying to get it working.  There's a #define USE_BLIT at the top of app.c that switches between using direct blit to layer0 and attempting to use the ImageWidget.  There's another #define USE_BMP_HEADER that determines if the Bitmap header should be kept or stripped.  Files on the USB MSD are expected to be 8.3 filename, 24-bit bitmaps.
 
Bitmap gets read in from USB in the USB_STATE_OPEN_FILE state.  Sent to the ImageWidget in the USB_STATE_DISPLAY_FILE state.  The fade for the text widget on layer 1 is a little busted, and not working exactly as intended, but the label itself works to read out the filename (8.3 format) of the image being put on the display.
 
As far as I can tell, this really should be as simple as constructing a GFXU_ImageAsset from the read in data to the laImageWidget_SetImage() function, but it just can't seem to figure out why it doesn't display.  There has to be something going on that I'm not seeing that's throwing a wrench into the works.
#18
automate
Junior Member
  • Total Posts : 109
  • Reward points : 0
  • Joined: 2014/11/10 09:58:57
  • Location: 0
  • Status: offline
Re: Harmony v3: A way to have a "Clean" blit? 2019/12/10 09:22:30 (permalink)
0
For your issue, it is best to start with a working demonstration. Microchip examples are ready to run. They are capable of loading MHC and running MH Graphics Composer. This will help generate the appropriate files.
 
When working with images, you have ImageWidget and ImageWidgetPlus. MHGC will produce laUtils_PreprocessImage() for all images stored to DDR. You should focus on flash images and then DDR preprocessed images.
 
After you are comfortable with 24bit images in flash and DDR, use aria_quickstart_ext example to create external assets of the same images.
 
You application can then be shared as a common communication source. Your current application is not capable of running MHC and verification of your problem, is not impossible, but slightly difficult.
 
 
#19
KTrenholm
Super Member
  • Total Posts : 787
  • Reward points : 0
  • Joined: 2012/08/08 14:04:23
  • Location: Connecticut, USA
  • Status: online
Re: Harmony v3: A way to have a "Clean" blit? 2019/12/10 09:42:03 (permalink)
0
As I've mentioned, I've used multiple demo projects and they all work fine, including aria_image_viewer.  Images preprocessed from MHC display with no issues on initialization of the application.  You can even see it in my project, the bootup screen color bars are processed into flash by MHC.  You can see it in gfx_assets.c:

const uint8_t bars_data[391680] =
{
...
};

 
and the corresponding image asset:
 

GFXU_ImageAsset bars =
{
    {
        GFXU_ASSET_TYPE_IMAGE, // asset type
        GFXU_ASSET_LOCATION_ID_INTERNAL, // data location id
        (void*)bars_data, // data address pointer
        391680, // data size
    },    
    GFXU_IMAGE_FORMAT_RAW, // image format type
    480, // image width
    272, // image height
    480, // buffer width
    272, // buffer height
    GFX_COLOR_MODE_RGB_888, // image color mode
    GFXU_IMAGE_COMPRESSION_NONE, // image compression type (raw only)
    GFXU_IMAGE_SUPPORTS_CLIPPING, // image flags
    0x0, // image mask color
    GFX_NULL // no palette
};

 
I can see where it's called in libaria_init.c in ScreenCreate_bootscreen():
 

    img_backImage = laImageWidget_New();
    laWidget_SetSize((laWidget*)img_backImage, 480, 272);
    laWidget_SetBackgroundType((laWidget*)img_backImage, LA_WIDGET_BACKGROUND_NONE);
    laWidget_SetBorderType((laWidget*)img_backImage, LA_WIDGET_BORDER_NONE);
    laImageWidget_SetImage(img_backImage, &bars);
    laWidget_AddChild((laWidget*)layer0, (laWidget*)img_backImage);

       
This displays to the ImageWidget with no probelms on initialization, but after attempting (and failing) to display other (from USB) images to the widget, if I try and return to it when USB disconnects in my code:

        case USB_STATE_IDLE:
            if(usbData.deviceIsConnected == false)
            {
                LED1_Off();
                appData.usb_state = USB_STATE_WAIT_FOR_DEVICE_ATTACH;
                laLabelWidget_SetText((laLabelWidget *)lbl_imgName, laString_CreateFromCharBuffer("USB REMOVED", &NotoSans_Regular));
                laImageWidget_SetImage(img_backImage, &bars);
                Layer1_ResetFade();
            }
            break;

 
This does not work to display the color bars.  The Label Widget updates with no problems but the image widget remains all white pixels.
post edited by KTrenholm - 2019/12/10 09:43:39
#20
Page: 12 > Showing page 1 of 2
Jump to:
© 2020 APG vNext Commercial Version 4.5