Loading 32-bit PNG with datatypes

This forum is for general developer support questions.
Grzegorz Kraszewski
Posts: 6
Joined: Wed Oct 24, 2012 11:56 am

Loading 32-bit PNG with datatypes

Post by Grzegorz Kraszewski »

I want to load a PNG image with its alpha channel and then blit fragments of this image into window RastPort using BltBitMapTags(). So far I'm unsuccesfull, images are blitted, but without alpha. The first problem is that PDTA_Depth returns me 24 (instead of 32). Do I need some special tag for NewDTObject()?
Crisot
Posts: 17
Joined: Fri Jan 04, 2013 12:43 pm

Re: Loading 32-bit PNG with datatypes

Post by Crisot »

Code: Select all

dto = NewDTObject(filename,
                              DTA_GroupID, GID_PICTURE,
                              PDTA_DestMode, PMODE_V43,
                              PDTA_Remap, FALSE,
                              TAG_END );

GetDTAttrs(dto, PDTA_BitMapHeader, (ULONG)&bmh, TAG_END );
 
bufA=AllocVec(bmh->bmh_Width*bmh->bmh_Height*4, MEMF_SHARED);

bpa.pbpa_PixelData = bufA;
bpa.pbpa_PixelFormat = PBPAFMT_ARGB;
bpa.pbpa_PixelArrayMod = bmh->bmh_Width*4;
bpa.pbpa_Left = 0;
bpa.pbpa_Top = 0;
bpa.pbpa_Width = bmh->bmh_Width;
bpa.pbpa_Height = bmh->bmh_Height;
IDoMethodA(dto, (Msg)&bpa);
This is (sniped) what I use to load 32 bits alpha pictures, And yes, IIRC, bmh_Depth returns 24, even with 32 bits pictures. Dunno why, but this used to work for me anyway.
Maybe the problem come from BltBitMapTags(), but I can't help you, I never used it. Anyway it's simple, just check every 4th byte in your picture buffer.
AmiDARK
Posts: 40
Joined: Thu Oct 20, 2011 10:23 am

Re: Loading 32-bit PNG with datatypes

Post by AmiDARK »

Hi Grzegorz,

Here is my personal function to load images (using datatypes) in the AmiDARK Engine.
It work with PNG using alpha transparency ( RGBA 32bits images ).

Code: Select all

struct MyPicture * LoadPicture( APTR FileName ){
  struct MyPicture *pt = NULL;
  Object *dto = NULL;
  ULONG nb;
  ULONG * AvailMethod = NULL;
  struct BitMapHeader *bmh;
  struct pdtBlitPixelArray bpa;
  void * bpaptr = &bpa;
  if ( !FileName ) return NULL;
  dto = IDataTypes->NewDTObject( (STRPTR)FileName,
                                 DTA_SourceType,    DTST_FILE,
                                 DTA_GroupID,       GID_PICTURE,
                                 PDTA_DestMode,     PMODE_V43,
                                 PDTA_Remap,        TRUE,
                                 OBP_Precision,     PRECISION_EXACT,
                                 TAG_DONE );
  if ( dto != 0 ){
    nb = IIntuition->GetAttrs( dto, PDTA_BitMapHeader, &bmh, TAG_DONE );
    if( nb != 0 ){
      int resread;
      /* Allocation de la structure Picture et du buffer mémoire */
      pt = AllocPicture32( bmh->bmh_Width, bmh->bmh_Height );
      if ( pt != NULL ){
        bpa.pbpa_PixelData = pt->Pixels;
        bpa.pbpa_PixelFormat = PBPAFMT_RGBA;
        bpa.pbpa_PixelArrayMod = bmh->bmh_Width * 4;
        bpa.pbpa_Left = 0;
        bpa.pbpa_Top = 0;
        bpa.pbpa_Width = bmh->bmh_Width;
        bpa.pbpa_Height = bmh->bmh_Height;
        AvailMethod = IDataTypes->GetDTMethods( dto );
        if ( IDataTypes->FindMethod( AvailMethod, PDTM_READPIXELARRAY ) != 0 ){
          bpa.MethodID = PDTM_READPIXELARRAY;
          resread = IIntuition->IDoMethodA( dto, bpaptr );
         }else{
          DebugMessage( debugDEImage, "Method PDTM_READPIXELARRAY not compatible with object.\n", 0 );
         }
       }else{
        DebugMessage( debugDEImage, "Cannot allocate memory for internal picture structure.\n", 0 );
       }
     }else{
      DebugMessage( debugDEImage, "Informations cannot be read from image file.\n", 0 );
     }
     IIntuition->DisposeObject( dto );
   }else{
    DebugMessage( debugDEImage, "Unable to load the image file.\n", 0 );
   }
  return pt;
MyPicture structure is :

Code: Select all

struct MyPicture{
  int Width;
  int Height;
  int Depth;
  unsigned char *Pixels;
 };
and I setup my image buffer this way :

Code: Select all

struct MyPicture * AllocPicture32( int Width, int Height ){
  struct MyPicture *pt = NULL;
  pt = (struct MyPicture *)MyAllocVec( sizeof( struct MyPicture ), MEMF_ANY|MEMF_CLEAR );
  if ( pt ){
    pt->Pixels = MyAllocVec( Width * ( Height + 1 ) * 4, MEMF_ANY );
    pt->Width = Width;
    pt->Height = Height;
    pt->Depth = 32;
    if ( pt->Pixels == NULL ){
      MyFreeVec( pt );
      pt = NULL;
     }
   }
  return pt;
 }
I use IIntuition->IDoMethodA( dto, bpaptr ) to uncompress the image in my memory buffer as raw RGBA 32 bits pixels maps
it allow me to set how the image is decoded using : bpa.pbpa_PixelFormat = PBPAFMT_RGBA;
I force Depth to 32 in the Buffer allocation in the function AllocPicture32( int Width, int Height ). It ensure that the information is correctly given.
I think you will always get 24 bits for image even if there is an alpha 8 bits channel (it's something I remind to have heard when I worked on DataType system :p)

I'm currently working on understanding bltBitMapTags functions and it seem to be used this way :

Code: Select all

void myBltBitMap2BitMap( struct BitMap * srcBitMap, int xStart, int yStart, struct BitMap * tgtBitMap, int xStartT, int yStartT, int Width, int Height, BOOL Transparency ){
  IGraphics->BltBitMapTags( BLITA_SrcType, BLITT_BITMAP,        BLITA_Source, srcBitMap,
                            BLITA_SrcX, xStart,                 BLITA_SrcY, yStart,
                            BLITA_DestType, BLITT_BITMAP,       BLITA_Dest, tgtBitMap,
                            BLITA_DestX, xStartT,               BLITA_DestY, yStartT,
                            BLITA_Width, Width,                 BLITA_Height, Height,
                            BLITA_AlphaMask, Transparency,      TAG_END );
 }
if you use 2 bitmap structures for sources & target.
My function is untested because I'm currently working on these bltBitMap functions these days :p

I hope it helped you.

Kindest Regards,
AmiDARK
Sam440EP - AmigaOS 4.1 Final Edition
Grzegorz Kraszewski
Posts: 6
Joined: Wed Oct 24, 2012 11:56 am

Re: Loading 32-bit PNG with datatypes

Post by Grzegorz Kraszewski »

I see both of you use PDTM_READPIXELARRAY method. As my code is based on AmigaOS 3.x one, it works differently. After setting PDTA_Mode to v43 (which is the default anyway, as stated it the autodoc), I perform DTM_PROCLAYOUT and then query PDTA_DestBitmap. Finally I allocate my buffer bitmap with friend bitmap set to screen's bitmap and do a blit from datatype's DestBitmap to my buffer. Unfortunately it seems this way I loose alpha information.

Then I will simply separate AmigaOS 4 code from AmigaOS 3 code and use PDTM_READPIXELARRAY. I still will copy this pixel array into my buffer bitmap. When my game runs I do many blits from buffer to the game window, so having game imagery in a bitmap being friend to screen bitmap speeds things up.

Then I have another, loosely related question. How to sync blitting frames of animation with screen refresh? I use WaitBOVP() on both AmigaOS 3 and MorphOS, but on AmigaOS 4 animation is significantly slower. Looks like it synchronizes to every second frame instead of each frame. WaitTOF() would be better? Or there is some AmigaOS 4 specific way?
Crisot
Posts: 17
Joined: Fri Jan 04, 2013 12:43 pm

Re: Loading 32-bit PNG with datatypes

Post by Crisot »

Hum, my Os3.x code was really quite the same as the code I showed you, except I used another function than IDoMethodA, but can't remember... Unfortunatelly, I can hardly turn on my 4000T. Are you sure also your PNG datatype support Alpha?

For Os4, I use WaitTOF(), and be sure you have INTERRUPT=YES (or INTERRUPTS=YES, can't remember) in your devs/monitor tooltypes. BTW, screensync give very good visual result, but if you are working on something "heavy" then it's a good idea to make triple buffer and switch/blit from a second process. Vsync in a single process always round down the framerate (60 -> 30 -> 15 -> etc...)
Grzegorz Kraszewski
Posts: 6
Joined: Wed Oct 24, 2012 11:56 am

Re: Loading 32-bit PNG with datatypes

Post by Grzegorz Kraszewski »

Crisot wrote:Hum, my Os3.x code was really quite the same as the code I showed you,
And it worked with OCS/ECS/AGA? I support them too, just in this case the graphics is 4-color IFF ILBM, of course without any alpha.
Crisot wrote:Unfortunatelly, I can hardly turn on my 4000T. Are you sure also your PNG datatype support Alpha?
I have OS 4.1u6 and datatype, which comes with it. I would be surprised if it does not support alpha.
Crisot wrote:BTW, screensync give very good visual result, but if you are working on something "heavy" then it's a good idea to make triple buffer
It is logical game, so not heavy. Also I do doublebuffering in the only one effect involving larger blits (larger is some 700 x 150 pixels). Other than that animations involve moving 24 x 24 pixels block over background (only one at a time) so I don't think it is heavy.
Crisot
Posts: 17
Joined: Fri Jan 04, 2013 12:43 pm

Re: Loading 32-bit PNG with datatypes

Post by Crisot »

Ah! True! Was CGX/Warp3D code. Not sure it works with classic screenmodes.
Ok, with a simple logic game, you won't have to bother with aynchronous triple buffer ^^
chris
Posts: 564
Joined: Sat Jun 18, 2011 12:05 pm
Contact:

Re: Loading 32-bit PNG with datatypes

Post by chris »

@Grzegorz Kraszewski

Are you supplying BLITA_UseSrcAlpha, TRUE to your BltBitMapTags call?
Grzegorz Kraszewski
Posts: 6
Joined: Wed Oct 24, 2012 11:56 am

Re: Loading 32-bit PNG with datatypes

Post by Grzegorz Kraszewski »

chris wrote:Are you supplying BLITA_UseSrcAlpha, TRUE to your BltBitMapTags call?
Of course I do. I have read the autodoc of it carefully.

Code: Select all

BltBitMapTags(
	BLITA_Source, ggfx->Bricks,
	BLITA_SrcType, BLITT_BITMAP,
	BLITA_SrcX, src_x,
	BLITA_SrcY, src_y,
	BLITA_Dest, win->RPort,
	BLITA_DestType, BLITT_RASTPORT,
	BLITA_DestX, x,
	BLITA_DestY, y,
	BLITA_Width, ggfx->BrickWidth,
	BLITA_Height, ggfx->BrickHeight,
	BLITA_UseSrcAlpha, TRUE,
TAG_END);
User avatar
thomasrapp
Posts: 318
Joined: Sun Jun 19, 2011 12:22 am

Re: Loading 32-bit PNG with datatypes

Post by thomasrapp »

AmiDARK wrote:Here is my personal function to load images (using datatypes) in the AmiDARK Engine.
Setting PDTA_Remap to TRUE without setting PDTA_Screen also is nonsense. Same applies to OBP_Precision.
Post Reply