-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathezdib.c
2130 lines (1677 loc) · 49.6 KB
/
ezdib.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*------------------------------------------------------------------
// Copyright (c) 1997 - 2012
// Robert Umbehant
// ezdib@wheresjames.com
// http://www.wheresjames.com
//
// Redistribution and use in source and binary forms, with or
// without modification, are permitted for commercial and
// non-commercial purposes, provided that the following
// conditions are met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * The names of the developers or contributors may not be used to
// endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
// CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//----------------------------------------------------------------*/
#include "ezdib.h"
//------------------------------------------------------------------
// Config
//------------------------------------------------------------------
/// Enable static fonts
/**
This will prevent the creation of a font index, so font drawing
will be slightly slower. Unless you are on a memory constrained
system, you will probably prefer to leave this on.
*/
// #define EZD_STATIC_FONTS
/// Define if you do not have string.h
// #define EZD_NO_MEMCPY
/// Define if you do not have malloc, calloc, and free,
/**
ezd_flood_file() will not work.
*/
// #define EZD_NO_ALLOCATION
/// If you have no file handling routines
/**
ezd_save() will not work
*/
// #define EZD_NO_FILES
/// If you do not have math.h. Sorry, you won't get circles
/**
ezd_circle() and ezd_arc() will not work
*/
// #define EZD_NO_MATH
// Debugging
#if defined( _DEBUG )
# define EZD_DEBUG
#endif
//------------------------------------------------------------------
// Internal config
//------------------------------------------------------------------
#if !defined( EZD_NO_FILES )
# include <stdio.h>
#endif
// malloc, calloc, free
#if !defined( EZD_NO_ALLOCATION )
# if !defined( EZD_NO_STDLIB )
# include <stdlib.h>
# else
// No debug functions without stdlib
# undef EZD_DEBUG
# endif
# if !defined( EZD_malloc )
# define EZD_malloc malloc
# endif
# if !defined( EZD_calloc )
# define EZD_calloc calloc
# endif
# if !defined( EZD_free )
# define EZD_free free
# endif
#else
// Must use static fonts if no allocation routines
# define EZD_STATIC_FONTS
// Assume our debug functions won't work either
# undef EZD_DEBUG
#endif
// sin(), cos()
#if !defined( EZD_NO_MATH )
# include <math.h>
#endif
// memcpy and memset() substitutes
#if defined( EZD_NO_MEMCPY )
# define EZD_MEMCPY ezd_memcpy
# define EZD_MEMSET ezd_memset
static void ezd_memcpy( char *pDst, const char *pSrc, int sz )
{ while ( 0 < sz-- )
*(char*)pDst++ = *(char*)pSrc++;
}
static void ezd_memset( char *pDst, int v, int sz )
{ while ( 0 < sz-- )
*(char*)pDst++ = (char)v;
}
#else
# include <string.h>
# define EZD_MEMCPY memcpy
# define EZD_MEMSET memset
#endif
#if defined( EZD_DEBUG )
# define _MSG( m ) printf( "\n%s(%d): %s() : %s\n", __FILE__, __LINE__, __FUNCTION__, m )
# define _SHOW( f, ... ) printf( "\n%s(%d): %s() : " f "\n", __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__ )
# define _ERR( r, m ) ( _MSG( m ), r )
#else
# define _MSG( m )
# define _SHOW( ... )
# define _ERR( r, m ) ( r )
#endif
//------------------------------------------------------------------
// Data structures
//------------------------------------------------------------------
#if !defined( EZD_NOPACK )
# pragma pack( push, 1 )
#endif
/// DIB file magic number
#define EZD_MAGIC_NUMBER 0x4d42
/// Header for a standard dib file (.bmp)
typedef struct _SDIBFileHeader
{
/// Magic number, must be 0x42 0x4D (BM)
unsigned short uMagicNumber;
/// Size of the file in bytes
unsigned int uSize;
/// Reserved
unsigned short uReserved1;
/// Reserved
unsigned short uReserved2;
/// Offset to start of image data
unsigned int uOffset;
} SDIBFileHeader;
/// Standard bitmap structure
typedef struct _SBitmapInfoHeader
{
/// Size of this structure
unsigned int biSize;
/// Image width
int biWidth;
/// Image height
int biHeight;
/// Number of bit planes in the image
unsigned short biPlanes;
/// Bits per pixel / color depth
unsigned short biBitCount;
/// Type of compression used
unsigned int biCompression;
/// The total size of the image data
unsigned int biSizeImage;
/// Horizontal resolution in pixels per meter
int biXPelsPerMeter;
/// Vertical resolution in pixels per meter
int biYPelsPerMeter;
/// Total number of colors actually used in the image,
/// zero for all colors used.
unsigned int biClrUsed;
/// Number of colors required for displaying the image,
/// zero for all colors required.
unsigned int biClrImportant;
} SBitmapInfoHeader;
# define EZD_FLAG_FREE_BUFFER 0x00010000
// Returns non-zero if any color components are greater than the threshold
# define EZD_COMPARE_THRESHOLD( c, t ) ( ( c & 0xff ) > t \
|| ( ( c >> 8 ) & 0xff ) > t \
|| ( ( c >> 16 ) & 0xff ) > t )
// This structure contains the memory image
typedef struct _SImageData
{
/// Windows compatible image information
SBitmapInfoHeader bih;
/// Color palette for 1 bit images
int colPalette[ 2 ];
/// Threshold color for 1 bit images
int colThreshold;
/// Image flags
unsigned int uFlags;
/// User set pixel callback function
t_ezd_set_pixel pfSetPixel;
/// User data passed to set pixel callback function
void *pSetPixelUser;
/// User image pointer
unsigned char *pImage;
/// Image data
unsigned char pBuffer[ 4 ];
} SImageData;
#if !defined( EZD_STATIC_FONTS )
// This structure contains the memory image
typedef struct _SFontData
{
/// Font flags
unsigned int uFlags;
/// Font index pointers
const char *pIndex[ 256 ];
/// Font bitmap data
char pGlyph[ 1 ];
} SFontData;
#endif
#if !defined( EZD_NOPACK )
# pragma pack( pop )
#endif
void ezd_destroy( HEZDIMAGE x_hDib )
{
#if !defined( EZD_NO_ALLOCATION )
if ( x_hDib )
{ SImageData *p = (SImageData*)x_hDib;
if ( EZD_FLAG_FREE_BUFFER & p->uFlags )
EZD_free( (SImageData*)x_hDib );
} // end if
#endif
}
int ezd_header_size()
{
return sizeof( SImageData );
}
HEZDIMAGE ezd_initialize( void *x_pBuffer, int x_nBuffer, int x_lWidth, int x_lHeight, int x_lBpp, unsigned int x_uFlags )
{
int nImageSize;
SImageData *p;
// Ensure the user buffer is acceptable
if ( !x_pBuffer || ( 0 < x_nBuffer && sizeof( SImageData ) > x_nBuffer ) )
return _ERR( (HEZDIMAGE)0, "Invalid header buffer" );
// Sanity check
if ( !x_lWidth || !x_lHeight )
return _ERR( (HEZDIMAGE)0, "Invalid parameters" );
// Calculate image size
nImageSize = EZD_IMAGE_SIZE( x_lWidth, x_lHeight, x_lBpp, 4 );
if ( 0 >= nImageSize )
return _ERR( (HEZDIMAGE)0, "Invalid bits per pixel" );
// Point to users buffer
p = (SImageData*)x_pBuffer;
// Initialize the memory
EZD_MEMSET( (char*)p, 0, sizeof( SImageData ) );
// Initialize image metrics
p->bih.biSize = sizeof( SBitmapInfoHeader );
p->bih.biWidth = x_lWidth;
p->bih.biHeight = x_lHeight;
p->bih.biPlanes = 1;
p->bih.biBitCount = x_lBpp;
p->bih.biSizeImage = nImageSize;
// Initialize color palette
if ( 1 == x_lBpp )
{ p->bih.biClrUsed = 2;
p->bih.biClrImportant = 2;
p->colPalette[ 0 ] = 0;
p->colPalette[ 1 ] = 0xffffff;
} // end if
// Point image buffer
p->pImage = ( EZD_FLAG_USER_IMAGE_BUFFER & x_uFlags ) ? 0 : p->pBuffer;
// Save the flags
p->uFlags = x_uFlags;
return (HEZDIMAGE)p;
}
HEZDIMAGE ezd_create( int x_lWidth, int x_lHeight, int x_lBpp, unsigned int x_uFlags )
{
#if defined( EZD_NO_ALLOCATION )
return 0;
#else
int nImageSize;
SImageData *p;
// Make sure the caller isn't stepping on our internal flags
if ( 0xffff0000 & x_uFlags )
return _ERR( (HEZDIMAGE)0, "You have specified invalid flags" );
// Sanity check
if ( !x_lWidth || !x_lHeight )
return _ERR( (HEZDIMAGE)0, "Invalid image width or height" );
// Calculate image size
nImageSize = EZD_IMAGE_SIZE( x_lWidth, x_lHeight, x_lBpp, 4 );
if ( 0 >= nImageSize )
return _ERR( (HEZDIMAGE)0, "Invalid bits per pixel" );
// Allocate memory
p = (SImageData*)EZD_malloc( sizeof( SImageData )
+ ( ( EZD_FLAG_USER_IMAGE_BUFFER & x_uFlags ) ? 0 : nImageSize ) );
if ( !p )
return 0;
// Initialize the header
return ezd_initialize( p, sizeof( SImageData ), x_lWidth, x_lHeight, x_lBpp, x_uFlags | EZD_FLAG_FREE_BUFFER );
#endif
}
int ezd_set_image_buffer( HEZDIMAGE x_hDib, void *x_pImg, int x_nImg )
{
SImageData *p = (SImageData*)x_hDib;
if ( !p || !p || sizeof( SBitmapInfoHeader ) != p->bih.biSize )
{ _MSG( "Invalid parameters" ); return 0; }
// Verify image buffer size if needed
if ( x_pImg && 0 < x_nImg && x_nImg < (int)p->bih.biSizeImage )
{ _MSG( "Invalid user image buffer size" ); return 0; }
// Save user image pointer
p->pImage = ( !x_pImg && !( EZD_FLAG_USER_IMAGE_BUFFER & p->uFlags ) )
? p->pBuffer : x_pImg;
return 1;
}
int ezd_set_pixel_callback( HEZDIMAGE x_hDib, t_ezd_set_pixel x_pf, void *x_pUser )
{
SImageData *p = (SImageData*)x_hDib;
if ( !p || !p || sizeof( SBitmapInfoHeader ) != p->bih.biSize )
return _ERR( 0, "Invalid parameters" );
// Save user callback info
p->pfSetPixel = x_pf;
p->pSetPixelUser = x_pUser;
return 1;
}
int ezd_set_palette_color( HEZDIMAGE x_hDib, int x_idx, int x_col )
{
SImageData *p = (SImageData*)x_hDib;
if ( !p || !p || sizeof( SBitmapInfoHeader ) != p->bih.biSize )
return _ERR( 0, "Invalid parameters" );
if ( 0 > x_idx || 1 < x_idx )
return _ERR( 0, "Palette index out of range" );
// Set this palette color
p->colPalette[ x_idx ] = x_col;
return 1;
}
int ezd_get_palette_color( HEZDIMAGE x_hDib, int x_idx, int x_col )
{
SImageData *p = (SImageData*)x_hDib;
if ( !p || !p || sizeof( SBitmapInfoHeader ) != p->bih.biSize )
return _ERR( 0, "Invalid parameters" );
if ( 0 > x_idx || 1 < x_idx )
return _ERR( 0, "Palette index out of range" );
// Return this palette color
return p->colPalette[ x_idx ];
}
int* ezd_get_palette( HEZDIMAGE x_hDib )
{
SImageData *p = (SImageData*)x_hDib;
if ( !p || !p || sizeof( SBitmapInfoHeader ) != p->bih.biSize )
return _ERR( (int*)0, "Invalid parameters" );
// Return a pointer to the palette
return p->colPalette;
}
int ezd_get_palette_size( HEZDIMAGE x_hDib )
{
SImageData *p = (SImageData*)x_hDib;
if ( !p || !p || sizeof( SBitmapInfoHeader ) != p->bih.biSize )
return _ERR( 0, "Invalid parameters" );
switch( p->bih.biBitCount )
{
case 1 :
return 2;
} // end switch
return 0;
}
int ezd_set_color_threshold( HEZDIMAGE x_hDib, int x_col )
{
SImageData *p = (SImageData*)x_hDib;
if ( !p || !p || sizeof( SBitmapInfoHeader ) != p->bih.biSize )
return _ERR( 0, "Invalid parameters" );
// Calculate scan width
p->colThreshold = x_col;
return 1;
}
int ezd_get_width( HEZDIMAGE x_hDib )
{
SImageData *p = (SImageData*)x_hDib;
if ( !p || !p || sizeof( SBitmapInfoHeader ) != p->bih.biSize )
return _ERR( 0, "Invalid parameters" );
// Calculate scan width
return p->bih.biWidth;
}
int ezd_get_height( HEZDIMAGE x_hDib )
{
SImageData *p = (SImageData*)x_hDib;
if ( !p || !p || sizeof( SBitmapInfoHeader ) != p->bih.biSize )
return _ERR( 0, "Invalid parameters" );
// Calculate scan width
return p->bih.biHeight;
}
int ezd_get_bpp( HEZDIMAGE x_hDib )
{
SImageData *p = (SImageData*)x_hDib;
if ( !p || !p || sizeof( SBitmapInfoHeader ) != p->bih.biSize )
return _ERR( 0, "Invalid parameters" );
// Calculate scan width
return p->bih.biBitCount;
}
int ezd_get_image_size( HEZDIMAGE x_hDib )
{
SImageData *p = (SImageData*)x_hDib;
if ( !p || !p || sizeof( SBitmapInfoHeader ) != p->bih.biSize )
return _ERR( 0, "Invalid parameters" );
// Calculate scan width
return p->bih.biSizeImage;
}
void* ezd_get_image_ptr( HEZDIMAGE x_hDib )
{
SImageData *p = (SImageData*)x_hDib;
if ( !p || !p || sizeof( SBitmapInfoHeader ) != p->bih.biSize )
return _ERR( (void*)0, "Invalid parameters" );
// Calculate scan width
return p->pImage;
}
int ezd_save( HEZDIMAGE x_hDib, const char *x_pFile )
{
#if defined( EZD_NO_FILES )
return 0;
#else
FILE *fh;
int palette_size = 0;
SDIBFileHeader dfh;
SImageData *p = (SImageData*)x_hDib;
// Sanity checks
if ( !x_pFile || !*x_pFile || !p || sizeof( SBitmapInfoHeader ) != p->bih.biSize || !p->pImage )
return _ERR( 0, "Invalid parameters" );
// Ensure packing is ok
if ( sizeof( SDIBFileHeader ) != 14 )
return _ERR( 0, "Structure packing for DIB header is incorrect" );
// Ensure packing is ok
if ( sizeof( SBitmapInfoHeader ) != 40 )
return _ERR( 0, "Structure packing for BITMAP header is incorrect" );
// Add palettte size
if ( 1 == p->bih.biBitCount )
palette_size = sizeof( p->colPalette[ 0 ] ) * 2;
// Attempt to open the output file
fh = fopen ( x_pFile, "wb" );
if ( !fh )
return _ERR( 0, "Failed to open DIB file for writing" );
// Fill in header info
dfh.uMagicNumber = EZD_MAGIC_NUMBER;
dfh.uSize = sizeof( SDIBFileHeader ) + p->bih.biSize + p->bih.biSizeImage;
dfh.uReserved1 = 0;
dfh.uReserved2 = 0;
dfh.uOffset = sizeof( SDIBFileHeader ) + p->bih.biSize + palette_size;
// Write the header
if ( sizeof( dfh ) != fwrite( &dfh, 1, sizeof( dfh ), fh ) )
{ fclose( fh ); return _ERR( 0, "Error writing DIB header" ); }
// Write the Bitmap header
if ( p->bih.biSize != fwrite( &p->bih, 1, p->bih.biSize, fh ) )
{ fclose( fh ); return _ERR( 0, "Error writing bitmap header" ); }
// Write the color palette if needed
if ( 0 < palette_size )
if ( sizeof( p->colPalette ) != fwrite( p->colPalette, 1, palette_size, fh ) )
{ fclose( fh ); return _ERR( 0, "Error writing palette" ); }
// Write the Image data
if ( p->bih.biSizeImage != fwrite( p->pImage, 1, p->bih.biSizeImage, fh ) )
{ fclose( fh ); return _ERR( 0, "Error writing image data" ); }
// Close the file handle
fclose( fh );
return 1;
#endif
}
int ezd_fill( HEZDIMAGE x_hDib, int x_col )
{
int w, h, sw, pw, x, y;
SImageData *p = (SImageData*)x_hDib;
if ( !p || !p || sizeof( SBitmapInfoHeader ) != p->bih.biSize
|| ( !p->pImage && !p->pfSetPixel ) )
return _ERR( 0, "Invalid parameters" );
// Calculate image metrics
w = EZD_ABS( p->bih.biWidth );
h = EZD_ABS( p->bih.biHeight );
// Check for user callback function
if ( p->pfSetPixel )
{
// Fill each pixel
for ( y = 0; y < h; y++ )
for( x = 0; x < w; x++ )
if ( !p->pfSetPixel( p->pSetPixelUser, x, y, x_col, 0 ) )
return 0;
return 1;
} // end if
// Pixel and scan widths
pw = EZD_FITTO( p->bih.biBitCount, 8 );
sw = EZD_SCANWIDTH( w, p->bih.biBitCount, 4 );
// Set the first line
switch( p->bih.biBitCount )
{
case 1 :
EZD_MEMSET( p->pImage, EZD_COMPARE_THRESHOLD( x_col, p->colThreshold ) ? 0xff : 0, sw );
break;
case 24 :
{
// Color values
unsigned char r = x_col & 0xff;
unsigned char g = ( x_col >> 8 ) & 0xff;
unsigned char b = ( x_col >> 16 ) & 0xff;
unsigned char *pImg = p->pImage;
// Set the first line
for( x = 0; x < w; x++, pImg += pw )
pImg[ 0 ] = r, pImg[ 1 ] = g, pImg[ 2 ] = b;
} break;
case 32 :
{
// Set the first line
int *pImg = (int*)p->pImage;
for( x = 0; x < w; x++, pImg++ )
*pImg = x_col;
} break;
default :
return 0;
} // end switch
// Copy remaining lines
for( y = 1; y < h; y++ )
EZD_MEMCPY( &p->pImage[ y * sw ], p->pImage, sw );
return 1;
}
int ezd_set_pixel( HEZDIMAGE x_hDib, int x, int y, int x_col )
{
int w, h, sw, pw;
SImageData *p = (SImageData*)x_hDib;
if ( !p || sizeof( SBitmapInfoHeader ) != p->bih.biSize
|| ( !p->pImage && !p->pfSetPixel ) )
return _ERR( 0, "Invalid parameters" );
// Calculate image metrics
w = EZD_ABS( p->bih.biWidth );
h = EZD_ABS( p->bih.biHeight );
// Ensure pixel is within the image
if ( 0 > x || x >= w || 0 > y || y >= h )
{ _SHOW( "Point out of range : %d,%d : %dx%d ", x, y, w, h );
return 0;
} // en dif
// Set the specified pixel
if ( p->pfSetPixel )
return p->pfSetPixel( p->pSetPixelUser, x, y, x_col, 0 );
// Pixel and scan width
pw = EZD_FITTO( p->bih.biBitCount, 8 );
sw = EZD_SCANWIDTH( w, p->bih.biBitCount, 4 );
// Set the first line
switch( p->bih.biBitCount )
{
case 1 :
p->pImage[ y * sw + ( x >> 3 ) ] |= 0x80 >> ( x & 7 );
break;
case 24 :
{
// Color values
unsigned char r = x_col & 0xff;
unsigned char g = ( x_col >> 8 ) & 0xff;
unsigned char b = ( x_col >> 16 ) & 0xff;
unsigned char *pImg = &p->pImage[ y * sw + x * pw ];
// Set the pixel color
pImg[ 0 ] = r, pImg[ 1 ] = g, pImg[ 2 ] = b;
} break;
case 32 :
*(unsigned int*)&p->pImage[ y * sw + x * pw ] = x_col;
break;
default :
return 0;
} // end switch
return 1;
}
int ezd_get_pixel( HEZDIMAGE x_hDib, int x, int y )
{
int w, h, sw, pw;
SImageData *p = (SImageData*)x_hDib;
if ( !p || !p || sizeof( SBitmapInfoHeader ) != p->bih.biSize || !p->pImage )
return _ERR( 0, "Invalid parameters" );
// Calculate image metrics
w = EZD_ABS( p->bih.biWidth );
h = EZD_ABS( p->bih.biHeight );
// Ensure pixel is within the image
if ( 0 > x || x >= w || 0 > y || y >= h )
{ _SHOW( "Point out of range : %d,%d : %dx%d ", x, y, w, h );
return 0;
} // en dif
// Pixel and scan width
pw = EZD_FITTO( p->bih.biBitCount, 8 );
sw = EZD_SCANWIDTH( w, p->bih.biBitCount, 4 );
// Set the first line
switch( p->bih.biBitCount )
{
case 1 :
return p->colPalette[ ( p->pImage[ y * sw + ( x >> 3 ) ] & ( 0x80 >> ( x & 7 ) ) ) ? 1 : 0 ];
case 24 :
{
// Return the color of the specified pixel
unsigned char *pImg = &p->pImage[ y * sw + x * pw ];
return pImg[ 0 ] | ( pImg[ 1 ] << 8 ) | ( pImg[ 2 ] << 16 );
} break;
case 32 :
return *(unsigned int*)&p->pImage[ y * sw + x * pw ];
} // end switch
return 0;
}
int ezd_line( HEZDIMAGE x_hDib, int x1, int y1, int x2, int y2, int x_col )
{
int w, h, sw, pw, xd, yd, xl, yl, done = 0;
SImageData *p = (SImageData*)x_hDib;
if ( !p || sizeof( SBitmapInfoHeader ) != p->bih.biSize
|| ( !p->pImage && !p->pfSetPixel ) )
return _ERR( 0, "Invalid parameters" );
// Calculate image metrics
w = EZD_ABS( p->bih.biWidth );
h = EZD_ABS( p->bih.biHeight );
// Determine direction and distance
xd = ( x1 < x2 ) ? 1 : -1;
yd = ( y1 < y2 ) ? 1 : -1;
xl = ( x1 < x2 ) ? ( x2 - x1 ) : ( x1 - x2 );
yl = ( y1 < y2 ) ? ( y2 - y1 ) : ( y1 - y2 );
// Check for user callback function
if ( p->pfSetPixel )
{
int mx = 0, my = 0;
// Draw the line
while ( !done )
{
if ( x1 == x2 && y1 == y2 )
done = 1;
// Plot pixel
if ( 0 <= x1 && x1 < w && 0 <= y1 && y1 < h )
if ( !p->pfSetPixel( p->pSetPixelUser, x1, y1, x_col, 0 ) )
return 0;
mx += xl;
if ( x1 != x2 && mx > yl )
x1 += xd, mx -= yl;
my += yl;
if ( y1 != y2 && my > xl )
y1 += yd, my -= xl;
} // end while
return 1;
} // end if
// Pixel and scan width
pw = EZD_FITTO( p->bih.biBitCount, 8 );
sw = EZD_SCANWIDTH( w, p->bih.biBitCount, 4 );
// Set the first line
switch( p->bih.biBitCount )
{
case 1 :
{
int mx = 0, my = 0, c = EZD_COMPARE_THRESHOLD( x_col, p->colThreshold );
static unsigned char xm[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
// Draw the line
while ( !done )
{
if ( x1 == x2 && y1 == y2 )
done = 1;
// Plot pixel
if ( 0 <= x1 && x1 < w && 0 <= y1 && y1 < h )
{
if ( c )
p->pImage[ y1 * sw + ( x1 >> 3 ) ] |= xm[ x1 & 7 ];
else
p->pImage[ y1 * sw + ( x1 >> 3 ) ] &= ~xm[ x1 & 7 ];
} // end if
mx += xl;
if ( x1 != x2 && mx > yl )
x1 += xd, mx -= yl;
my += yl;
if ( y1 != y2 && my > xl )
y1 += yd, my -= xl;
} // end while
} break;
case 24 :
{
// Color values
unsigned char r = x_col & 0xff;
unsigned char g = ( x_col >> 8 ) & 0xff;
unsigned char b = ( x_col >> 16 ) & 0xff;
unsigned char *pImg;
int mx = 0, my = 0;
while ( !done )
{
if ( x1 == x2 && y1 == y2 )
done = 1;
// Plot pixel
if ( 0 <= x1 && x1 < w && 0 <= y1 && y1 < h )
{ pImg = &p->pImage[ y1 * sw + x1 * pw ];
pImg[ 0 ] = r, pImg[ 1 ] = g, pImg[ 2 ] = b;
} // end if
mx += xl;
if ( x1 != x2 && mx > yl )
x1 += xd, mx -= yl;
my += yl;
if ( y1 != y2 && my > xl )
y1 += yd, my -= xl;
} // end while
} break;
case 32 :
{
// Color values
int mx = 0, my = 0;
// Draw the line
while ( !done )
{
if ( x1 == x2 && y1 == y2 )
done = 1;
// Plot pixel
if ( 0 <= x1 && x1 < w && 0 <= y1 && y1 < h )
*(unsigned int*)&p->pImage[ y1 * sw + x1 * pw ] = x_col;
mx += xl;
if ( x1 != x2 && mx > yl )
x1 += xd, mx -= yl;
my += yl;
if ( y1 != y2 && my > xl )
y1 += yd, my -= xl;
} // end while
} break;
default :
return 0;
} // end switch
return 1;
}
int ezd_rect( HEZDIMAGE x_hDib, int x1, int y1, int x2, int y2, int x_col )
{
// Draw rectangle
return ezd_line( x_hDib, x1, y1, x2, y1, x_col )
&& ezd_line( x_hDib, x2, y1, x2, y2, x_col )
&& ezd_line( x_hDib, x2, y2, x1, y2, x_col )
&& ezd_line( x_hDib, x1, y2, x1, y1, x_col );
}
#define EZD_PI ( (double)3.141592654 )
#define EZD_PI2 ( EZD_PI * (double)2 )
#define EZD_PI4 ( EZD_PI * (double)4 )
int ezd_arc( HEZDIMAGE x_hDib, int x, int y, int x_rad, double x_dStart, double x_dEnd, int x_col )
{
#if defined( EZD_NO_MATH )
return 0;
#else
double arc;
int i, w, h, sw, pw, px, py;
int res = (int)( (double)x_rad * EZD_PI4 ), resdraw;
unsigned char *pImg;
SImageData *p = (SImageData*)x_hDib;
if ( !p || sizeof( SBitmapInfoHeader ) != p->bih.biSize
|| ( !p->pImage && !p->pfSetPixel ) )
return _ERR( 0, "Invalid parameters" );
// Dont' draw null arc
if ( x_dStart == x_dEnd )
return 1;
// Ensure correct order
else if ( x_dStart > x_dEnd )
{ double t = x_dStart;
x_dStart = x_dEnd;
x_dEnd = t;
} // end if
// Get arc size
arc = x_dEnd - x_dStart;
// How many points to draw
resdraw = ( EZD_PI2 <= arc ) ? res : (int)( arc * (double)res / EZD_PI2 );
// Calculate image metrics
w = EZD_ABS( p->bih.biWidth );
h = EZD_ABS( p->bih.biHeight );
// Ensure pixel is within the image
if ( 0 > x || x >= w || 0 > y || y >= h )
{ _SHOW( "Point out of range : %d,%d : %dx%d ", x, y, w, h );
return 0;
} // en dif
// Check for user callback function
if ( p->pfSetPixel )
{
// Draw the circle
for ( i = 0; i < resdraw; i++ )
{
// Offset for this pixel
px = x + (int)( (double)x_rad * cos( x_dStart + (double)i * EZD_PI2 / (double)res ) );
py = y + (int)( (double)x_rad * sin( x_dStart + (double)i * EZD_PI2 / (double)res ) );
// Plot pixel
if ( 0 <= px && px < w && 0 <= py && py < h )
if ( !p->pfSetPixel( p->pSetPixelUser, px, py, x_col, 0 ) )
return 0;
} // end while
return 1;
} // end if
// Pixel and scan width
pw = EZD_FITTO( p->bih.biBitCount, 8 );
sw = EZD_SCANWIDTH( w, p->bih.biBitCount, 4 );
switch( p->bih.biBitCount )
{
case 1:
{
int c = EZD_COMPARE_THRESHOLD( x_col, p->colThreshold );
static unsigned char xm[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
// Draw the circle
for ( i = 0; i < resdraw; i++ )
{
// Offset for this pixel
px = x + (int)( (double)x_rad * cos( x_dStart + (double)i * EZD_PI2 / (double)res ) );
py = y + (int)( (double)x_rad * sin( x_dStart + (double)i * EZD_PI2 / (double)res ) );
// Plot pixel