2025-08-29 12:49 UTC+0200 Przemyslaw Czerpak (druzus/at/poczta.onet.pl)

* contrib/hbbmp/core.c
  * contrib/hbbmp/hbbmp.ch
  * contrib/hbbmp/hbbmp.h
  * contrib/hbbmp/hbbmp.hbx
    + added new PRG functions:
         hb_bmp_frombitmap( <cBitMap>, <nAlign>, <nWidth>, <nHeight>, ;
                            [<nDepth>=1], [<nDPI>=72], [<aPalette>], ;
                            [@<nError>] ) -> <pBMP> | NIL
         hb_bmp_colorreset( <pBMP> )

  * contrib/hbct/dattime3.c
    ! struct timespec initialization

  * contrib/hbplist.txt
    + added hbbmp library

  * contrib/hbzebra/coredraw.c
  * contrib/hbzebra/hbzebra.hbx
    + added new PRG function:
         hb_zebra_getbitmap( <hZebra>, <nAlign>=8, <lBottomUp>=.F., ;
                             @<nWidth>, @<nHeight>, <nScaleX>, <nScaleY>, ;
                             <nBorder> ) -> <cBitMap> | NIL

  * contrib/hbzebra/tests/bmp.prg
    + added example for much faster BMP creation using hb_zebra_getbitmap() and
      hb_bmp_frombitmap() functions

  * src/rtl/filebuf.c
    ! casting

  * src/vm/extrap.c
    * allocate stack buffer dynamically, in new Linux version IGSTKSZ is
      defined as sysconf( _SC_SIGSTKSZ ) so it cannot be used as legal size
      for static arrays
This commit is contained in:
Przemysław Czerpak
2025-08-29 12:49:40 +02:00
parent e679f6f8d6
commit c4b2a030c4
12 changed files with 296 additions and 19 deletions

View File

@@ -7,6 +7,42 @@
Entries may not always be in chronological/commit order.
See license at the end of file. */
2025-08-29 12:49 UTC+0200 Przemyslaw Czerpak (druzus/at/poczta.onet.pl)
* contrib/hbbmp/core.c
* contrib/hbbmp/hbbmp.ch
* contrib/hbbmp/hbbmp.h
* contrib/hbbmp/hbbmp.hbx
+ added new PRG functions:
hb_bmp_frombitmap( <cBitMap>, <nAlign>, <nWidth>, <nHeight>, ;
[<nDepth>=1], [<nDPI>=72], [<aPalette>], ;
[@<nError>] ) -> <pBMP> | NIL
hb_bmp_colorreset( <pBMP> )
* contrib/hbct/dattime3.c
! struct timespec initialization
* contrib/hbplist.txt
+ added hbbmp library
* contrib/hbzebra/coredraw.c
* contrib/hbzebra/hbzebra.hbx
+ added new PRG function:
hb_zebra_getbitmap( <hZebra>, <nAlign>=8, <lBottomUp>=.F., ;
@<nWidth>, @<nHeight>, <nScaleX>, <nScaleY>, ;
<nBorder> ) -> <cBitMap> | NIL
* contrib/hbzebra/tests/bmp.prg
+ added example for much faster BMP creation using hb_zebra_getbitmap() and
hb_bmp_frombitmap() functions
* src/rtl/filebuf.c
! casting
* src/vm/extrap.c
* allocate stack buffer dynamically, in new Linux version IGSTKSZ is
defined as sysconf( _SC_SIGSTKSZ ) so it cannot be used as legal size
for static arrays
2025-08-23 18:49 UTC+0200 Przemyslaw Czerpak (druzus/at/poczta.onet.pl)
* contrib/hbbmp/core.c
! fixed copy & past typos reported by Grigory Filatov. Thanks a lot.

View File

@@ -65,7 +65,11 @@ PHB_BMPINFO hb_bmp_new( int width, int height, int depth, int dpi, int * piError
*piError = 0;
if( fromtop )
{
height = -height;
if( height == 1 )
fromtop = HB_FALSE;
}
if( dpi == 0 )
dpi = HB_BMP_DPI_DEFAULT;
@@ -114,6 +118,72 @@ PHB_BMPINFO hb_bmp_new( int width, int height, int depth, int dpi, int * piError
return pBMP;
}
PHB_BMPINFO hb_bmp_frombitmap( const HB_BYTE * bitmap, int align,
int width, int height, int depth, int dpi,
const int * palette, int colors, int * piError )
{
static const int mono_palette[ 2 ] = { 0x00FFFFFF, 0x00000000 };
PHB_BMPINFO pBMP = NULL;
if( bitmap && ( align >= 8 || align >= depth ) && ( align & ( align - 1 ) ) == 0 )
pBMP = hb_bmp_new( width, height, depth, dpi, piError );
else if ( piError )
*piError = HB_BMP_ERROR_CORRUPT;
if( pBMP )
{
if( bitmap )
{
int rowbits = ( ( pBMP->width * depth ) + align - 1 ) & ~( align - 1 );
int rowlen = ( rowbits + 0x07 ) >> 3, row, col;
if( align == 32 )
memcpy( pBMP->data, bitmap, pBMP->height * pBMP->rowlen );
else if( pBMP->height == 1 )
memcpy( pBMP->data, bitmap, HB_MIN( rowlen, pBMP->rowlen ) );
else if( align >= 8 )
{
for( row = 0; row < height; ++row )
memcpy( pBMP->data + pBMP->rowlen * row, bitmap + rowlen * row,
HB_MIN( rowlen, pBMP->rowlen ) );
}
else
{
int maskb, shift;
shift = depth == 4 ? 1 : ( depth == 2 ? 2 : 3 );
maskb = ( 0x01 << shift ) - 1;
for( row = 0; row < height; ++row )
{
HB_BYTE * rowdst = pBMP->data + pBMP->rowlen * row;
int offset = row * rowbits;
for( col = 0; col < width; ++col, offset += depth )
rowdst[ col >> shift ] |= ( ( bitmap[ offset >> shift ] >>
( ( maskb - ( offset & maskb ) ) * depth ) ) &
maskb ) << ( maskb - ( col & maskb ) ) * depth;
}
}
}
if( depth == 1 && ( palette == NULL || colors <= 0 ) )
{
palette = mono_palette;
colors = 2;
}
if( palette && colors > 0 && depth <= 8 )
{
int i;
if( colors > 256 )
colors = 256;
for( i = 0; i < colors; ++i )
{
int clr = palette[ i ];
hb_bmp_color( pBMP, ( clr >> 16 ) & 0xFF, ( clr >> 8 ) & 0xFF, clr & 0xFF, ( clr >> 24 ) & 0xFF );
}
}
}
return pBMP;
}
PHB_BMPINFO hb_bmp_copy( PHB_BMPINFO pBMP )
{
PHB_BMPINFO pBMPnew = ( PHB_BMPINFO ) hb_xgrab( sizeof( HB_BMPINFO ) );
@@ -159,6 +229,12 @@ int hb_bmp_depth( PHB_BMPINFO pBMP )
return pBMP->depth;
}
void hb_bmp_colorreset( PHB_BMPINFO pBMP )
{
memset( pBMP->palette, 0, sizeof( pBMP->palette ) );
pBMP->clrused = 0;
}
HB_MAXINT hb_bmp_color( PHB_BMPINFO pBMP, int r, int g, int b, int a )
{
HB_MAXINT iColor = -1;
@@ -460,7 +536,9 @@ PHB_BMPINFO hb_bmp_decode( const HB_BYTE * data, HB_SIZE size, int * piError )
PHB_BMPINFO pBMP = NULL;
int iError = 0;
if( ! data || size < HB_BMP_FILEHEADER_SIZE + HB_BMP_INFOHEADER_MINSIZE )
if( ! data || size > 0x10000000 )
iError = HB_BMP_ERROR_PARAM;
else if( size < HB_BMP_FILEHEADER_SIZE + HB_BMP_INFOHEADER_MINSIZE )
iError = HB_BMP_ERROR_CORRUPT;
else
{
@@ -691,7 +769,6 @@ void hb_bmpReturn( PHB_BMPINFO pBMP )
HB_FUNC( HB_BMP_NEW )
{
int iError = 0;
PHB_BMPINFO pBMP = hb_bmp_new( hb_parni( 1 ), hb_parni( 2 ),
hb_parnidef( 3, 1 ),
hb_parnidef( 4, HB_BMP_DPI_DEFAULT ),
@@ -700,6 +777,50 @@ HB_FUNC( HB_BMP_NEW )
hb_bmpReturn( pBMP );
}
/* hb_bmp_frombitmap( <cBitMap>, <nAlign>, <nWidth>, <nHeight>, [<nDepth>=1], [<nDPI>=72], [<aPalette>], [@<nError>] ) -> <pBMP> | NIL */
HB_FUNC( HB_BMP_FROMBITMAP )
{
const HB_BYTE * bitmap = ( const HB_BYTE * ) hb_parc( 1 );
int align = hb_parni( 2 ), width = hb_parni( 3 ), height = hb_parni( 4 ),
depth = hb_parni( 5 ), dpi = hb_parni( 6 ),
iError = 0;
PHB_ITEM pColors = hb_param( 7, HB_IT_ARRAY );
HB_BOOL fromtop = height < 0;
PHB_BMPINFO pBMP = NULL;
if( fromtop )
{
height = -height;
if( height == 1 )
fromtop = HB_FALSE;
}
if( ! bitmap || ( align & ( align - 1 ) ) != 0 ||
( HB_SIZE ) ( ( ( width * depth + align - 1 ) & ~( align - 1 ) ) *
height + 0x07 ) >> 3 > hb_parclen( 1 ) )
iError = HB_BMP_ERROR_PARAM;
else
{
pBMP = hb_bmp_frombitmap( bitmap, align, width, fromtop ? -height : height, depth, dpi,
NULL, 0, &iError );
if( pBMP && pColors && depth <= 8 )
{
HB_SIZE nLen = hb_arrayLen( pColors ), nAt;
if( nLen > ( HB_SIZE ) ( 1 << depth ) )
nLen = ( HB_SIZE ) ( 1 << depth );
hb_bmp_colorreset( pBMP );
for( nAt = 1; nAt <= nLen; ++nAt )
{
int clr = hb_arrayGetNI( pColors, nAt );
hb_bmp_color( pBMP, ( clr >> 16 ) & 0xFF, ( clr >> 8 ) & 0xFF,
clr * 0xFF, ( clr >> 24 ) & 0xFF );
}
}
}
hb_storni( iError, 8 );
hb_bmpReturn( pBMP );
}
HB_FUNC( HB_BMP_COPY )
{
PHB_BMPINFO pBMP = hb_bmpParam( 1, HB_TRUE );
@@ -774,6 +895,14 @@ HB_FUNC( HB_BMP_DEPTH )
hb_retni( hb_bmp_depth( pBMP ) );
}
HB_FUNC( HB_BMP_COLORRESET )
{
PHB_BMPINFO pBMP = hb_bmpParam( 1, HB_TRUE );
if( pBMP )
hb_bmp_colorreset( pBMP );
}
HB_FUNC( HB_BMP_COLOR )
{
PHB_BMPINFO pBMP = hb_bmpParam( 1, HB_TRUE );

View File

@@ -59,5 +59,6 @@
#define HB_BMP_ERROR_UNSUPPORTED 8
#define HB_BMP_ERROR_FILEREAD 9
#define HB_BMP_ERROR_FILEWRITE 10
#define HB_BMP_ERROR_PARAM 11
#endif /* _HBBMP_CH_ */

View File

@@ -112,6 +112,7 @@ typedef struct _HB_BMPINFO
} HB_BMPINFO, * PHB_BMPINFO;
extern HB_EXPORT PHB_BMPINFO hb_bmp_new( int width, int height, int depth, int dpi, int * piError );
extern HB_EXPORT PHB_BMPINFO hb_bmp_frombitmap( const HB_BYTE * bitmap, int align, int width, int height, int depth, int dpi, const int * palette, int colors, int * piError );
extern HB_EXPORT PHB_BMPINFO hb_bmp_copy( PHB_BMPINFO pBMP );
extern HB_EXPORT PHB_BMPINFO hb_bmp_decode( const HB_BYTE * data, HB_SIZE size, int * piError );
extern HB_EXPORT HB_BYTE * hb_bmp_encode( PHB_BMPINFO pBMP, HB_SIZE * pnSsize );
@@ -122,6 +123,7 @@ extern HB_EXPORT int hb_bmp_error( PHB_BMPINFO pBMP );
extern HB_EXPORT int hb_bmp_width( PHB_BMPINFO pBMP );
extern HB_EXPORT int hb_bmp_height( PHB_BMPINFO pBMP );
extern HB_EXPORT int hb_bmp_depth( PHB_BMPINFO pBMP );
extern HB_EXPORT void hb_bmp_colorreset( PHB_BMPINFO pBMP );
extern HB_EXPORT HB_MAXINT hb_bmp_color( PHB_BMPINFO pBMP, int r, int g, int b, int a );
extern HB_EXPORT HB_BOOL hb_bmp_color2rgb( PHB_BMPINFO pBMP, HB_MAXINT clr, int * r, int * g, int * b, int * a );
extern HB_EXPORT HB_BOOL hb_bmp_putpixel( PHB_BMPINFO pBMP, int x, int y, HB_MAXINT clr );

View File

@@ -23,12 +23,14 @@
DYNAMIC hb_bmp_color
DYNAMIC hb_bmp_color2rgb
DYNAMIC hb_bmp_colorreset
DYNAMIC hb_bmp_copy
DYNAMIC hb_bmp_decode
DYNAMIC hb_bmp_depth
DYNAMIC hb_bmp_encode
DYNAMIC HB_BMP_ERROR
DYNAMIC hb_bmp_error
DYNAMIC hb_bmp_free
DYNAMIC hb_bmp_frombitmap
DYNAMIC hb_bmp_getpixel
DYNAMIC hb_bmp_height
DYNAMIC hb_bmp_line

View File

@@ -195,7 +195,7 @@ HB_FUNC( SETDATE )
long lNewDate = lDate - hb_dateEncode( 1970, 1, 1 );
# if defined( __GLIBC__ ) && ( ( __GLIBC__ > 2 ) || ( ( __GLIBC__ == 2 ) && ( __GLIBC_MINOR__ >= 31 ) ) )
/* stime() is deprecated in glibc 2.31+ */
struct timespec ts = { 0 };
struct timespec ts = { 0, 0 };
clock_gettime( CLOCK_REALTIME, &ts ); /* keep tv_nsec */
ts.tv_sec = lNewDate * 86400 + ( ts.tv_sec % 86400 );
fResult = clock_settime( CLOCK_REALTIME, &ts ) == 0;

View File

@@ -4,6 +4,7 @@ gtwvg/gtwvg.hbp
hbamf/hbamf.hbp
hbblat/hbblat.hbp
hbblink/hbblink.hbp
hbbmp/hbbmp.hbp
hbbz2/hbbz2.hbp # uses: bz2 (locally hosted)
hbbz2io/hbbz2io.hbp # uses: bz2 (locally hosted)
hbcairo/hbcairo.hbp

View File

@@ -171,6 +171,7 @@ int hb_zebra_getsize( PHB_ZEBRA pZebra, int * piWidth, int * piHeight )
return 0;
}
/* hb_zebra_getsize( <hZebra>, @<nWidth>, @<nHeight> ) -> <nError> */
HB_FUNC( HB_ZEBRA_GETSIZE )
{
PHB_ZEBRA pZebra = hb_zebra_param( 1 );
@@ -184,3 +185,94 @@ HB_FUNC( HB_ZEBRA_GETSIZE )
hb_storni( iHeight, 3 );
}
}
/* NOTE: caller must free the returned bitmap pointer if not NULL */
unsigned char * hb_zebra_getbitmap( PHB_ZEBRA pZebra, int iAlign, HB_BOOL fBottomUp,
HB_SIZE * pnSize, int * piWidth, int * piHeight,
int iScaleX, int iScaleY, int iBorder )
{
unsigned char * pBitMap = NULL;
HB_SIZE nSize = 0;
int iWidth, iHeight;
if( hb_zebra_getsize( pZebra, &iWidth, &iHeight ) == 0 &&
iWidth != 0 && iHeight != 0 )
{
HB_SIZE nLen = hb_bitbuffer_len( pZebra->pBits ), n;
int iLineBits, iLineOffset, iMaxCol, iCol;
if( iAlign < 1 || iAlign > 64 || ( iAlign & ( iAlign - 1 ) ) != 0 )
iAlign = 8;
if( iScaleX < 1 )
iScaleX = 1;
if( iScaleY < 1 )
iScaleY = 1;
if( iBorder < 0 )
iBorder = 0;
iWidth = iWidth * iScaleX + ( iBorder << 1 );
iHeight = iHeight * iScaleY + ( iBorder << 1 );
iLineBits = ( iWidth + ( iAlign - 1 ) ) & ~( iAlign - 1 );
nSize = ( iLineBits * iHeight + 0x07 ) >> 3;
if( nLen > ( nSize << 3 ) )
nLen = nSize << 3;
pBitMap = ( unsigned char * ) hb_xgrab( nSize + 1 );
iMaxCol = pZebra->iCol;
iCol = 0;
if( fBottomUp )
iLineOffset = iLineBits * ( iHeight - iBorder - 1 );
else
iLineOffset = iLineBits * iBorder;
memset( pBitMap, 0, nSize );
for( n = 0; n < nLen; n++ )
{
if( hb_bitbuffer_get( pZebra->pBits, n ) )
{
int iBitPos = iLineOffset + iCol * iScaleX + iBorder, iX, iY;
for( iY = 0; iY < iScaleY; ++iY )
{
for( iX = 0; iX < iScaleX; ++iX )
{
unsigned char * ptr = pBitMap + ( ( iBitPos + iX ) >> 3 );
*ptr |= 0x80 >> ( ( iBitPos + iX ) & 0x07 );
}
iBitPos += fBottomUp ? - iLineBits : iLineBits;
}
}
if( ++iCol == iMaxCol )
{
iCol = 0;
iLineOffset += ( fBottomUp ? - iLineBits : iLineBits ) * iScaleY;
}
}
}
*pnSize = nSize;
*piWidth = iWidth;
*piHeight = iHeight;
return pBitMap;
}
/* hb_zebra_getbitmap( <hZebra>, <nAlign>=8, <lBottomUp>=.F., @<nWidth>, @<nHeight>, <nScaleX>, <nScaleY>, <nBorder> ) -> <cBitMap> | NIL */
HB_FUNC( HB_ZEBRA_GETBITMAP )
{
PHB_ZEBRA pZebra = hb_zebra_param( 1 );
if( pZebra )
{
HB_SIZE nSize;
int iWidth, iHeight;
unsigned char * pBitMap = hb_zebra_getbitmap( pZebra, hb_parni( 2 ), hb_parl( 3 ),
&nSize, &iWidth, &iHeight,
hb_parni( 6 ), hb_parni( 7 ), hb_parni( 8 ) );
hb_storni( iWidth, 4 );
hb_storni( iHeight, 5 );
if( pBitMap )
hb_retclen_buffer( ( char * ) pBitMap, nSize );
else
hb_retc_null();
}
}

View File

@@ -37,6 +37,7 @@ DYNAMIC hb_zebra_create_upca
DYNAMIC hb_zebra_create_upce
DYNAMIC hb_zebra_destroy
DYNAMIC hb_zebra_draw
DYNAMIC hb_zebra_getbitmap
DYNAMIC hb_zebra_getcode
DYNAMIC hb_zebra_geterror
DYNAMIC hb_zebra_getsize

View File

@@ -33,7 +33,8 @@ PROCEDURE Main()
STATIC PROCEDURE DrawBarcode( nLineWidth, cType, cCode, nFlags )
LOCAL hZebra, pBMP, nLineHeight, nX, nY, nWidth, nHeight, nDepth, nColor, cFile
LOCAL hZebra, cFile, cBitMap, pBMP, ;
nLineHeight, nX, nY, nWidth, nHeight, nDepth, nAlign, nColor
SWITCH cType
CASE "EAN13" ; hZebra := hb_zebra_create_ean13( cCode, nFlags ) ; EXIT
@@ -59,13 +60,13 @@ STATIC PROCEDURE DrawBarcode( nLineWidth, cType, cCode, nFlags )
nLineHeight := nLineWidth * 36
ENDIF
nAlign := 32
nDepth := 1
nX := nY := 1
/* get barcode size and add 1 pixel border over it */
hb_zebra_getsize( hZebra, @nWidth, @nHeight )
nX := 1
nY := 1
nWidth := nWidth * nLineWidth + 2
nHeight := nHeight * nLineHeight + 2
nWidth := nWidth * nLineWidth + nY + nY
nHeight := nHeight * nLineHeight + nX + nX
? cType, "code width", hb_ntos( nWidth ), "height", hb_ntos( nHeight )
IF Empty( pBMP := hb_bmp_new( nWidth, nHeight, nDepth ) )
@@ -86,6 +87,18 @@ STATIC PROCEDURE DrawBarcode( nLineWidth, cType, cCode, nFlags )
/* destroy BMP file */
pBMP := NIL
ENDIF
/* and now much faster version */
cBitMap := hb_zebra_getbitmap( hZebra, nAlign, .T./*lBottomUp>*/, @nWidth, @nHeight, nLineWidth, nLineHeight, nX )
pBMP := hb_bmp_frombitmap( cBitMap, nAlign, nWidth, nHeight, nDepth, /*nDPI*/, /*aPalette*/, /*@nError*/ )
cFile := Lower( cType ) + "b.bmp"
? "Creating BMP file:", cFile
IF ! hb_bmp_save( pBMP, cFile )
? "Cannot save BMP to file:", cFile
ENDIF
/* destroy BMP file */
pBMP := NIL
ELSE
? "Type", cType, "Code", cCode, "Error", hb_zebra_geterror( hZebra )
ENDIF

View File

@@ -1655,7 +1655,7 @@ HB_BOOL hb_fileSave( const char * pszFileName, const void * buffer, HB_SIZE nSiz
NULL, NULL );
if( pFile != NULL )
{
const HB_BYTE * pData = buffer;
const HB_BYTE * pData = ( const HB_BYTE * ) buffer;
while( nSize > 0 )
{

View File

@@ -82,7 +82,7 @@
#endif
#if defined( HB_SIGNAL_EXCEPTION_HANDLER )
static HB_BYTE * s_signal_stack[ SIGSTKSZ ];
static void * s_signal_stack = NULL;
#endif
#if defined( HB_OS_WIN ) && ! defined( HB_OS_WIN_CE ) && ! defined( __TINYC__ )
@@ -585,7 +585,9 @@ void hb_vmSetExceptionHandler( void )
#elif defined( HB_SIGNAL_EXCEPTION_HANDLER )
{
stack_t ss;
ss.ss_sp = ( void * ) s_signal_stack;
if( s_signal_stack == NULL )
s_signal_stack = hb_xgrab( SIGSTKSZ );
ss.ss_sp = s_signal_stack;
ss.ss_size = SIGSTKSZ;
ss.ss_flags = 0;
/* set alternative stack for SIGSEGV executed on stack overflow */
@@ -620,10 +622,6 @@ void hb_vmUnsetExceptionHandler( void )
}
#elif defined( HB_SIGNAL_EXCEPTION_HANDLER )
{
/* we are using static buffer for alternative stack so we do not
* have to deallocate it to free the memory on application exit
*/
#if 0
stack_t ss, oss;
ss.ss_sp = NULL;
ss.ss_size = SIGSTKSZ;
@@ -631,10 +629,12 @@ void hb_vmUnsetExceptionHandler( void )
/* set alternative stack for SIGSEGV executed on stack overflow */
if( sigaltstack( &ss, &oss ) == 0 )
{
if( oss.ss_sp && SS_DISABLE )
free( oss.ss_sp );
if( s_signal_stack != NULL )
{
hb_xfree( s_signal_stack );
s_signal_stack = NULL;
}
}
#endif
}
#endif
}