2025-08-22 21:50 UTC+0200 Przemyslaw Czerpak (druzus/at/poczta.onet.pl)
+ contrib/hbbmp/core.c
+ contrib/hbbmp/hbbmp.ch
+ contrib/hbbmp/hbbmp.h
+ contrib/hbbmp/hbbmp.hbc
+ contrib/hbbmp/hbbmp.hbp
+ contrib/hbbmp/hbbmp.hbx
+ contrib/hbbmp/readme.txt
+ contrib/hbbmp/tests/hbbmptst.prg
+ contrib/hbbmp/tests/hbmk.hbm
+ added new BMP image library for Harbour
; HBBMP is small library for Harbour dedicated to create and modify
BMP images. It has not any 3rd party libs dependencies.
See readme.txt for more information
+ contrib/hbzebra/tests/bmp.prg
+ added example code which uses HBBMP as backend for HBZEBRA and
creates BMP images with generated barcodes.
This commit is contained in:
@@ -7,6 +7,25 @@
|
||||
Entries may not always be in chronological/commit order.
|
||||
See license at the end of file. */
|
||||
|
||||
2025-08-22 21:50 UTC+0200 Przemyslaw Czerpak (druzus/at/poczta.onet.pl)
|
||||
+ contrib/hbbmp/core.c
|
||||
+ contrib/hbbmp/hbbmp.ch
|
||||
+ contrib/hbbmp/hbbmp.h
|
||||
+ contrib/hbbmp/hbbmp.hbc
|
||||
+ contrib/hbbmp/hbbmp.hbp
|
||||
+ contrib/hbbmp/hbbmp.hbx
|
||||
+ contrib/hbbmp/readme.txt
|
||||
+ contrib/hbbmp/tests/hbbmptst.prg
|
||||
+ contrib/hbbmp/tests/hbmk.hbm
|
||||
+ added new BMP image library for Harbour
|
||||
; HBBMP is small library for Harbour dedicated to create and modify
|
||||
BMP images. It has not any 3rd party libs dependencies.
|
||||
See readme.txt for more information
|
||||
|
||||
+ contrib/hbzebra/tests/bmp.prg
|
||||
+ added example code which uses HBBMP as backend for HBZEBRA and
|
||||
creates BMP images with generated barcodes.
|
||||
|
||||
2025-08-22 12:00 UTC+0200 Przemyslaw Czerpak (druzus/at/poczta.onet.pl)
|
||||
* contrib/hbzebra/coredraw.c
|
||||
* contrib/hbzebra/hbzebra.hbx
|
||||
|
||||
876
contrib/hbbmp/core.c
Normal file
876
contrib/hbbmp/core.c
Normal file
@@ -0,0 +1,876 @@
|
||||
/*
|
||||
* BMP image library for Harbour
|
||||
*
|
||||
* Copyright 2025 Przemyslaw Czerpak <druzus /at/ priv.onet.pl>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file LICENSE.txt. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA (or visit https://www.gnu.org/licenses/).
|
||||
*
|
||||
* As a special exception, the Harbour Project gives permission for
|
||||
* additional uses of the text contained in its release of Harbour.
|
||||
*
|
||||
* The exception is that, if you link the Harbour libraries with other
|
||||
* files to produce an executable, this does not by itself cause the
|
||||
* resulting executable to be covered by the GNU General Public License.
|
||||
* Your use of that executable is in no way restricted on account of
|
||||
* linking the Harbour library code into it.
|
||||
*
|
||||
* This exception does not however invalidate any other reasons why
|
||||
* the executable file might be covered by the GNU General Public License.
|
||||
*
|
||||
* This exception applies only to the code released by the Harbour
|
||||
* Project under the name Harbour. If you copy code from other
|
||||
* Harbour Project or Free Software Foundation releases into a copy of
|
||||
* Harbour, as the General Public License permits, the exception does
|
||||
* not apply to the code that you add in this way. To avoid misleading
|
||||
* anyone as to the status of such modified files, you must delete
|
||||
* this exception notice from them.
|
||||
*
|
||||
* If you write modifications of your own for Harbour, it is your choice
|
||||
* whether to permit this exception to apply to your modifications.
|
||||
* If you do not wish that, delete this exception notice.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hbbmp.h"
|
||||
#include "hbapi.h"
|
||||
#include "hbapifs.h"
|
||||
#include "hbapierr.h"
|
||||
|
||||
void hb_bmp_free( PHB_BMPINFO pBMP )
|
||||
{
|
||||
if( pBMP->data )
|
||||
hb_xfree( pBMP->data );
|
||||
hb_xfree( pBMP );
|
||||
}
|
||||
|
||||
PHB_BMPINFO hb_bmp_new( int width, int height, int depth, int dpi, int * piError )
|
||||
{
|
||||
PHB_BMPINFO pBMP = NULL;
|
||||
HB_BOOL fromtop = height < 0;
|
||||
|
||||
if( piError )
|
||||
*piError = 0;
|
||||
|
||||
if( fromtop )
|
||||
height = -height;
|
||||
if( dpi == 0 )
|
||||
dpi = HB_BMP_DPI_DEFAULT;
|
||||
|
||||
if( width < 1 || height < 1 || width > 0x10000 || height > 0x10000 )
|
||||
{
|
||||
if( piError )
|
||||
*piError = HB_BMP_ERROR_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
int rowlen;
|
||||
|
||||
switch( depth )
|
||||
{
|
||||
case 0:
|
||||
depth = HB_BMP_DEPTH_DEFAULT;
|
||||
/* fallthrough */
|
||||
case 1:
|
||||
/* 2 color depth BMP is not officially supported,
|
||||
uncomment line below if you need it */
|
||||
/* case 2: */
|
||||
case 4:
|
||||
case 8:
|
||||
case 16:
|
||||
case 24:
|
||||
case 32:
|
||||
break;
|
||||
default:
|
||||
if( piError )
|
||||
*piError = HB_BMP_ERROR_DEPTH;
|
||||
return NULL;
|
||||
}
|
||||
pBMP = ( PHB_BMPINFO ) hb_xgrabz( sizeof( HB_BMPINFO ) );
|
||||
rowlen = ( ( width * depth + 31 ) >> 5 ) << 2;
|
||||
|
||||
pBMP->error = 0;
|
||||
pBMP->width = width;
|
||||
pBMP->height = height;
|
||||
pBMP->dpi = dpi;
|
||||
pBMP->depth = depth;
|
||||
pBMP->clrused = 0;
|
||||
pBMP->rowlen = rowlen;
|
||||
pBMP->fromtop = fromtop;
|
||||
pBMP->data = ( HB_BYTE * ) hb_xgrabz( rowlen * height );
|
||||
}
|
||||
return pBMP;
|
||||
}
|
||||
|
||||
PHB_BMPINFO hb_bmp_copy( PHB_BMPINFO pBMP )
|
||||
{
|
||||
PHB_BMPINFO pBMPnew = ( PHB_BMPINFO ) hb_xgrab( sizeof( HB_BMPINFO ) );
|
||||
|
||||
memcpy( pBMPnew, pBMP, sizeof( HB_BMPINFO ) );
|
||||
pBMPnew->data = ( HB_BYTE * ) hb_xgrab( pBMP->rowlen * pBMP->height );
|
||||
memcpy( pBMPnew->data, pBMP->data, pBMP->rowlen * pBMP->height );
|
||||
|
||||
pBMPnew->error = 0;
|
||||
|
||||
return pBMPnew;
|
||||
}
|
||||
|
||||
HB_BYTE * hb_bmp_bitmapptr( PHB_BMPINFO pBMP, HB_SIZE * pnSize )
|
||||
{
|
||||
if( pnSize )
|
||||
*pnSize = pBMP->rowlen * pBMP->height;
|
||||
return pBMP->data;
|
||||
}
|
||||
|
||||
void hb_bmp_seterror( PHB_BMPINFO pBMP, int error )
|
||||
{
|
||||
pBMP->error = error;
|
||||
}
|
||||
|
||||
int hb_bmp_error( PHB_BMPINFO pBMP )
|
||||
{
|
||||
return pBMP->error;
|
||||
}
|
||||
|
||||
int hb_bmp_width( PHB_BMPINFO pBMP )
|
||||
{
|
||||
return pBMP->width;
|
||||
}
|
||||
|
||||
int hb_bmp_height( PHB_BMPINFO pBMP )
|
||||
{
|
||||
return pBMP->height;
|
||||
}
|
||||
|
||||
int hb_bmp_depth( PHB_BMPINFO pBMP )
|
||||
{
|
||||
return pBMP->depth;
|
||||
}
|
||||
|
||||
HB_MAXINT hb_bmp_color( PHB_BMPINFO pBMP, int r, int g, int b, int a )
|
||||
{
|
||||
HB_MAXINT iColor = -1;
|
||||
|
||||
pBMP->error = 0;
|
||||
|
||||
if( ( r & 0xFF ) != r || ( g & 0xFF ) != g ||
|
||||
( b & 0xFF ) != b || ( a & 0xFF ) != a )
|
||||
pBMP->error = HB_BMP_ERROR_COLORVALUE;
|
||||
else if( pBMP->depth == 32 )
|
||||
iColor = b | ( g << 8 ) | ( r << 16 ) | ( a << 24 );
|
||||
else if( pBMP->depth == 24 )
|
||||
iColor = b | ( g << 8 ) | ( r << 16 );
|
||||
/* 16 color depth does not have RGB mapping in BMP format
|
||||
* color indexes have to be used directly and their RGB
|
||||
* values defined outside BMP structure
|
||||
*/
|
||||
else if( pBMP->depth <= 8 )
|
||||
{
|
||||
int i;
|
||||
for( i = 0; i < pBMP->clrused; ++i )
|
||||
{
|
||||
if( pBMP->palette[ i ].blue == b &&
|
||||
pBMP->palette[ i ].green == g &&
|
||||
pBMP->palette[ i ].red == r &&
|
||||
pBMP->palette[ i ].alpha == a )
|
||||
{
|
||||
iColor = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( iColor == -1 )
|
||||
{
|
||||
if( pBMP->clrused < 1 << pBMP->depth )
|
||||
{
|
||||
iColor = pBMP->clrused++;
|
||||
pBMP->palette[ iColor ].blue = b;
|
||||
pBMP->palette[ iColor ].green = g;
|
||||
pBMP->palette[ iColor ].red = r;
|
||||
pBMP->palette[ iColor ].alpha = a;
|
||||
}
|
||||
else
|
||||
pBMP->error = HB_BMP_ERROR_PALETTEFULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
pBMP->error = HB_BMP_ERROR_COLORINDEX;
|
||||
|
||||
return iColor;
|
||||
}
|
||||
|
||||
HB_BOOL hb_bmp_color2rgb( PHB_BMPINFO pBMP, HB_MAXINT clr, int * r, int * g, int * b, int * a )
|
||||
{
|
||||
pBMP->error = HB_BMP_ERROR_COLORINDEX;
|
||||
* b = * g = * r = * a = -1;
|
||||
|
||||
if( clr >= 0 && clr <= HB_LL( 0xFFFFFFFF ) )
|
||||
{
|
||||
switch( pBMP->depth )
|
||||
{
|
||||
case 1:
|
||||
case 2:
|
||||
case 4:
|
||||
case 8:
|
||||
if( clr < ( HB_MAXINT ) pBMP->clrused )
|
||||
{
|
||||
* b = pBMP->palette[ clr ].blue;
|
||||
* g = pBMP->palette[ clr ].green;
|
||||
* r = pBMP->palette[ clr ].red;
|
||||
* a = pBMP->palette[ clr ].alpha;
|
||||
pBMP->error = 0;
|
||||
}
|
||||
break;
|
||||
/* 16 color depth does not have RGB mapping in BMP format
|
||||
* color indexes have to be used directly and their RGB
|
||||
* values defined outside BMP structure
|
||||
*/
|
||||
case 24:
|
||||
/* ignore alpha channel */
|
||||
clr &= 0xFFFFFF;
|
||||
/* fallthrough */
|
||||
case 32:
|
||||
* b = clr & 0xFF;
|
||||
* g = ( clr >> 8 ) & 0xFF;
|
||||
* r = ( clr >> 16 ) & 0xFF;
|
||||
* a = ( clr >> 24 ) & 0xFF;
|
||||
pBMP->error = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return pBMP->error == 0;
|
||||
}
|
||||
|
||||
HB_BOOL hb_bmp_putpixel( PHB_BMPINFO pBMP, int x, int y, HB_MAXINT clr )
|
||||
{
|
||||
if( x < 0 || x >= pBMP->width || y < 0 || y >= pBMP->height )
|
||||
pBMP->error = HB_BMP_ERROR_RANGE;
|
||||
else if( clr < 0 || ( clr > ( pBMP->depth <= 8 ? pBMP->clrused :
|
||||
( pBMP->depth == 16 ? 0xFFFF :
|
||||
HB_LL( 0xFFFFFFFF ) ) ) ) )
|
||||
pBMP->error = HB_BMP_ERROR_COLORINDEX;
|
||||
else
|
||||
{
|
||||
int index = ( ( ( pBMP->fromtop ? y : pBMP->height - y - 1 ) *
|
||||
pBMP->rowlen ) << 3 ) + ( x * pBMP->depth );
|
||||
HB_BYTE * ptr = &pBMP->data[ index >> 3 ];
|
||||
int shift = -1;
|
||||
|
||||
switch( pBMP->depth )
|
||||
{
|
||||
case 1:
|
||||
shift = 0x07 ^ ( x & 0x07 );
|
||||
break;
|
||||
case 2:
|
||||
shift = ( 0x03 ^ ( x & 0x03 ) ) << 1;
|
||||
break;
|
||||
case 4:
|
||||
shift = ( 0x01 ^ ( x & 0x01 ) ) << 2;
|
||||
break;
|
||||
case 8:
|
||||
*ptr = ( HB_BYTE ) clr;
|
||||
break;
|
||||
case 16:
|
||||
HB_PUT_LE_UINT16( ptr, clr );
|
||||
break;
|
||||
case 24:
|
||||
HB_PUT_LE_UINT24( ptr, clr );
|
||||
break;
|
||||
case 32:
|
||||
HB_PUT_LE_UINT32( ptr, clr );
|
||||
break;
|
||||
}
|
||||
if( shift >= 0 )
|
||||
*ptr = ( HB_BYTE ) ( ( *ptr & ~( ( ( 0x01 << pBMP->depth ) - 1 ) << shift ) ) | ( clr << shift ) );
|
||||
pBMP->error = 0;
|
||||
}
|
||||
return pBMP->error == 0;
|
||||
}
|
||||
|
||||
HB_MAXINT hb_bmp_getpixel( PHB_BMPINFO pBMP, int x, int y )
|
||||
{
|
||||
HB_MAXINT clr = -1;
|
||||
|
||||
if( x < 0 || x >= pBMP->width || y < 0 || y >= pBMP->height )
|
||||
pBMP->error = HB_BMP_ERROR_RANGE;
|
||||
else
|
||||
{
|
||||
int index = ( ( ( pBMP->fromtop ? y : pBMP->height - y - 1 ) *
|
||||
pBMP->rowlen ) << 3 ) + ( x * pBMP->depth );
|
||||
HB_BYTE * ptr = &pBMP->data[ index >> 3 ];
|
||||
int shift = -1;
|
||||
|
||||
switch( pBMP->depth )
|
||||
{
|
||||
case 1:
|
||||
shift = 0x07 ^ ( x & 0x07 );
|
||||
break;
|
||||
case 2:
|
||||
shift = ( 0x03 ^ ( x & 0x03 ) ) << 1;
|
||||
break;
|
||||
case 4:
|
||||
shift = ( 0x01 ^ ( x & 0x01 ) ) << 2;
|
||||
break;
|
||||
case 8:
|
||||
clr = *ptr;
|
||||
break;
|
||||
case 16:
|
||||
clr = HB_GET_LE_UINT16( ptr );
|
||||
break;
|
||||
case 24:
|
||||
clr = HB_GET_LE_UINT24( ptr );
|
||||
break;
|
||||
case 32:
|
||||
clr = HB_GET_LE_UINT32( ptr );
|
||||
break;
|
||||
}
|
||||
if( shift >= 0 )
|
||||
clr = ( *ptr & ( ( ( 0x01 << pBMP->depth ) - 1 ) << shift ) ) >> shift;
|
||||
pBMP->error = 0;
|
||||
}
|
||||
return clr;
|
||||
}
|
||||
|
||||
void hb_bmp_line( PHB_BMPINFO pBMP, int x1, int y1, int x2, int y2, HB_MAXINT clr )
|
||||
{
|
||||
if( clr < 0 || ( clr > ( pBMP->depth <= 8 ? pBMP->clrused :
|
||||
( pBMP->depth == 16 ? 0xFFFF :
|
||||
HB_LL( 0xFFFFFFFF ) ) ) ) )
|
||||
pBMP->error = HB_BMP_ERROR_COLORINDEX;
|
||||
else
|
||||
{
|
||||
double dd;
|
||||
int dx, dy, x, y;
|
||||
|
||||
dx = x1 >= x2 ? x1 - x2 : x2 - x1;
|
||||
dy = y1 >= y2 ? y1 - y2 : y2 - y1;
|
||||
|
||||
if( dx >= dy || dy == 0 ? x1 > x2 : y1 > y2 || dx == 0 )
|
||||
{
|
||||
int nn = x1;
|
||||
x1 = x2;
|
||||
x2 = nn;
|
||||
nn = y1;
|
||||
y1 = y2;
|
||||
y2 = nn;
|
||||
}
|
||||
|
||||
if( dy == 0 )
|
||||
{
|
||||
for( x = HB_MAX( x1, 0 ); x <= x2 && x < pBMP->width; ++x )
|
||||
hb_bmp_putpixel( pBMP, x, y1, clr );
|
||||
}
|
||||
else if( dx == 0 )
|
||||
{
|
||||
for( y = HB_MAX( y1, 0 ); y <= y2 && y < pBMP->height; ++y )
|
||||
hb_bmp_putpixel( pBMP, x1, y, clr );
|
||||
}
|
||||
else if( dx >= dy )
|
||||
{
|
||||
dd = ( double ) ( y2 - y1 ) / ( x2 - x1 );
|
||||
for( x = HB_MAX( x1, 0 ); x <= x2 && x < pBMP->width; ++x )
|
||||
hb_bmp_putpixel( pBMP, x, ( int ) ( dd * ( x - x1 ) + 0.50001 ) + y1, clr );
|
||||
}
|
||||
else
|
||||
{
|
||||
dd = ( double ) ( x2 - x1 ) / ( y2 - y1 );
|
||||
for( y = HB_MAX( y1, 0 ); y <= y2 && y < pBMP->height; ++y )
|
||||
hb_bmp_putpixel( pBMP, ( int ) ( dd * ( y - y1 ) + 0.50001 ) + x1, y, clr );
|
||||
}
|
||||
pBMP->error = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void hb_bmp_rect( PHB_BMPINFO pBMP, int x, int y, int width, int height, HB_MAXINT clr, HB_BOOL fFill )
|
||||
{
|
||||
if( width < 0 )
|
||||
{
|
||||
x += width;
|
||||
width = - width;
|
||||
}
|
||||
if( height < 0 )
|
||||
{
|
||||
y += height;
|
||||
height = - height;
|
||||
}
|
||||
if( clr < 0 || ( clr > ( pBMP->depth <= 8 ? pBMP->clrused :
|
||||
( pBMP->depth == 16 ? 0xFFFF :
|
||||
HB_LL( 0xFFFFFFFF ) ) ) ) )
|
||||
pBMP->error = HB_BMP_ERROR_COLORINDEX;
|
||||
else if( width < 0 || height < 0 ||
|
||||
x >= pBMP->width || y >= pBMP->height ||
|
||||
x + width < 0 || y + height < 0 )
|
||||
pBMP->error = HB_BMP_ERROR_RANGE;
|
||||
else
|
||||
{
|
||||
int x1, y1, x2, y2, xx, yy;
|
||||
|
||||
x1 = HB_MAX( x, 0 );
|
||||
y1 = HB_MAX( y, 0 );
|
||||
x2 = x1 + width >= pBMP->width ? pBMP->width : x1 + width;
|
||||
y2 = y1 + height >= pBMP->height ? pBMP->height : y1 + height;
|
||||
if( fFill )
|
||||
{
|
||||
for( xx = x1; xx < x2; ++xx )
|
||||
{
|
||||
for( yy = y1; yy < y2; ++yy )
|
||||
hb_bmp_putpixel( pBMP, xx, yy, clr );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( y >= 0 )
|
||||
{
|
||||
for( xx = x1; xx < x2; ++xx )
|
||||
hb_bmp_putpixel( pBMP, xx, y, clr );
|
||||
}
|
||||
if( x >= 0 )
|
||||
{
|
||||
for( yy = y1; yy < y2; ++yy )
|
||||
hb_bmp_putpixel( pBMP, x, yy, clr );
|
||||
}
|
||||
if( y2 < pBMP->height )
|
||||
{
|
||||
for( xx = x1; xx < x2; ++xx )
|
||||
hb_bmp_putpixel( pBMP, xx, y2 - 1, clr );
|
||||
}
|
||||
if( x2 < pBMP->width )
|
||||
{
|
||||
for( yy = y1; yy < y2; ++yy )
|
||||
hb_bmp_putpixel( pBMP, x2 - 1, yy, clr );
|
||||
}
|
||||
}
|
||||
pBMP->error = 0;
|
||||
}
|
||||
}
|
||||
|
||||
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 )
|
||||
iError = HB_BMP_ERROR_CORRUPT;
|
||||
else
|
||||
{
|
||||
PHB_BMPHEADER header = ( PHB_BMPHEADER ) data;
|
||||
if( header->signature[ 0 ] != 'B' || header->signature[ 1 ] != 'M' )
|
||||
iError = HB_BMP_ERROR_CORRUPT;
|
||||
else
|
||||
{
|
||||
/* file_size in BMP headers is often wrong so I do not check it
|
||||
* int file_size = HB_GET_LE_INT32( header->file_size );
|
||||
*/
|
||||
int bmpoffset = HB_GET_LE_INT32( header->bmpoffset ),
|
||||
headersize = HB_GET_LE_INT32( header->headersize ),
|
||||
width = 0, height = 0, depth = 0, rowlen = 0, dpi = 0,
|
||||
clrused = 0, palette_bytes = 0;
|
||||
HB_BOOL fromtop;
|
||||
|
||||
if( size < ( HB_SIZE ) ( HB_BMP_FILEHEADER_SIZE +
|
||||
HB_BMP_INFOHEADER_MINSIZE + headersize ) )
|
||||
iError = HB_BMP_ERROR_CORRUPT;
|
||||
else if( headersize == 12 || headersize == 16 )
|
||||
{
|
||||
PHB_BMPOS2HEADER header_os2 = ( PHB_BMPOS2HEADER ) header->file_size;
|
||||
width = HB_GET_LE_UINT16( header_os2->width );
|
||||
height = HB_GET_LE_UINT16( header_os2->height );
|
||||
depth = HB_GET_LE_UINT16( header_os2->bitsperpixel );
|
||||
if( depth <= 8 )
|
||||
clrused = 0x01 << depth;
|
||||
dpi = HB_BMP_DPI_DEFAULT;
|
||||
palette_bytes = 3;
|
||||
if( depth != 1 && depth != 2 && depth != 4 && depth != 8 && depth != 24 )
|
||||
iError = HB_BMP_ERROR_CORRUPT;
|
||||
}
|
||||
else if( headersize == 40 || headersize == 52 || headersize == 56 ||
|
||||
headersize == 108 || headersize == 124 )
|
||||
{
|
||||
width = HB_GET_LE_INT32( header->width );
|
||||
height = HB_GET_LE_INT32( header->height );
|
||||
dpi = ( int ) ( ( double ) HB_GET_LE_INT32( header->hresolution ) / 39.3701 + 0.5 );
|
||||
depth = HB_GET_LE_UINT16( header->bitsperpixel );
|
||||
if( depth <= 8 )
|
||||
{
|
||||
clrused = HB_GET_LE_INT32( header->clrused );
|
||||
if( clrused == 0 )
|
||||
clrused = 0x01 << depth;
|
||||
}
|
||||
palette_bytes = 4;
|
||||
if( ( depth != 1 && depth != 2 && depth != 4 && depth != 8 &&
|
||||
depth != 16 && depth != 24 && depth != 32 ) )
|
||||
iError = HB_BMP_ERROR_CORRUPT;
|
||||
else if( HB_GET_LE_INT32( header->compression ) != 0 )
|
||||
iError = HB_BMP_ERROR_UNSUPPORTED;
|
||||
}
|
||||
else
|
||||
iError = HB_BMP_ERROR_CORRUPT;
|
||||
|
||||
fromtop = height < 0;
|
||||
if( fromtop )
|
||||
height = -height;
|
||||
|
||||
rowlen = ( ( width * depth + 31 ) >> 5 ) << 2;
|
||||
if( iError == 0 &&
|
||||
( HB_BMP_FILEHEADER_SIZE + headersize + clrused * palette_bytes > bmpoffset ||
|
||||
( HB_SIZE ) bmpoffset + rowlen * height > size ) )
|
||||
iError = HB_BMP_ERROR_CORRUPT;
|
||||
else if( iError == 0 )
|
||||
{
|
||||
pBMP = hb_bmp_new( width, fromtop ? -height : height, depth, dpi, &iError );
|
||||
if( pBMP )
|
||||
{
|
||||
const HB_BYTE * ptr = data + HB_BMP_FILEHEADER_SIZE + headersize;
|
||||
int idx, unused = 0;
|
||||
for( idx = 0; idx < clrused; ++idx )
|
||||
{
|
||||
pBMP->palette[ idx ].blue = *ptr++;
|
||||
pBMP->palette[ idx ].green = *ptr++;
|
||||
pBMP->palette[ idx ].red = *ptr++;
|
||||
if( palette_bytes == 4 )
|
||||
pBMP->palette[ idx ].alpha = *ptr++;
|
||||
if( pBMP->palette[ idx ].blue == 0 &&
|
||||
pBMP->palette[ idx ].green == 0 &&
|
||||
pBMP->palette[ idx ].red == 0 &&
|
||||
pBMP->palette[ idx ].alpha == 0 )
|
||||
++unused;
|
||||
else if( unused > 1 )
|
||||
unused = 1;
|
||||
}
|
||||
if( unused > 1 )
|
||||
clrused -= unused - 1;
|
||||
pBMP->clrused = clrused;
|
||||
memcpy( pBMP->data, data + bmpoffset, rowlen * height );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if( piError )
|
||||
*piError = iError;
|
||||
|
||||
return pBMP;
|
||||
}
|
||||
|
||||
HB_BYTE * hb_bmp_encode( PHB_BMPINFO pBMP, HB_SIZE * pnSize )
|
||||
{
|
||||
int clrused, bmpoffset, bmpsize, file_size, idx, height, dpi;
|
||||
PHB_BMPHEADER header;
|
||||
HB_BYTE * data, * ptr;
|
||||
|
||||
/* always allocate area for whole palette for programs which
|
||||
* do not check number of used colors in BMP header
|
||||
*/
|
||||
clrused = pBMP->depth > 8 ? 0 : 0x01 << pBMP->depth;
|
||||
/* 4 byte alignment is not required inside file */
|
||||
/* bmpoffset = ( sizeof( HB_BMPHEADER ) + clrused * 4 + 3 ) & ~0x03; */
|
||||
bmpoffset = sizeof( HB_BMPHEADER ) + clrused * 4;
|
||||
bmpsize = pBMP->rowlen * pBMP->height;
|
||||
file_size = bmpoffset + bmpsize;
|
||||
height = pBMP->fromtop ? -pBMP->height : pBMP->height;
|
||||
dpi = ( int ) ( HB_BMP_INCHES_PER_METRE * pBMP->dpi + 0.5 );
|
||||
|
||||
/* when clrused is set in BMP header to value different then 0 or
|
||||
* palette size some BMP viewers cannot show BMP correctly so
|
||||
* I decided to comment code below and always store 0
|
||||
*/
|
||||
/*
|
||||
if( clrused > 0 )
|
||||
clrused = clrused > pBMP->clrused ? pBMP->clrused : 0;
|
||||
*/
|
||||
clrused = 0;
|
||||
|
||||
data = ( HB_BYTE * ) hb_xgrab( file_size + 1 );
|
||||
memset( data, 0, sizeof( HB_BMPHEADER ) );
|
||||
|
||||
header = ( PHB_BMPHEADER ) data;
|
||||
header->signature[ 0 ] = 'B';
|
||||
header->signature[ 1 ] = 'M';
|
||||
HB_PUT_LE_UINT32( header->file_size, file_size );
|
||||
HB_PUT_LE_UINT16( header->reserved1, 0 );
|
||||
HB_PUT_LE_UINT16( header->reserved2, 0 );
|
||||
HB_PUT_LE_UINT32( header->bmpoffset, bmpoffset );
|
||||
HB_PUT_LE_UINT32( header->headersize, sizeof( HB_BMPHEADER ) - HB_BMP_FILEHEADER_SIZE );
|
||||
HB_PUT_LE_UINT32( header->width, pBMP->width );
|
||||
HB_PUT_LE_UINT32( header->height, height );
|
||||
HB_PUT_LE_UINT16( header->planes, 1 );
|
||||
HB_PUT_LE_UINT16( header->bitsperpixel, pBMP->depth );
|
||||
HB_PUT_LE_UINT32( header->compression, 0 );
|
||||
HB_PUT_LE_UINT32( header->bitmapsize, bmpsize );
|
||||
HB_PUT_LE_UINT32( header->hresolution, dpi );
|
||||
HB_PUT_LE_UINT32( header->vresolution, dpi );
|
||||
HB_PUT_LE_UINT32( header->clrused, clrused );
|
||||
HB_PUT_LE_UINT32( header->clrimportant, 0 );
|
||||
|
||||
ptr = data + sizeof( HB_BMPHEADER );
|
||||
for( idx = 0; idx < pBMP->clrused; ++idx )
|
||||
{
|
||||
*ptr++ = pBMP->palette[ idx ].blue;
|
||||
*ptr++ = pBMP->palette[ idx ].green;
|
||||
*ptr++ = pBMP->palette[ idx ].red;
|
||||
*ptr++ = pBMP->palette[ idx ].alpha;
|
||||
}
|
||||
while( ptr < data + bmpoffset )
|
||||
*ptr++ = 0;
|
||||
memcpy( data + bmpoffset, pBMP->data, pBMP->rowlen * pBMP->height );
|
||||
|
||||
data[ file_size ] = 0;
|
||||
*pnSize = file_size;
|
||||
|
||||
pBMP->error = 0;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/* Collectable pointer support */
|
||||
|
||||
static HB_GARBAGE_FUNC( hb_bmp_destructor )
|
||||
{
|
||||
PHB_BMPINFO * pBMPptr = ( PHB_BMPINFO * ) Cargo;
|
||||
|
||||
if( *pBMPptr )
|
||||
{
|
||||
hb_bmp_free( *pBMPptr );
|
||||
*pBMPptr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static const HB_GC_FUNCS s_gcBMPfuncs =
|
||||
{
|
||||
hb_bmp_destructor,
|
||||
hb_gcDummyMark
|
||||
};
|
||||
|
||||
void hb_bmpParamFree( int iParam )
|
||||
{
|
||||
PHB_BMPINFO * pBMPPtr = ( PHB_BMPINFO * ) hb_parptrGC( &s_gcBMPfuncs, iParam );
|
||||
|
||||
if( pBMPPtr && *pBMPPtr )
|
||||
{
|
||||
hb_bmp_free( *pBMPPtr );
|
||||
*pBMPPtr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
PHB_BMPINFO hb_bmpParam( int iParam, HB_BOOL fError )
|
||||
{
|
||||
PHB_BMPINFO * pBMPPtr = ( PHB_BMPINFO * ) hb_parptrGC( &s_gcBMPfuncs, iParam );
|
||||
|
||||
if( pBMPPtr && *pBMPPtr )
|
||||
return *pBMPPtr;
|
||||
else if( fError )
|
||||
hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void hb_bmpReturn( PHB_BMPINFO pBMP )
|
||||
{
|
||||
if( pBMP )
|
||||
{
|
||||
PHB_BMPINFO * pBMPPtr = ( PHB_BMPINFO * )
|
||||
hb_gcAllocate( sizeof( PHB_BMPINFO ), &s_gcBMPfuncs );
|
||||
*pBMPPtr = pBMP;
|
||||
hb_retptrGC( pBMPPtr );
|
||||
}
|
||||
else
|
||||
hb_ret();
|
||||
}
|
||||
|
||||
/* PRG functions */
|
||||
|
||||
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 ),
|
||||
&iError );
|
||||
hb_storni( iError, 5 );
|
||||
hb_bmpReturn( pBMP );
|
||||
}
|
||||
|
||||
HB_FUNC( HB_BMP_COPY )
|
||||
{
|
||||
PHB_BMPINFO pBMP = hb_bmpParam( 1, HB_TRUE );
|
||||
|
||||
if( pBMP )
|
||||
pBMP = hb_bmp_copy( pBMP );
|
||||
|
||||
hb_bmpReturn( pBMP );
|
||||
}
|
||||
|
||||
HB_FUNC( HB_BMP_DECODE )
|
||||
{
|
||||
const char * data = hb_parc( 1 );
|
||||
if( data )
|
||||
{
|
||||
int iError = 0;
|
||||
PHB_BMPINFO pBMP = hb_bmp_decode( ( const HB_BYTE * ) data, hb_parclen( 1 ), &iError );
|
||||
hb_storni( iError, 2 );
|
||||
hb_bmpReturn( pBMP );
|
||||
}
|
||||
else
|
||||
hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
|
||||
}
|
||||
|
||||
HB_FUNC( HB_BMP_ENCODE )
|
||||
{
|
||||
PHB_BMPINFO pBMP = hb_bmpParam( 1, HB_TRUE );
|
||||
|
||||
if( pBMP )
|
||||
{
|
||||
HB_SIZE size;
|
||||
HB_BYTE * data = hb_bmp_encode( pBMP, &size );
|
||||
|
||||
hb_retclen_buffer( ( char * ) data, size );
|
||||
}
|
||||
}
|
||||
|
||||
HB_FUNC( HB_BMP_FREE )
|
||||
{
|
||||
hb_bmpParamFree( 1 );
|
||||
}
|
||||
|
||||
HB_FUNC( HB_BMP_ERROR )
|
||||
{
|
||||
PHB_BMPINFO pBMP = hb_bmpParam( 1, HB_TRUE );
|
||||
|
||||
if( pBMP )
|
||||
hb_retni( hb_bmp_error( pBMP ) );
|
||||
}
|
||||
|
||||
HB_FUNC( HB_BMP_WIDTH )
|
||||
{
|
||||
PHB_BMPINFO pBMP = hb_bmpParam( 1, HB_TRUE );
|
||||
|
||||
if( pBMP )
|
||||
hb_retni( hb_bmp_width( pBMP ) );
|
||||
}
|
||||
|
||||
HB_FUNC( HB_BMP_HEIGHT )
|
||||
{
|
||||
PHB_BMPINFO pBMP = hb_bmpParam( 1, HB_TRUE );
|
||||
|
||||
if( pBMP )
|
||||
hb_retni( hb_bmp_height( pBMP ) );
|
||||
}
|
||||
|
||||
HB_FUNC( HB_BMP_DEPTH )
|
||||
{
|
||||
PHB_BMPINFO pBMP = hb_bmpParam( 1, HB_TRUE );
|
||||
|
||||
if( pBMP )
|
||||
hb_retni( hb_bmp_depth( pBMP ) );
|
||||
}
|
||||
|
||||
HB_FUNC( HB_BMP_COLOR )
|
||||
{
|
||||
PHB_BMPINFO pBMP = hb_bmpParam( 1, HB_TRUE );
|
||||
|
||||
if( pBMP )
|
||||
hb_retnint( hb_bmp_color( pBMP, hb_parni( 2 ), hb_parni( 3 ), hb_parni( 4 ), hb_parni( 5 ) ) );
|
||||
}
|
||||
|
||||
HB_FUNC( HB_BMP_COLOR2RGB )
|
||||
{
|
||||
PHB_BMPINFO pBMP = hb_bmpParam( 1, HB_TRUE );
|
||||
|
||||
if( pBMP )
|
||||
{
|
||||
int r, g, b, a;
|
||||
hb_retl( hb_bmp_color2rgb( pBMP, hb_parnint( 2 ), &r, &g, &b, &a ) );
|
||||
hb_storni( r, 3 );
|
||||
hb_storni( g, 4 );
|
||||
hb_storni( b, 5 );
|
||||
hb_storni( a, 6 );
|
||||
}
|
||||
}
|
||||
|
||||
HB_FUNC( HB_BMP_PUTPIXEL )
|
||||
{
|
||||
PHB_BMPINFO pBMP = hb_bmpParam( 1, HB_TRUE );
|
||||
|
||||
if( pBMP )
|
||||
hb_retl( hb_bmp_putpixel( pBMP, hb_parni( 2 ), hb_parni( hb_parni( 3 ) ), hb_parnint( 4 ) ) );
|
||||
}
|
||||
|
||||
HB_FUNC( HB_BMP_GETPIXEL )
|
||||
{
|
||||
PHB_BMPINFO pBMP = hb_bmpParam( 1, HB_TRUE );
|
||||
|
||||
if( pBMP )
|
||||
hb_retnint( hb_bmp_getpixel( pBMP, hb_parni( 2 ), hb_parni( hb_parni( 3 ) ) ) );
|
||||
}
|
||||
|
||||
HB_FUNC( HB_BMP_LINE )
|
||||
{
|
||||
PHB_BMPINFO pBMP = hb_bmpParam( 1, HB_TRUE );
|
||||
|
||||
if( pBMP )
|
||||
hb_bmp_line( pBMP, hb_parni( 2 ), hb_parni( 3 ), hb_parni( 4 ), hb_parni( 5 ), hb_parnint( 6 ) );
|
||||
}
|
||||
|
||||
HB_FUNC( HB_BMP_RECT )
|
||||
{
|
||||
PHB_BMPINFO pBMP = hb_bmpParam( 1, HB_TRUE );
|
||||
|
||||
if( pBMP )
|
||||
hb_bmp_rect( pBMP, hb_parni( 2 ), hb_parni( 3 ), hb_parni( 4 ), hb_parni( 5 ), hb_parnint( 6 ), hb_parldef( 7, HB_TRUE ) );
|
||||
}
|
||||
|
||||
HB_FUNC( HB_BMP_LOAD )
|
||||
{
|
||||
const char * pszFileName = hb_parc( 1 );
|
||||
|
||||
if( pszFileName )
|
||||
{
|
||||
int iError = 0;
|
||||
HB_SIZE size;
|
||||
HB_BYTE * data = hb_fileLoad( pszFileName, 0x1000000, &size );
|
||||
if( data )
|
||||
{
|
||||
PHB_BMPINFO pBMP = hb_bmp_decode( data, size, &iError );
|
||||
hb_bmpReturn( pBMP );
|
||||
hb_xfree( data );
|
||||
}
|
||||
else
|
||||
iError = HB_BMP_ERROR_FILEREAD;
|
||||
hb_storni( iError, 2 );
|
||||
}
|
||||
else
|
||||
hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
|
||||
}
|
||||
|
||||
HB_FUNC( HB_BMP_SAVE )
|
||||
{
|
||||
PHB_BMPINFO pBMP = hb_bmpParam( 1, HB_TRUE );
|
||||
|
||||
if( pBMP )
|
||||
{
|
||||
const char * pszFileName = hb_parc( 2 );
|
||||
|
||||
if( pszFileName )
|
||||
{
|
||||
HB_SIZE size;
|
||||
HB_BYTE * data = hb_bmp_encode( pBMP, &size );
|
||||
HB_BOOL fResult = hb_fileSave( pszFileName, data, size );
|
||||
if( ! fResult )
|
||||
hb_bmp_seterror( pBMP, HB_BMP_ERROR_FILEWRITE );
|
||||
hb_retl( fResult );
|
||||
hb_xfree( data );
|
||||
}
|
||||
else
|
||||
hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
|
||||
}
|
||||
}
|
||||
63
contrib/hbbmp/hbbmp.ch
Normal file
63
contrib/hbbmp/hbbmp.ch
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* BMP image library for Harbour
|
||||
*
|
||||
* Copyright 2025 Przemyslaw Czerpak <druzus /at/ priv.onet.pl>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file LICENSE.txt. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA (or visit https://www.gnu.org/licenses/).
|
||||
*
|
||||
* As a special exception, the Harbour Project gives permission for
|
||||
* additional uses of the text contained in its release of Harbour.
|
||||
*
|
||||
* The exception is that, if you link the Harbour libraries with other
|
||||
* files to produce an executable, this does not by itself cause the
|
||||
* resulting executable to be covered by the GNU General Public License.
|
||||
* Your use of that executable is in no way restricted on account of
|
||||
* linking the Harbour library code into it.
|
||||
*
|
||||
* This exception does not however invalidate any other reasons why
|
||||
* the executable file might be covered by the GNU General Public License.
|
||||
*
|
||||
* This exception applies only to the code released by the Harbour
|
||||
* Project under the name Harbour. If you copy code from other
|
||||
* Harbour Project or Free Software Foundation releases into a copy of
|
||||
* Harbour, as the General Public License permits, the exception does
|
||||
* not apply to the code that you add in this way. To avoid misleading
|
||||
* anyone as to the status of such modified files, you must delete
|
||||
* this exception notice from them.
|
||||
*
|
||||
* If you write modifications of your own for Harbour, it is your choice
|
||||
* whether to permit this exception to apply to your modifications.
|
||||
* If you do not wish that, delete this exception notice.
|
||||
*
|
||||
*/
|
||||
|
||||
/* NOTE: This file is also used by C code. */
|
||||
|
||||
#ifndef _HBBMP_CH_
|
||||
#define _HBBMP_CH_
|
||||
|
||||
#define HB_BMP_ERROR_SIZE 1
|
||||
#define HB_BMP_ERROR_DEPTH 2
|
||||
#define HB_BMP_ERROR_COLORVALUE 3
|
||||
#define HB_BMP_ERROR_PALETTEFULL 4
|
||||
#define HB_BMP_ERROR_COLORINDEX 5
|
||||
#define HB_BMP_ERROR_RANGE 6
|
||||
#define HB_BMP_ERROR_CORRUPT 7
|
||||
#define HB_BMP_ERROR_UNSUPPORTED 8
|
||||
#define HB_BMP_ERROR_FILEREAD 9
|
||||
#define HB_BMP_ERROR_FILEWRITE 10
|
||||
|
||||
#endif /* _HBBMP_CH_ */
|
||||
138
contrib/hbbmp/hbbmp.h
Normal file
138
contrib/hbbmp/hbbmp.h
Normal file
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* BMP image library for Harbour
|
||||
*
|
||||
* Copyright 2025 Przemyslaw Czerpak <druzus /at/ priv.onet.pl>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file LICENSE.txt. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA (or visit https://www.gnu.org/licenses/).
|
||||
*
|
||||
* As a special exception, the Harbour Project gives permission for
|
||||
* additional uses of the text contained in its release of Harbour.
|
||||
*
|
||||
* The exception is that, if you link the Harbour libraries with other
|
||||
* files to produce an executable, this does not by itself cause the
|
||||
* resulting executable to be covered by the GNU General Public License.
|
||||
* Your use of that executable is in no way restricted on account of
|
||||
* linking the Harbour library code into it.
|
||||
*
|
||||
* This exception does not however invalidate any other reasons why
|
||||
* the executable file might be covered by the GNU General Public License.
|
||||
*
|
||||
* This exception applies only to the code released by the Harbour
|
||||
* Project under the name Harbour. If you copy code from other
|
||||
* Harbour Project or Free Software Foundation releases into a copy of
|
||||
* Harbour, as the General Public License permits, the exception does
|
||||
* not apply to the code that you add in this way. To avoid misleading
|
||||
* anyone as to the status of such modified files, you must delete
|
||||
* this exception notice from them.
|
||||
*
|
||||
* If you write modifications of your own for Harbour, it is your choice
|
||||
* whether to permit this exception to apply to your modifications.
|
||||
* If you do not wish that, delete this exception notice.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _HBBMP_H_
|
||||
#define _HBBMP_H_
|
||||
|
||||
#include "hbdefs.h"
|
||||
#include "hbbmp.ch"
|
||||
|
||||
HB_EXTERN_BEGIN
|
||||
|
||||
#define HB_BMP_DEPTH_DEFAULT 1
|
||||
#define HB_BMP_DPI_DEFAULT 72
|
||||
#define HB_BMP_INCHES_PER_METRE 39.3701
|
||||
|
||||
#define HB_BMP_FILEHEADER_SIZE 14
|
||||
#define HB_BMP_INFOHEADER_MINSIZE 12
|
||||
|
||||
typedef struct _HB_BMPHEADER
|
||||
{
|
||||
HB_BYTE signature [ 2 ]; /* "BM" */
|
||||
HB_BYTE file_size [ 4 ]; /* the size of the BMP file in bytes */
|
||||
HB_BYTE reserved1 [ 2 ]; /* reserved, depends on the application, if created manually can be 0 */
|
||||
HB_BYTE reserved2 [ 2 ]; /* reserved, depends on the application, if created manually can be 0 */
|
||||
HB_BYTE bmpoffset [ 4 ]; /* the offset of the byte where the bitmap image data (pixel array) can be found */
|
||||
|
||||
HB_BYTE headersize [ 4 ]; /* the size of this header, in bytes (40) */
|
||||
HB_BYTE width [ 4 ]; /* the bitmap width in pixels (signed integer) */
|
||||
HB_BYTE height [ 4 ]; /* the bitmap height in pixels (signed integer) */
|
||||
HB_BYTE planes [ 2 ]; /* the number of color planes (must be 1) */
|
||||
HB_BYTE bitsperpixel[ 2 ]; /* the number of bits per pixel (color depth): 1, 4, 8, 16, 24 or 32 */
|
||||
HB_BYTE compression [ 4 ]; /* the compression method, 0 uncompressed */
|
||||
HB_BYTE bitmapsize [ 4 ]; /* the image size (the size of the raw bitmap data), 0 can be used for uncompressed bitmaps */
|
||||
HB_BYTE hresolution [ 4 ]; /* the horizontal resolution of the image (pixel per metre, signed integer) */
|
||||
HB_BYTE vresolution [ 4 ]; /* the vertical resolution of the image (pixel per metre, signed integer) */
|
||||
HB_BYTE clrused [ 4 ]; /* the number of colors in the color palette, or 0 to default to 2^n */
|
||||
HB_BYTE clrimportant[ 4 ]; /* the number of important colors used, or 0 when every color is important; generally ignored */
|
||||
} HB_BMPHEADER, * PHB_BMPHEADER;
|
||||
|
||||
typedef struct _HB_BMPOS2HEADER
|
||||
{
|
||||
HB_BYTE headersize [ 4 ]; /* the size of this header, in bytes (12) */
|
||||
HB_BYTE width [ 2 ]; /* the bitmap width in pixels (signed integer) */
|
||||
HB_BYTE height [ 2 ]; /* the bitmap height in pixels (signed integer) */
|
||||
HB_BYTE planes [ 2 ]; /* the number of color planes (must be 1) */
|
||||
HB_BYTE bitsperpixel[ 2 ]; /* the number of bits per pixel (color depth): 1, 4, 8, 16, 24 or 32 */
|
||||
} HB_BMPOS2HEADER, * PHB_BMPOS2HEADER;
|
||||
|
||||
typedef struct _HB_BMPPALETTEITM
|
||||
{
|
||||
HB_BYTE blue;
|
||||
HB_BYTE green;
|
||||
HB_BYTE red;
|
||||
HB_BYTE alpha;
|
||||
} HB_BMPPALETTEITM, * PHB_BMPPALETTEITM;
|
||||
|
||||
typedef struct _HB_BMPINFO
|
||||
{
|
||||
int error;
|
||||
int width;
|
||||
int height;
|
||||
int rowlen;
|
||||
HB_BOOL fromtop;
|
||||
int dpi;
|
||||
int depth;
|
||||
int clrused;
|
||||
HB_BMPPALETTEITM palette[ 256 ];
|
||||
HB_BYTE* data;
|
||||
} 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_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 );
|
||||
extern HB_EXPORT void hb_bmp_free( PHB_BMPINFO pBMP );
|
||||
extern HB_EXPORT HB_BYTE * hb_bmp_bitmapptr( PHB_BMPINFO pBMP, HB_SIZE * pnSize );
|
||||
extern HB_EXPORT void hb_bmp_seterror( PHB_BMPINFO pBMP, int error );
|
||||
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 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 );
|
||||
extern HB_EXPORT HB_MAXINT hb_bmp_getpixel( PHB_BMPINFO pBMP, int x, int y );
|
||||
extern HB_EXPORT void hb_bmp_line( PHB_BMPINFO pBMP, int x1, int y1, int x2, int y2, HB_MAXINT clr );
|
||||
extern HB_EXPORT void hb_bmp_rect( PHB_BMPINFO pBMP, int x, int y, int width, int height, HB_MAXINT clr, HB_BOOL fFill );
|
||||
|
||||
extern HB_EXPORT PHB_BMPINFO hb_bmpParam( int iParam, HB_BOOL fError );
|
||||
extern HB_EXPORT void hb_bmpParamFree( int iParam );
|
||||
extern HB_EXPORT void hb_bmpReturn( PHB_BMPINFO pBMP );
|
||||
|
||||
HB_EXTERN_END
|
||||
|
||||
#endif /* _HBBMP_H_ */
|
||||
5
contrib/hbbmp/hbbmp.hbc
Normal file
5
contrib/hbbmp/hbbmp.hbc
Normal file
@@ -0,0 +1,5 @@
|
||||
description=BMP image library for Harbour
|
||||
|
||||
incpaths=.
|
||||
|
||||
libs=${hb_name}
|
||||
10
contrib/hbbmp/hbbmp.hbp
Normal file
10
contrib/hbbmp/hbbmp.hbp
Normal file
@@ -0,0 +1,10 @@
|
||||
-hblib
|
||||
-inc
|
||||
|
||||
-o${hb_name}
|
||||
|
||||
-w3 -es2
|
||||
|
||||
${hb_name}.hbx
|
||||
|
||||
core.c
|
||||
46
contrib/hbbmp/hbbmp.hbx
Normal file
46
contrib/hbbmp/hbbmp.hbx
Normal file
@@ -0,0 +1,46 @@
|
||||
/* --------------------------------------------------------------------
|
||||
* NOTE: You can add manual override which functions to include or
|
||||
* exclude from automatically generated EXTERNAL/DYNAMIC list.
|
||||
* Syntax: // HB_FUNC_INCLUDE <func>
|
||||
* // HB_FUNC_EXCLUDE <func>
|
||||
*/
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* WARNING: Automatically generated code below. DO NOT EDIT! (except casing)
|
||||
* Regenerate using hbmk2 '-hbx=' option.
|
||||
*/
|
||||
|
||||
#ifndef __HBEXTERN_CH__HBBMP__
|
||||
#define __HBEXTERN_CH__HBBMP__
|
||||
|
||||
#if defined( __HBEXTREQ__ ) .OR. defined( __HBEXTERN__HBBMP__ANNOUNCE )
|
||||
ANNOUNCE __HBEXTERN__HBBMP__
|
||||
#endif
|
||||
|
||||
#if defined( __HBEXTREQ__ ) .OR. defined( __HBEXTERN__HBBMP__REQUEST )
|
||||
#command DYNAMIC <fncs,...> => EXTERNAL <fncs>
|
||||
#endif
|
||||
|
||||
DYNAMIC hb_bmp_color
|
||||
DYNAMIC hb_bmp_color2rgb
|
||||
DYNAMIC hb_bmp_copy
|
||||
DYNAMIC hb_bmp_decode
|
||||
DYNAMIC hb_bmp_depth
|
||||
DYNAMIC hb_bmp_encode
|
||||
DYNAMIC HB_BMP_ERROR
|
||||
DYNAMIC hb_bmp_free
|
||||
DYNAMIC hb_bmp_getpixel
|
||||
DYNAMIC hb_bmp_height
|
||||
DYNAMIC hb_bmp_line
|
||||
DYNAMIC hb_bmp_load
|
||||
DYNAMIC hb_bmp_new
|
||||
DYNAMIC hb_bmp_putpixel
|
||||
DYNAMIC hb_bmp_rect
|
||||
DYNAMIC hb_bmp_save
|
||||
DYNAMIC hb_bmp_width
|
||||
|
||||
#if defined( __HBEXTREQ__ ) .OR. defined( __HBEXTERN__HBBMP__REQUEST )
|
||||
#uncommand DYNAMIC <fncs,...> => EXTERNAL <fncs>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
110
contrib/hbbmp/readme.txt
Normal file
110
contrib/hbbmp/readme.txt
Normal file
@@ -0,0 +1,110 @@
|
||||
Copyright 2025 Przemyslaw Czerpak <druzus /at/ priv.onet.pl>
|
||||
|
||||
HBBMP is small library for Harbour dedicated to create and modify
|
||||
BMP images. It has not any 3rd party libs dependencies.
|
||||
It allows to create new images load existing ones and draw
|
||||
simple graphics primitives. I did not implement more advanced
|
||||
ones to not create math lib dependencies.
|
||||
Anyhow if someone is interesting in it then please implement it.
|
||||
For me this library is enough to work as backend for HBZEBRA
|
||||
library (excellent job of Mindaugas Kavaliauskas).
|
||||
I hope you will find it useful.
|
||||
|
||||
Only uncompressed BMP images are supported. When BMP file with
|
||||
compression flag is loaded then UNSUPPORTED error is set. This
|
||||
is the only case when this error can appear.
|
||||
|
||||
This library can work images using 1, 4, 8, 16, 24 and 32 color
|
||||
depth (all officially defined). It can work with 2-bit color depth
|
||||
(4 colors) BMP images which are not supported in official
|
||||
documentation. I blocked them inside hb_bmp_new() C function but
|
||||
if someone needs to create such BMP file then it's enough to
|
||||
uncomment one line with "case 2:" in this code.
|
||||
In BMP images with 1, 4 and 8 color depths number of colors is
|
||||
limited to 2, 16 and 256 colors. If limit exceeds or unsupported
|
||||
colors are defined then -1 is returned and error is set.
|
||||
In BMP images with 24 color depth alpha channel does not exists
|
||||
and this library silently ignores it when user pass it in color
|
||||
index.
|
||||
BMP images with 16-bit color depth does not have RGB color table
|
||||
so only arbitrary color indexes can be used and their real colors
|
||||
necessary for visualization have to be defined outside BMP file.
|
||||
BMP images color depth 24 and 32 do not use color table and color
|
||||
indexes are pure big endian RGB values with optional alpha channel
|
||||
which is ignored in case of 24 bit depth (0xAARRGGBB) so it's not
|
||||
necessary to allocate colors and programmer may use it directly,
|
||||
i.e. red := 0xFF0000
|
||||
The color and alpha must be in range from 0 to 255.
|
||||
When new BMP is created user can change the order in which rows
|
||||
are stored in memory and files from bottom-up to top-down setting
|
||||
the image height to negative value.
|
||||
|
||||
On PRG level the BMP image structure is represented as pointer
|
||||
item with attached destructor so when last variable (Harbour
|
||||
item) pointing to given BMP structure is cleared or overwritten
|
||||
(f.e. by pBMP := NIL) then destructor is called and BMP image
|
||||
structure removed from memory. Anyhow it's possible to force
|
||||
release operation by explicit call to hb_bmp_free().
|
||||
|
||||
|
||||
|
||||
The following PRG functions exist in HBBMP lib:
|
||||
|
||||
Create new BMP in memory, return pointer item or NIL on error.
|
||||
hb_bmp_new( <nWidth>, <nHeight>, [<nDepth>=1], [<nDPI>=72], [@<nError>] )
|
||||
=> <pBMP> | NIL (error indicator)
|
||||
|
||||
Make independent copy of memory BMP structures:
|
||||
hb_bmp_copy( <pBMPsrc> ) => <pBMPcopy>
|
||||
|
||||
Free BMP structure from memory:
|
||||
hb_bmp_free( <pBMP> ) => NIL
|
||||
|
||||
Load BMP image from file, return pointer item BMP image structure
|
||||
or NIL on error:
|
||||
hb_bmp_load( <cFileName>, [@<nError>] ) => <pBMP> | NIL
|
||||
|
||||
Save BMP image into file:
|
||||
hb_bmp_save( <pBMP>, <cFileName> ) => <lOK>
|
||||
|
||||
Create new BMP image structure from passed BMP file body, return
|
||||
pointer item BMP structure or NIL on error:
|
||||
hb_bmp_decode( <cBMPdata>, [@<nError>] ) => <pBMP> | NIL
|
||||
|
||||
Create BMP file body from BMP image structure:
|
||||
hb_bmp_encode( <pBMP> ) => <cBMPdata>
|
||||
|
||||
Get BMP width:
|
||||
hb_bmp_width( <pBMP> ) => <nWidth>
|
||||
|
||||
Get BMP height:
|
||||
hb_bmp_height( <pBMP> ) => <nHeight>
|
||||
|
||||
Get BMP color depth:
|
||||
hb_bmp_depth( <pBMP> ) => <nDepth>
|
||||
|
||||
Allocate new color or take index to existing one, or error -1
|
||||
is returned:
|
||||
hb_bmp_color( <pBMP>, <nRed>, <nGreen>, <nBlue>, <nAlpha> )
|
||||
=> <nColor> | -1
|
||||
|
||||
Convert color index to its RGB value, return .T. on success or
|
||||
.F. in case of error:
|
||||
hb_bmp_color2rgb( <pBMP>, <nColor>,
|
||||
@<nRed>, @<nGreen>, @<nBlue>, @<nAlpha> )
|
||||
=> <lOK>
|
||||
|
||||
Set pixel using given coordinates and color index:
|
||||
hb_bmp_putpixel( <pBMP>, <nX>, <nY>, <nColor> ) => <lOK>
|
||||
|
||||
Get color index of pixel at given coordinates, on error -1
|
||||
is returned:
|
||||
hb_bmp_getpixel( <pBMP>, <nX>, <nY> ) => <nColor>
|
||||
|
||||
Draw line from the given starting and ending points and color index:
|
||||
hb_bmp_line( <pBMP>, <nX1>, <nY1>, <nX2>, <nY2>, <nColor> ) => NIL
|
||||
|
||||
Draw rectangle (filled by default) using given coordinates, size and
|
||||
index color:
|
||||
hb_bmp_rect( <pBMP>, <nX>, <nY>, <nWidth>, <nHeight>,
|
||||
<nColor>, [<lFill>=.t.] ) => NIL
|
||||
75
contrib/hbbmp/tests/hbbmptst.prg
Normal file
75
contrib/hbbmp/tests/hbbmptst.prg
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2025 Przemyslaw Czerpak <druzus /at/ priv.onet.pl>
|
||||
*/
|
||||
|
||||
#define WIDTH 240
|
||||
#define HEIGHT 200
|
||||
|
||||
#xtranslate _out( <frm> [, <params,...>] ) => outstd( hb_strFormat( <frm>, <params> ) + hb_eol() )
|
||||
#xtranslate _err( <frm> [, <params,...>] ) => outerr( hb_strFormat( <frm>, <params> ) + hb_eol() )
|
||||
|
||||
REQUEST HB_GT_CGI_DEFAULT
|
||||
|
||||
PROCEDURE Main()
|
||||
LOCAL pBMP, depth, bkg, black, red, green, blue, last, fname, x1, x2, y1, y2, nn
|
||||
|
||||
FOR EACH depth IN { 1, 4, 8, 24, 32 }
|
||||
IF Empty( pBMP := hb_bmp_new( WIDTH, HEIGHT, depth ) )
|
||||
_err( "Cannot create BMP with DEPTH=%d", depth )
|
||||
ELSE
|
||||
_out( "Created BMP width=%d, height=%d, depth=%d", ;
|
||||
hb_bmp_width( pBMP ), hb_bmp_height( pBMP ), hb_bmp_depth( pBMP ) )
|
||||
bmp_color( pBMP, 255, 255, 255, 0, @bkg, @last )
|
||||
bmp_color( pBMP, 0, 0, 0, 0, @black, @last )
|
||||
bmp_color( pBMP, 127, 0, 0, 0, @red, @last )
|
||||
bmp_color( pBMP, 0, 127, 0, 0, @green, @last )
|
||||
bmp_color( pBMP, 0, 0, 127, 0, @blue, @last )
|
||||
|
||||
hb_bmp_rect( pBMP, 0, 0, WIDTH, HEIGHT, bkg )
|
||||
hb_bmp_rect( pBMP, 1, 1, WIDTH - 2, HEIGHT - 2, black, .f. )
|
||||
|
||||
hb_bmp_rect( pBMP, 20, 20, WIDTH - 40, HEIGHT - 40, black )
|
||||
hb_bmp_rect( pBMP, 30, 30, WIDTH - 60, HEIGHT - 60, bkg )
|
||||
x1 := 40 ; y1 := 40 ; x2 := WIDTH - 40 ; y2 := HEIGHT - 40
|
||||
hb_bmp_rect( pBMP, x1, y1, x2 - x1 + 1, y2 - y1 + 1, red, .f. )
|
||||
hb_bmp_line( pBMP, x1, y1, x2, y2, blue )
|
||||
hb_bmp_line( pBMP, x2, y1, x1, y2, green )
|
||||
hb_bmp_line( pBMP, x1 + x1, y1, x2 - x1, y2, blue )
|
||||
hb_bmp_line( pBMP, x2 - x1, y1, x1 + x1, y2, green )
|
||||
|
||||
FOR nn := 1 TO 5
|
||||
hb_bmp_rect( pBMP, 20 * nn, 8, 12, 8, { green, blue, red, black, green }[ nn ] )
|
||||
NEXT
|
||||
|
||||
fname := "test_" + strzero( depth, 2 ) + ".bmp"
|
||||
bmp_save( pBMP, fname )
|
||||
pBMP := NIL
|
||||
ENDIF
|
||||
_out( "" )
|
||||
NEXT
|
||||
RETURN
|
||||
|
||||
STATIC FUNCTION bmp_color( pBMP, r, g, b, a, /*@*/clr, /*@*/last )
|
||||
LOCAL r2, g2, b2, a2
|
||||
clr = hb_bmp_color( pBMP, r, g, b, a )
|
||||
IF clr >= 0
|
||||
last := clr
|
||||
hb_bmp_color2rgb( pBMP, clr, @r2, @g2, @b2, @a2 )
|
||||
_out( "Allocated color 0x%08x: r=%s, g=%s, b=%s, a=%s => r=%s, g=%s, b=%s, a=%s", clr, ;
|
||||
hb_valToExp( r ), hb_valToExp( g ), hb_valToExp( b ), hb_valToExp( a ), ;
|
||||
hb_valToExp( r2 ), hb_valToExp( g2 ), hb_valToExp( b2 ), hb_valToExp( a2 ) )
|
||||
RETURN .T.
|
||||
ELSE
|
||||
clr := last
|
||||
_err( "Cannot allocate color" )
|
||||
ENDIF
|
||||
RETURN .F.
|
||||
|
||||
STATIC FUNCTION bmp_save( pBMP, fname )
|
||||
IF hb_bmp_save( pBMP, fname )
|
||||
_out( "Created file: %s", fname )
|
||||
RETURN .T.
|
||||
ELSE
|
||||
_err( "Cannot save file: %s", fname )
|
||||
ENDIF
|
||||
RETURN .F.
|
||||
3
contrib/hbbmp/tests/hbmk.hbm
Normal file
3
contrib/hbbmp/tests/hbmk.hbm
Normal file
@@ -0,0 +1,3 @@
|
||||
hbbmp.hbc
|
||||
|
||||
-w3 -es2
|
||||
106
contrib/hbzebra/tests/bmp.prg
Normal file
106
contrib/hbzebra/tests/bmp.prg
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright 2025 Przemyslaw Czerpak <druzus /at/ priv.onet.pl>
|
||||
*/
|
||||
|
||||
#require "hbzebra"
|
||||
#require "hbbmp"
|
||||
|
||||
#define WIDTH 1
|
||||
|
||||
REQUEST HB_GT_CGI_DEFAULT
|
||||
|
||||
PROCEDURE Main()
|
||||
|
||||
DrawBarcode( WIDTH, "EAN13", "477012345678" )
|
||||
DrawBarcode( WIDTH, "EAN8", "1234567" )
|
||||
DrawBarcode( WIDTH, "UPCA", "01234567891" )
|
||||
DrawBarcode( WIDTH, "UPCE", "123456" )
|
||||
DrawBarcode( WIDTH, "CODE39", "ABC123" )
|
||||
DrawBarcode( WIDTH, "CODE39", "ABC123", HB_ZEBRA_FLAG_CHECKSUM + HB_ZEBRA_FLAG_WIDE3 )
|
||||
DrawBarcode( WIDTH, "ITF", "12345678901", HB_ZEBRA_FLAG_CHECKSUM )
|
||||
DrawBarcode( WIDTH, "MSI", "1234567", HB_ZEBRA_FLAG_CHECKSUM )
|
||||
DrawBarcode( WIDTH, "CODABAR", "40156", HB_ZEBRA_FLAG_WIDE3 )
|
||||
DrawBarcode( WIDTH, "CODE93", "ABC-123" )
|
||||
DrawBarcode( WIDTH, "CODE11", "1234567890", HB_ZEBRA_FLAG_CHECKSUM + HB_ZEBRA_FLAG_WIDE3 )
|
||||
DrawBarcode( WIDTH, "CODE128", "Code 128" )
|
||||
DrawBarcode( WIDTH, "PDF417", "Hello, World of Harbour!!! It's 2D barcode PDF417 :)" )
|
||||
DrawBarcode( WIDTH, "DATAMATRIX", "Hello, World of Harbour!!! It's 2D barcode DataMatrix :)" )
|
||||
DrawBarcode( WIDTH, "QRCODE", "https://en.wikipedia.org/wiki/QR_Code" )
|
||||
|
||||
?
|
||||
|
||||
RETURN
|
||||
|
||||
STATIC PROCEDURE DrawBarcode( nLineWidth, cType, cCode, nFlags )
|
||||
|
||||
LOCAL hZebra, pBMP, nLineHeight, nX, nY, nWidth, nHeight, nDepth, nColor, cFile
|
||||
|
||||
SWITCH cType
|
||||
CASE "EAN13" ; hZebra := hb_zebra_create_ean13( cCode, nFlags ) ; EXIT
|
||||
CASE "EAN8" ; hZebra := hb_zebra_create_ean8( cCode, nFlags ) ; EXIT
|
||||
CASE "UPCA" ; hZebra := hb_zebra_create_upca( cCode, nFlags ) ; EXIT
|
||||
CASE "UPCE" ; hZebra := hb_zebra_create_upce( cCode, nFlags ) ; EXIT
|
||||
CASE "CODE39" ; hZebra := hb_zebra_create_code39( cCode, nFlags ) ; EXIT
|
||||
CASE "ITF" ; hZebra := hb_zebra_create_itf( cCode, nFlags ) ; EXIT
|
||||
CASE "MSI" ; hZebra := hb_zebra_create_msi( cCode, nFlags ) ; EXIT
|
||||
CASE "CODABAR" ; hZebra := hb_zebra_create_codabar( cCode, nFlags ) ; EXIT
|
||||
CASE "CODE93" ; hZebra := hb_zebra_create_code93( cCode, nFlags ) ; EXIT
|
||||
CASE "CODE11" ; hZebra := hb_zebra_create_code11( cCode, nFlags ) ; EXIT
|
||||
CASE "CODE128" ; hZebra := hb_zebra_create_code128( cCode, nFlags ) ; EXIT
|
||||
CASE "PDF417" ; hZebra := hb_zebra_create_pdf417( cCode, nFlags ); nLineHeight := nLineWidth * 3 ; EXIT
|
||||
CASE "DATAMATRIX" ; hZebra := hb_zebra_create_datamatrix( cCode, nFlags ); nLineHeight := nLineWidth ; EXIT
|
||||
CASE "QRCODE" ; hZebra := hb_zebra_create_qrcode( cCode, nFlags ); nLineHeight := nLineWidth ; EXIT
|
||||
ENDSWITCH
|
||||
|
||||
IF hZebra != NIL
|
||||
IF hb_zebra_geterror( hZebra ) == 0
|
||||
|
||||
IF nLineHeight == NIL
|
||||
nLineHeight := nLineWidth * 36
|
||||
ENDIF
|
||||
|
||||
nDepth := 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
|
||||
|
||||
? cType, "code width", hb_ntos( nWidth ), "height", hb_ntos( nHeight )
|
||||
IF Empty( pBMP := hb_bmp_new( nWidth, nHeight, nDepth ) )
|
||||
? "Cannot create BMP image"
|
||||
ELSE
|
||||
/* allocate white color (RGB) and use it to fill the background */
|
||||
nColor := hb_bmp_color( pBMP, 255, 255, 255 )
|
||||
hb_bmp_rect( pBMP, 0, 0, nWidth, nHeight, nColor )
|
||||
/* allocate black color for barcode drawing */
|
||||
nColor := hb_bmp_color( pBMP, 0, 0, 0 )
|
||||
? "Building BMP with", cType, "code for vale:", hb_zebra_getcode( hZebra )
|
||||
hb_zebra_draw_bmp( hZebra, pBMP, nColor, nX, nY, nLineWidth, nLineHeight )
|
||||
cFile := Lower( cType ) + ".bmp"
|
||||
? "Creating BMP file:", cFile
|
||||
IF ! hb_bmp_save( pBMP, cFile )
|
||||
? "Cannot save BMP to file:", cFile
|
||||
ENDIF
|
||||
/* destroy BMP file */
|
||||
pBMP := NIL
|
||||
ENDIF
|
||||
ELSE
|
||||
? "Type", cType, "Code", cCode, "Error", hb_zebra_geterror( hZebra )
|
||||
ENDIF
|
||||
hb_zebra_destroy( hZebra )
|
||||
ELSE
|
||||
? "Invalid barcode type", cType
|
||||
ENDIF
|
||||
?
|
||||
|
||||
RETURN
|
||||
|
||||
STATIC FUNCTION hb_zebra_draw_bmp( hZebra, pBMP, nColor, ... )
|
||||
|
||||
IF hb_zebra_geterror( hZebra ) != 0
|
||||
RETURN HB_ZEBRA_ERROR_INVALIDZEBRA
|
||||
ENDIF
|
||||
|
||||
RETURN hb_zebra_draw( hZebra, {| x, y, w, h | hb_bmp_rect( pBMP, x, y, w, h, nColor ) }, ... )
|
||||
Reference in New Issue
Block a user