Page 1 of 2

Bug in HasAlpha()

PostPosted: Sat Apr 01, 2017 12:16 pm
by Enrico Maria Giordano
The function HasAlpha doesn't work anymore. It returns .T. even if the image doesn't have an alpha channel. I noticed that the function has been changed in dibbmp.c, don't know exactly when.

EMG

Re: Bug in HasAlpha()

PostPosted: Sat Apr 01, 2017 1:17 pm
by Enrico Maria Giordano
This is a sample:

Code: Select all  Expand view
#include "Fivewin.ch"


FUNCTION MAIN()

    LOCAL hBmp := LOADIMG( "c:\fwh\bitmaps\olga1.jpg" )

    ? hBmp
    ? HASALPHA( hBmp )

    RETURN NIL


FUNCTION LOADIMG( cFile )

    IF !FILE( cFile )
        RETURN 0
    ENDIF

    IF UPPER( CFILEEXT( cFile ) ) = "BMP"
        RETURN READBITMAP( 0, cFile )
    ENDIF

    RETURN GDIP_IMAGEFROMFILE( cFile, .T., UPPER( CFILEEXT( cFile ) ) = "GIF" )


Any ideas?

EMG

Re: Bug in HasAlpha()

PostPosted: Tue Apr 04, 2017 2:28 pm
by Enrico Maria Giordano
Up! :-)

EMG

Re: Bug in HasAlpha()

PostPosted: Tue Apr 04, 2017 10:16 pm
by cnavarro
Try with

Code: Select all  Expand view


#include "Fivewin.ch"


FUNCTION MAIN()

    local cFile := "d:\fwh\fwhteam\bitmaps\olga1.jpg"
    local hBmp := LoadImg( cFile )

    ? hBmp, HASALPHA( hBmp )
    ? GdiplusImagePixGetAlpha( GdiPlusImageLoadCachedFile( cFile ) ), ;
      ( GdiplusImagePixGetAlpha( GdiPlusImageLoadCachedFile( cFile ) ) = 0 )

    cFile  := "D:\Fwh\FwhTeam\bitmaps\AlphaBmp\android.bmp"
    hBmp := LoadImg( cFile )

    ? hBmp, HASALPHA( hBmp )
    ? GdiplusImagePixGetAlpha( GdiPlusImageLoadCachedFile( cFile ) ), ;
      ( GdiplusImagePixGetAlpha( GdiPlusImageLoadCachedFile( cFile ) ) = 0 )

Return NIL

//----------------------------------------------------------------------------//

FUNCTION LoadImg( cFile )

    IF !FILE( cFile )
        RETURN 0
    ENDIF

    IF UPPER( CFILEEXT( cFile ) ) = "BMP"
        RETURN READBITMAP( 0, cFile )
    ENDIF

Return GDIP_IMAGEFROMFILE( cFile, .T., UPPER( CFILEEXT( cFile ) ) = "GIF" )

 

Re: Bug in HasAlpha()

PostPosted: Tue Apr 04, 2017 10:22 pm
by cnavarro
Another possibility

Code: Select all  Expand view


#include "Fivewin.ch"


FUNCTION MAIN()

   local oBmp
   local cFile := "d:\fwh\fwhteam\bitmaps\olga1.jpg"
   local hBmp := LoadImg( cFile )

   ? hBmp, HASALPHA( hBmp )
   ? GdiplusImagePixGetAlpha( GdiPlusImageLoadCachedFile( cFile ) ), ;
      ( GdiplusImagePixGetAlpha( GdiPlusImageLoadCachedFile( cFile ) ) = 0 )

   cFile  := "D:\Fwh\FwhTeam\bitmaps\AlphaBmp\android.bmp"
   hBmp := LoadImg( cFile )

   ? hBmp, HASALPHA( hBmp )
   ? GdiplusImagePixGetAlpha( GdiPlusImageLoadCachedFile( cFile ) ), ;
      ( GdiplusImagePixGetAlpha( GdiPlusImageLoadCachedFile( cFile ) ) = 0 )

   cFile := "d:\fwh\fwhteam\bitmaps\olga1.jpg"
   oBmp := GdiBmp():New( cFile )
   ? oBmp:IsAlphaChannel(), oBmp:Is32Bits()
   oBmp:Destroy()

   cFile  := "D:\Fwh\FwhTeam\bitmaps\AlphaBmp\android.bmp"
   oBmp := GdiBmp():New( cFile )
   ? oBmp:IsAlphaChannel(), oBmp:Is32Bits()
   oBmp:Destroy()

Return NIL

//----------------------------------------------------------------------------//

FUNCTION LoadImg( cFile )

    IF !FILE( cFile )
        RETURN 0
    ENDIF

    IF UPPER( CFILEEXT( cFile ) ) = "BMP"
        RETURN READBITMAP( 0, cFile )
    ENDIF

Return GDIP_IMAGEFROMFILE( cFile, .T., UPPER( CFILEEXT( cFile ) ) = "GIF" )

 

Re: Bug in HasAlpha()

PostPosted: Wed Apr 05, 2017 8:09 am
by Enrico Maria Giordano
What is the official way to load an image and to check for alpha channel without using classes?

EMG

Re: Bug in HasAlpha()

PostPosted: Wed Apr 05, 2017 8:18 am
by Antonio Linares
This is an interesting reading and this code may be the simplest way to do it:

https://www.gamedev.net/topic/607214-get-alpha-channel-from-32bit-bmp/

Code: Select all  Expand view
struct ABGRStruct {
        BYTE a,b,g,r;
    };

    FILE *f = fopen("the_file_name.bmp", "rb");
    if(f){

        int w, h;
        fseek(f, 0x12, SEEK_SET);
        fread(&w, 1, sizeof(int), f);
        fread(&h, 1, sizeof(int), f);
        fseek(f, 54, SEEK_SET);

        int NumPixels = w * h;
        for(int i = 0; i < NumPixels; i++){
            ABGRStruct Pixel;
            fread(&Pixel, 1, 4, f);

            // do something with alpha
        }

        fclose(f);
    }

Re: Bug in HasAlpha()

PostPosted: Wed Apr 05, 2017 8:26 am
by Enrico Maria Giordano
Thank you. I will wait for something faster. I'm going to drop alpha channel support in my application, for the moment.

EMG

Re: Bug in HasAlpha()

PostPosted: Wed Apr 05, 2017 8:30 am
by Antonio Linares
BitBlt() is the fastest way to manage bitmaps

Not sure if there is a flag we could used for Alpha channel detection

Re: Bug in HasAlpha()

PostPosted: Wed Apr 05, 2017 9:19 am
by Antonio Linares
Enrico,

Windows function AlphaBlend() returns a logical value once it tries to paint a bitmap that have transparent or semitransparent pixels:

https://msdn.microsoft.com/en-us/library/windows/desktop/dd183351(v=vs.85).aspx

Thus, we could modify FWH function ABPaint() to return the return value of the AlphaBlend() call there

Re: Bug in HasAlpha()

PostPosted: Wed Apr 05, 2017 9:31 am
by Enrico Maria Giordano
Ok, let's try it.

EMG

Re: Bug in HasAlpha()

PostPosted: Wed Apr 05, 2017 10:01 am
by Antonio Linares
Please try it using this function:

You have to provide it a hDC and later on call DeleteDC()

Code: Select all  Expand view
HB_FUNC( ABPAINT )
{
   #ifdef _WIN64
     HDC hDC = ( HDC ) hb_parnll( 1 );
   #else
     HDC hDC = ( HDC ) hb_parnl( 1 );
   #endif

   HDC hDCComp = CreateCompatibleDC( hDC );
   BITMAP bm;
   HGDIOBJ hOldBmp = SelectObject( hDCComp, ( HBITMAP ) fw_parH( 4 ) );
   BLENDFUNCTION blend;
   int wDest, hDest;

   blend.BlendOp = AC_SRC_OVER;
   blend.BlendFlags = 0;
   blend.SourceConstantAlpha = IF( hb_parnl( 5 ) != 0, hb_parnl( 5 ), 220 );
   blend.AlphaFormat = AC_SRC_ALPHA;

   #ifdef _WIN64
      GetObject( ( HBITMAP ) hb_parnll( 4 ), sizeof( BITMAP ), ( LPSTR ) &bm );
   #else
      GetObject( ( HBITMAP ) hb_parnl( 4 ), sizeof( BITMAP ), ( LPSTR ) &bm );
   #endif

   wDest = bm.bmWidth;
   hDest = bm.bmHeight;

   if( hb_pcount() > 5 )
   {
      wDest = hb_parni( 6 );
      hDest = hb_parni( 7 );
   }

   hb_retl( AlphaBlend( hDC, hb_parnl( 2 ), hb_parnl( 3 ), wDest, hDest, hDCComp,
               0, 0, bm.bmWidth, bm.bmHeight, blend ) );

   SelectObject( hDCComp, hOldBmp );
   DeleteDC( hDCComp );
}
 

Re: Bug in HasAlpha()

PostPosted: Wed Apr 05, 2017 10:24 am
by Enrico Maria Giordano
I don't understand. I have to select the correct painting function to use after checking for alpha channel. Ie:

IF HASALPHA()
use ABPAINT()
ELSE
use something else
ENDIF

EMG

Re: Bug in HasAlpha()

PostPosted: Wed Apr 05, 2017 10:33 am
by Antonio Linares
The idea is:

lHasAlpha = ABPaint( hDC, nX, nY, hBitmap, nAlphaLevel )

Re: Bug in HasAlpha()

PostPosted: Wed Apr 05, 2017 11:17 am
by Enrico Maria Giordano
Yes, but then the image is already printed with the right or wrong function. We need of a checking function that doesn't print the image, I think.

EMG