2016-02-17 13:52:48 +03:00
/* png.c - Handles output to PNG file */
/*
libzint - the open source barcode library
2016-02-20 13:50:15 +03:00
Copyright ( C ) 2009 - 2016 Robin Stuart < rstuart114 @ gmail . com >
2016-02-17 13:52:48 +03:00
Redistribution and use in source and binary forms , with or without
modification , are permitted provided that the following conditions
are met :
1. Redistributions of source code must retain the above copyright
notice , this list of conditions and the following disclaimer .
2. Redistributions in binary form must reproduce the above copyright
notice , this list of conditions and the following disclaimer in the
documentation and / or other materials provided with the distribution .
3. Neither the name of the project nor the names of its contributors
may 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 .
2016-02-20 13:50:15 +03:00
*/
2016-02-17 13:52:48 +03:00
# include <stdio.h>
# ifdef _MSC_VER
# include <fcntl.h>
# include <io.h>
# endif
# include <stdlib.h>
# include <string.h>
# include "common.h"
# ifdef _MSC_VER
# include <malloc.h>
# endif /* _MSC_VER */
# ifndef NO_PNG
# include <png.h>
# include <zlib.h>
# include <setjmp.h>
# endif /* NO_PNG */
# include "maxipng.h" /* Maxicode shapes */
# include "font.h" /* Font for human readable text */
2016-07-18 22:14:56 +03:00
# include "bmp.h" /* Bitmap header structure */
# include <math.h>
2016-02-17 13:52:48 +03:00
# define SSET "0123456789ABCDEF"
# define PNG_DATA 100
# define BMP_DATA 200
# ifndef NO_PNG
2016-02-20 13:50:15 +03:00
2016-02-17 13:52:48 +03:00
struct mainprog_info_type {
long width ;
long height ;
FILE * outfile ;
jmp_buf jmpbuf ;
} ;
2016-02-20 13:50:15 +03:00
static void writepng_error_handler ( png_structp png_ptr , png_const_charp msg ) {
struct mainprog_info_type * graphic ;
2016-02-17 13:52:48 +03:00
fprintf ( stderr , " writepng libpng error: %s \n " , msg ) ;
fflush ( stderr ) ;
2016-02-20 13:50:15 +03:00
graphic = ( struct mainprog_info_type * ) png_get_error_ptr ( png_ptr ) ;
if ( graphic = = NULL ) {
/* we are completely hosed now */
2016-02-17 13:52:48 +03:00
fprintf ( stderr ,
2016-02-20 13:50:15 +03:00
" writepng severe error: jmpbuf not recoverable; terminating. \n " ) ;
2016-02-17 13:52:48 +03:00
fflush ( stderr ) ;
return ;
}
longjmp ( graphic - > jmpbuf , 1 ) ;
}
2016-02-20 13:50:15 +03:00
int png_pixel_plot ( struct zint_symbol * symbol , int image_height , int image_width , char * pixelbuf , int rotate_angle ) {
struct mainprog_info_type wpng_info ;
struct mainprog_info_type * graphic ;
png_structp png_ptr ;
png_infop info_ptr ;
unsigned char * image_data ;
int i , row , column , errno ;
int fgred , fggrn , fgblu , bgred , bggrn , bgblu ;
2016-02-17 13:52:48 +03:00
# ifndef _MSC_VER
2016-02-20 13:50:15 +03:00
unsigned char outdata [ image_width * 3 ] ;
2016-02-17 13:52:48 +03:00
# else
2016-02-20 13:50:15 +03:00
unsigned char * outdata = ( unsigned char * ) _alloca ( image_width * 3 ) ;
2016-02-17 13:52:48 +03:00
# endif
2016-02-20 13:50:15 +03:00
graphic = & wpng_info ;
switch ( rotate_angle ) {
case 0 :
case 180 :
graphic - > width = image_width ;
graphic - > height = image_height ;
break ;
case 90 :
case 270 :
graphic - > width = image_height ;
graphic - > height = image_width ;
break ;
}
/* sort out colour options */
to_upper ( ( unsigned char * ) symbol - > fgcolour ) ;
to_upper ( ( unsigned char * ) symbol - > bgcolour ) ;
if ( strlen ( symbol - > fgcolour ) ! = 6 ) {
strcpy ( symbol - > errtxt , " Malformed foreground colour target " ) ;
return ZINT_ERROR_INVALID_OPTION ;
}
if ( strlen ( symbol - > bgcolour ) ! = 6 ) {
strcpy ( symbol - > errtxt , " Malformed background colour target " ) ;
return ZINT_ERROR_INVALID_OPTION ;
}
errno = is_sane ( SSET , ( unsigned char * ) symbol - > fgcolour , strlen ( symbol - > fgcolour ) ) ;
if ( errno = = ZINT_ERROR_INVALID_DATA ) {
strcpy ( symbol - > errtxt , " Malformed foreground colour target " ) ;
return ZINT_ERROR_INVALID_OPTION ;
}
errno = is_sane ( SSET , ( unsigned char * ) symbol - > bgcolour , strlen ( symbol - > bgcolour ) ) ;
if ( errno = = ZINT_ERROR_INVALID_DATA ) {
strcpy ( symbol - > errtxt , " Malformed background colour target " ) ;
return ZINT_ERROR_INVALID_OPTION ;
}
fgred = ( 16 * ctoi ( symbol - > fgcolour [ 0 ] ) ) + ctoi ( symbol - > fgcolour [ 1 ] ) ;
fggrn = ( 16 * ctoi ( symbol - > fgcolour [ 2 ] ) ) + ctoi ( symbol - > fgcolour [ 3 ] ) ;
fgblu = ( 16 * ctoi ( symbol - > fgcolour [ 4 ] ) ) + ctoi ( symbol - > fgcolour [ 5 ] ) ;
bgred = ( 16 * ctoi ( symbol - > bgcolour [ 0 ] ) ) + ctoi ( symbol - > bgcolour [ 1 ] ) ;
bggrn = ( 16 * ctoi ( symbol - > bgcolour [ 2 ] ) ) + ctoi ( symbol - > bgcolour [ 3 ] ) ;
bgblu = ( 16 * ctoi ( symbol - > bgcolour [ 4 ] ) ) + ctoi ( symbol - > bgcolour [ 5 ] ) ;
/* Open output file in binary mode */
if ( ( symbol - > output_options & BARCODE_STDOUT ) ! = 0 ) {
2016-02-17 13:52:48 +03:00
# ifdef _MSC_VER
2016-02-20 13:50:15 +03:00
if ( - 1 = = _setmode ( _fileno ( stdout ) , _O_BINARY ) ) {
strcpy ( symbol - > errtxt , " Can't open output file " ) ;
return ZINT_ERROR_FILE_ACCESS ;
}
2016-02-17 13:52:48 +03:00
# endif
2016-02-20 13:50:15 +03:00
graphic - > outfile = stdout ;
} else {
if ( ! ( graphic - > outfile = fopen ( symbol - > outfile , " wb " ) ) ) {
strcpy ( symbol - > errtxt , " Can't open output file " ) ;
return ZINT_ERROR_FILE_ACCESS ;
}
}
/* Set up error handling routine as proc() above */
png_ptr = png_create_write_struct ( PNG_LIBPNG_VER_STRING , graphic , writepng_error_handler , NULL ) ;
if ( ! png_ptr ) {
strcpy ( symbol - > errtxt , " Out of memory " ) ;
return ZINT_ERROR_MEMORY ;
}
info_ptr = png_create_info_struct ( png_ptr ) ;
if ( ! info_ptr ) {
png_destroy_write_struct ( & png_ptr , NULL ) ;
strcpy ( symbol - > errtxt , " Out of memory " ) ;
return ZINT_ERROR_MEMORY ;
}
/* catch jumping here */
if ( setjmp ( graphic - > jmpbuf ) ) {
png_destroy_write_struct ( & png_ptr , & info_ptr ) ;
strcpy ( symbol - > errtxt , " libpng error occurred " ) ;
return ZINT_ERROR_MEMORY ;
}
/* open output file with libpng */
png_init_io ( png_ptr , graphic - > outfile ) ;
/* set compression */
png_set_compression_level ( png_ptr , 9 ) ;
/* set Header block */
png_set_IHDR ( png_ptr , info_ptr , graphic - > width , graphic - > height ,
8 , PNG_COLOR_TYPE_RGB , PNG_INTERLACE_NONE ,
PNG_COMPRESSION_TYPE_DEFAULT , PNG_FILTER_TYPE_DEFAULT ) ;
/* write all chunks up to (but not including) first IDAT */
png_write_info ( png_ptr , info_ptr ) ;
/* set up the transformations: for now, just pack low-bit-depth pixels
into bytes ( one , two or four pixels per byte ) */
png_set_packing ( png_ptr ) ;
/* Pixel Plotting */
switch ( rotate_angle ) {
case 0 : /* Plot the right way up */
for ( row = 0 ; row < image_height ; row + + ) {
for ( column = 0 ; column < image_width ; column + + ) {
i = column * 3 ;
switch ( * ( pixelbuf + ( image_width * row ) + column ) ) {
case ' 1 ' :
outdata [ i ] = fgred ;
outdata [ i + 1 ] = fggrn ;
outdata [ i + 2 ] = fgblu ;
break ;
default :
outdata [ i ] = bgred ;
outdata [ i + 1 ] = bggrn ;
outdata [ i + 2 ] = bgblu ;
break ;
}
}
/* write row contents to file */
image_data = outdata ;
png_write_row ( png_ptr , image_data ) ;
}
break ;
case 90 : /* Plot 90 degrees clockwise */
for ( row = 0 ; row < image_width ; row + + ) {
for ( column = 0 ; column < image_height ; column + + ) {
i = column * 3 ;
switch ( * ( pixelbuf + ( image_width * ( image_height - column - 1 ) ) + row ) ) {
case ' 1 ' :
outdata [ i ] = fgred ;
outdata [ i + 1 ] = fggrn ;
outdata [ i + 2 ] = fgblu ;
break ;
default :
outdata [ i ] = bgred ;
outdata [ i + 1 ] = bggrn ;
outdata [ i + 2 ] = bgblu ;
break ;
}
}
/* write row contents to file */
image_data = outdata ;
png_write_row ( png_ptr , image_data ) ;
}
break ;
case 180 : /* Plot upside down */
for ( row = 0 ; row < image_height ; row + + ) {
for ( column = 0 ; column < image_width ; column + + ) {
i = column * 3 ;
switch ( * ( pixelbuf + ( image_width * ( image_height - row - 1 ) ) + ( image_width - column - 1 ) ) ) {
case ' 1 ' :
outdata [ i ] = fgred ;
outdata [ i + 1 ] = fggrn ;
outdata [ i + 2 ] = fgblu ;
break ;
default :
outdata [ i ] = bgred ;
outdata [ i + 1 ] = bggrn ;
outdata [ i + 2 ] = bgblu ;
break ;
}
}
/* write row contents to file */
image_data = outdata ;
png_write_row ( png_ptr , image_data ) ;
}
break ;
case 270 : /* Plot 90 degrees anti-clockwise */
for ( row = 0 ; row < image_width ; row + + ) {
for ( column = 0 ; column < image_height ; column + + ) {
i = column * 3 ;
switch ( * ( pixelbuf + ( image_width * column ) + ( image_width - row - 1 ) ) ) {
case ' 1 ' :
outdata [ i ] = fgred ;
outdata [ i + 1 ] = fggrn ;
outdata [ i + 2 ] = fgblu ;
break ;
default :
outdata [ i ] = bgred ;
outdata [ i + 1 ] = bggrn ;
outdata [ i + 2 ] = bgblu ;
break ;
}
}
/* write row contents to file */
image_data = outdata ;
png_write_row ( png_ptr , image_data ) ;
}
break ;
}
/* End the file */
png_write_end ( png_ptr , NULL ) ;
/* make sure we have disengaged */
if ( png_ptr & & info_ptr ) png_destroy_write_struct ( & png_ptr , & info_ptr ) ;
if ( symbol - > output_options & BARCODE_STDOUT ) {
fflush ( wpng_info . outfile ) ;
} else {
fclose ( wpng_info . outfile ) ;
}
return 0 ;
2016-02-17 13:52:48 +03:00
}
# endif /* NO_PNG */
2016-02-20 13:50:15 +03:00
int bmp_pixel_plot ( struct zint_symbol * symbol , int image_height , int image_width , char * pixelbuf , int rotate_angle ) {
int i , row , column , errno ;
int fgred , fggrn , fgblu , bgred , bggrn , bgblu ;
2016-07-18 22:14:56 +03:00
int row_size ;
unsigned int data_size ;
unsigned char * bitmap_file_start , * bmp_posn ;
FILE * bmp_file ;
2016-02-20 13:50:15 +03:00
switch ( rotate_angle ) {
case 0 :
case 180 :
symbol - > bitmap_width = image_width ;
symbol - > bitmap_height = image_height ;
break ;
case 90 :
case 270 :
symbol - > bitmap_width = image_height ;
symbol - > bitmap_height = image_width ;
break ;
}
if ( symbol - > bitmap ! = NULL )
free ( symbol - > bitmap ) ;
2016-07-18 22:14:56 +03:00
row_size = 4 * floor ( ( 24 * symbol - > bitmap_width + 31 ) / 32 ) ;
symbol - > bitmap = ( char * ) malloc ( row_size * symbol - > bitmap_height ) ;
2016-02-17 13:52:48 +03:00
2016-02-20 13:50:15 +03:00
/* sort out colour options */
to_upper ( ( unsigned char * ) symbol - > fgcolour ) ;
to_upper ( ( unsigned char * ) symbol - > bgcolour ) ;
if ( strlen ( symbol - > fgcolour ) ! = 6 ) {
strcpy ( symbol - > errtxt , " Malformed foreground colour target " ) ;
return ZINT_ERROR_INVALID_OPTION ;
}
if ( strlen ( symbol - > bgcolour ) ! = 6 ) {
strcpy ( symbol - > errtxt , " Malformed background colour target " ) ;
return ZINT_ERROR_INVALID_OPTION ;
}
errno = is_sane ( SSET , ( unsigned char * ) symbol - > fgcolour , strlen ( symbol - > fgcolour ) ) ;
if ( errno = = ZINT_ERROR_INVALID_DATA ) {
strcpy ( symbol - > errtxt , " Malformed foreground colour target " ) ;
return ZINT_ERROR_INVALID_OPTION ;
}
errno = is_sane ( SSET , ( unsigned char * ) symbol - > bgcolour , strlen ( symbol - > fgcolour ) ) ;
if ( errno = = ZINT_ERROR_INVALID_DATA ) {
strcpy ( symbol - > errtxt , " Malformed background colour target " ) ;
return ZINT_ERROR_INVALID_OPTION ;
}
fgred = ( 16 * ctoi ( symbol - > fgcolour [ 0 ] ) ) + ctoi ( symbol - > fgcolour [ 1 ] ) ;
fggrn = ( 16 * ctoi ( symbol - > fgcolour [ 2 ] ) ) + ctoi ( symbol - > fgcolour [ 3 ] ) ;
fgblu = ( 16 * ctoi ( symbol - > fgcolour [ 4 ] ) ) + ctoi ( symbol - > fgcolour [ 5 ] ) ;
bgred = ( 16 * ctoi ( symbol - > bgcolour [ 0 ] ) ) + ctoi ( symbol - > bgcolour [ 1 ] ) ;
bggrn = ( 16 * ctoi ( symbol - > bgcolour [ 2 ] ) ) + ctoi ( symbol - > bgcolour [ 3 ] ) ;
bgblu = ( 16 * ctoi ( symbol - > bgcolour [ 4 ] ) ) + ctoi ( symbol - > bgcolour [ 5 ] ) ;
/* Pixel Plotting */
i = 0 ;
switch ( rotate_angle ) {
case 0 : /* Plot the right way up */
for ( row = 0 ; row < image_height ; row + + ) {
for ( column = 0 ; column < image_width ; column + + ) {
2016-07-18 22:14:56 +03:00
i = ( 3 * column ) + ( row * row_size ) ;
switch ( * ( pixelbuf + ( image_width * ( image_height - row - 1 ) ) + column ) ) {
2016-02-20 13:50:15 +03:00
case ' 1 ' :
2016-07-18 22:14:56 +03:00
symbol - > bitmap [ i ] = fgblu ;
symbol - > bitmap [ i + 1 ] = fggrn ;
symbol - > bitmap [ i + 2 ] = fgred ;
2016-02-20 13:50:15 +03:00
break ;
default :
2016-07-18 22:14:56 +03:00
symbol - > bitmap [ i ] = bgblu ;
symbol - > bitmap [ i + 1 ] = bggrn ;
symbol - > bitmap [ i + 2 ] = bgred ;
2016-02-20 13:50:15 +03:00
break ;
}
}
}
break ;
case 90 : /* Plot 90 degrees clockwise */
for ( row = 0 ; row < image_width ; row + + ) {
for ( column = 0 ; column < image_height ; column + + ) {
2016-07-18 22:14:56 +03:00
i = ( 3 * column ) + ( row * row_size ) ;
switch ( * ( pixelbuf + ( image_width * ( image_height - column - 1 ) ) + ( image_width - row - 1 ) ) ) {
2016-02-20 13:50:15 +03:00
case ' 1 ' :
2016-07-18 22:14:56 +03:00
symbol - > bitmap [ i ] = fgblu ;
symbol - > bitmap [ i + 1 ] = fggrn ;
symbol - > bitmap [ i + 2 ] = fgred ;
2016-02-20 13:50:15 +03:00
break ;
default :
2016-07-18 22:14:56 +03:00
symbol - > bitmap [ i ] = bgblu ;
symbol - > bitmap [ i + 1 ] = bggrn ;
symbol - > bitmap [ i + 2 ] = bgred ;
2016-02-20 13:50:15 +03:00
break ;
}
}
}
break ;
case 180 : /* Plot upside down */
for ( row = 0 ; row < image_height ; row + + ) {
for ( column = 0 ; column < image_width ; column + + ) {
2016-07-18 22:14:56 +03:00
i = ( 3 * column ) + ( row * row_size ) ;
switch ( * ( pixelbuf + ( image_width * row ) + ( image_width - column - 1 ) ) ) {
2016-02-20 13:50:15 +03:00
case ' 1 ' :
2016-07-18 22:14:56 +03:00
symbol - > bitmap [ i ] = fgblu ;
symbol - > bitmap [ i + 1 ] = fggrn ;
symbol - > bitmap [ i + 2 ] = fgred ;
2016-02-20 13:50:15 +03:00
break ;
default :
2016-07-18 22:14:56 +03:00
symbol - > bitmap [ i ] = bgblu ;
symbol - > bitmap [ i + 1 ] = bggrn ;
symbol - > bitmap [ i + 2 ] = bgred ;
2016-02-20 13:50:15 +03:00
break ;
}
}
}
break ;
case 270 : /* Plot 90 degrees anti-clockwise */
for ( row = 0 ; row < image_width ; row + + ) {
for ( column = 0 ; column < image_height ; column + + ) {
2016-07-18 22:14:56 +03:00
i = ( 3 * column ) + ( row * row_size ) ;
switch ( * ( pixelbuf + ( image_width * column ) + row ) ) {
2016-02-20 13:50:15 +03:00
case ' 1 ' :
2016-07-18 22:14:56 +03:00
symbol - > bitmap [ i ] = fgblu ;
symbol - > bitmap [ i + 1 ] = fggrn ;
symbol - > bitmap [ i + 2 ] = fgred ;
2016-02-20 13:50:15 +03:00
break ;
default :
2016-07-18 22:14:56 +03:00
symbol - > bitmap [ i ] = bgblu ;
symbol - > bitmap [ i + 1 ] = bggrn ;
symbol - > bitmap [ i + 2 ] = bgred ;
2016-02-20 13:50:15 +03:00
break ;
}
}
}
break ;
}
2016-07-18 22:14:56 +03:00
data_size = symbol - > bitmap_height * row_size ;
2016-07-18 22:22:56 +03:00
symbol - > bitmap_byte_length = data_size ;
2016-07-18 22:14:56 +03:00
bitmap_file_header_t file_header ;
bitmap_info_header_t info_header ;
file_header . header_field = 0x4d42 ; // "BM"
file_header . file_size = sizeof ( bitmap_file_header_t ) + sizeof ( bitmap_info_header_t ) + data_size ;
file_header . reserved = 0 ;
file_header . data_offset = sizeof ( bitmap_file_header_t ) + sizeof ( bitmap_info_header_t ) ;
info_header . header_size = sizeof ( bitmap_info_header_t ) ;
info_header . width = symbol - > bitmap_width ;
info_header . height = symbol - > bitmap_height ;
info_header . colour_planes = 1 ;
info_header . bits_per_pixel = 24 ;
info_header . compression_method = 0 ; // BI_RGB
info_header . image_size = 0 ;
info_header . horiz_res = 0 ;
info_header . vert_res = 0 ;
info_header . colours = 0 ;
info_header . important_colours = 0 ;
bitmap_file_start = ( unsigned char * ) malloc ( file_header . file_size ) ;
memset ( bitmap_file_start , 0xff , file_header . file_size ) ;
bmp_posn = bitmap_file_start ;
memcpy ( bitmap_file_start , & file_header , sizeof ( bitmap_file_header_t ) ) ;
bmp_posn + = sizeof ( bitmap_file_header_t ) ;
memcpy ( bmp_posn , & info_header , sizeof ( bitmap_info_header_t ) ) ;
bmp_posn + = sizeof ( bitmap_info_header_t ) ;
memcpy ( bmp_posn , symbol - > bitmap , data_size ) ;
/* Open output file in binary mode */
if ( ( symbol - > output_options & BARCODE_STDOUT ) ! = 0 ) {
# ifdef _MSC_VER
if ( - 1 = = _setmode ( _fileno ( stdout ) , _O_BINARY ) ) {
strcpy ( symbol - > errtxt , " Can't open output file " ) ;
return ZINT_ERROR_FILE_ACCESS ;
}
# endif
bmp_file = stdout ;
} else {
if ( ! ( bmp_file = fopen ( symbol - > outfile , " wb " ) ) ) {
strcpy ( symbol - > errtxt , " Can't open output file " ) ;
return ZINT_ERROR_FILE_ACCESS ;
}
}
fwrite ( bitmap_file_start , file_header . file_size , 1 , bmp_file ) ;
fclose ( bmp_file ) ;
2016-02-20 13:50:15 +03:00
return 0 ;
2016-02-17 13:52:48 +03:00
}
2016-02-20 13:50:15 +03:00
int png_to_file ( struct zint_symbol * symbol , int image_height , int image_width , char * pixelbuf , int rotate_angle , int image_type ) {
int error_number ;
float scaler = symbol - > scale ;
char * scaled_pixelbuf ;
int horiz , vert , i ;
int scale_width , scale_height ;
if ( scaler = = 0 ) {
scaler = 0.5 ;
}
scale_width = image_width * scaler ;
scale_height = image_height * scaler ;
/* Apply scale options by creating another pixel buffer */
if ( ! ( scaled_pixelbuf = ( char * ) malloc ( scale_width * scale_height ) ) ) {
printf ( " Insufficient memory for pixel buffer " ) ;
return ZINT_ERROR_ENCODING_PROBLEM ;
} else {
for ( i = 0 ; i < ( scale_width * scale_height ) ; i + + ) {
* ( scaled_pixelbuf + i ) = ' 0 ' ;
}
}
for ( vert = 0 ; vert < scale_height ; vert + + ) {
for ( horiz = 0 ; horiz < scale_width ; horiz + + ) {
* ( scaled_pixelbuf + ( vert * scale_width ) + horiz ) = * ( pixelbuf + ( ( int ) ( vert / scaler ) * image_width ) + ( int ) ( horiz / scaler ) ) ;
}
}
if ( image_type = = PNG_DATA ) {
2016-02-17 13:52:48 +03:00
# ifndef NO_PNG
2016-02-20 13:50:15 +03:00
error_number = png_pixel_plot ( symbol , scale_height , scale_width , scaled_pixelbuf , rotate_angle ) ;
2016-02-17 13:52:48 +03:00
# else
2016-02-20 13:50:15 +03:00
return ZINT_ERROR_INVALID_OPTION ;
2016-02-17 13:52:48 +03:00
# endif
2016-02-20 13:50:15 +03:00
} else {
error_number = bmp_pixel_plot ( symbol , scale_height , scale_width , scaled_pixelbuf , rotate_angle ) ;
}
2016-02-17 13:52:48 +03:00
2016-02-20 13:50:15 +03:00
free ( scaled_pixelbuf ) ;
2016-02-17 13:52:48 +03:00
2016-02-20 13:50:15 +03:00
return error_number ;
2016-02-17 13:52:48 +03:00
}
2016-02-20 13:50:15 +03:00
void draw_bar ( char * pixelbuf , int xpos , int xlen , int ypos , int ylen , int image_width , int image_height ) {
/* Draw a rectangle */
int i , j , png_ypos ;
2016-02-17 13:52:48 +03:00
2016-02-20 13:50:15 +03:00
png_ypos = image_height - ypos - ylen ;
/* This fudge is needed because EPS measures height from the bottom up but
PNG measures y position from the top down */
2016-02-17 13:52:48 +03:00
2016-02-20 13:50:15 +03:00
for ( i = ( xpos ) ; i < ( xpos + xlen ) ; i + + ) {
for ( j = ( png_ypos ) ; j < ( png_ypos + ylen ) ; j + + ) {
* ( pixelbuf + ( image_width * j ) + i ) = ' 1 ' ;
}
}
2016-02-17 13:52:48 +03:00
}
int bullseye_pixel ( int row , int col ) {
2016-02-20 13:50:15 +03:00
int block_val , block_pos , return_val ;
block_val = bullseye_compressed [ ( row * 12 ) + ( col / 8 ) ] ;
return_val = 0 ;
block_pos = col % 8 ;
if ( block_val & ( 0x80 > > block_pos ) ) {
return_val = 1 ;
}
return return_val ;
2016-02-17 13:52:48 +03:00
}
2016-02-20 13:50:15 +03:00
void draw_bullseye ( char * pixelbuf , int image_width , int xoffset , int yoffset ) {
/* Central bullseye in Maxicode symbols */
int i , j ;
for ( j = 103 ; j < 196 ; j + + ) {
for ( i = 0 ; i < 93 ; i + + ) {
if ( bullseye_pixel ( j - 103 , i ) ) {
/* if(bullseye[(((j - 103) * 93) + i)] == 1) { */
* ( pixelbuf + ( image_width * j ) + ( image_width * yoffset ) + i + 99 + xoffset ) = ' 1 ' ;
}
}
}
2016-02-17 13:52:48 +03:00
}
2016-02-20 13:50:15 +03:00
void draw_hexagon ( char * pixelbuf , int image_width , int xposn , int yposn ) {
/* Put a hexagon into the pixel buffer */
int i , j ;
for ( i = 0 ; i < 12 ; i + + ) {
for ( j = 0 ; j < 10 ; j + + ) {
if ( hexagon [ ( i * 10 ) + j ] = = 1 ) {
* ( pixelbuf + ( image_width * i ) + ( image_width * yposn ) + xposn + j ) = ' 1 ' ;
}
}
}
2016-02-17 13:52:48 +03:00
}
2016-06-19 14:32:49 +03:00
void draw_letter ( char * pixelbuf , unsigned char letter , int xposn , int yposn , int textflags , int image_width , int image_height ) {
2016-02-20 13:50:15 +03:00
/* Put a letter into a position */
2016-06-19 14:32:49 +03:00
int skip , x , y , glyph_no , max_x , max_y ;
2016-02-20 13:50:15 +03:00
skip = 0 ;
if ( letter < 33 ) {
skip = 1 ;
}
2016-06-19 14:32:49 +03:00
2016-02-20 13:50:15 +03:00
if ( ( letter > 127 ) & & ( letter < 161 ) ) {
skip = 1 ;
}
2016-06-19 14:32:49 +03:00
if ( xposn < 0 | | yposn < 0 ) {
skip = 1 ;
}
2016-02-20 13:50:15 +03:00
if ( skip = = 0 ) {
if ( letter > 128 ) {
2016-02-22 22:07:09 +03:00
glyph_no = letter - 66 ;
2016-02-20 13:50:15 +03:00
} else {
glyph_no = letter - 33 ;
}
2016-02-20 17:38:40 +03:00
2016-06-19 14:32:49 +03:00
switch ( textflags ) {
case 1 : // small font 5x9
max_x = 5 ;
max_y = 9 ;
if ( xposn + max_x > = image_width ) {
max_x = image_width - xposn - 1 ;
}
if ( yposn + max_y > = image_height ) {
max_y = image_height - yposn - 1 ;
}
for ( y = 0 ; y < max_y ; y + + ) {
for ( x = 0 ; x < max_x ; x + + ) {
if ( small_font [ ( glyph_no * 9 ) + y ] & ( 0x10 > > x ) ) {
* ( pixelbuf + ( y * image_width ) + ( yposn * image_width ) + xposn + x ) = ' 1 ' ;
}
}
}
break ;
case 2 : // bold font -> twice the regular font
2016-07-18 22:14:56 +03:00
{
2016-07-04 13:08:08 +03:00
char * linePtr ;
2016-06-19 14:32:49 +03:00
max_x = 7 ;
max_y = 14 ;
if ( xposn + max_x + 1 > = image_width ) {
max_x = image_width - xposn - 2 ;
}
if ( yposn + max_y > = image_height ) {
max_y = image_height - yposn - 1 ;
}
2016-07-04 13:08:08 +03:00
linePtr = pixelbuf + ( yposn * image_width ) + xposn + 1 ;
2016-06-19 14:32:49 +03:00
for ( y = 0 ; y < max_y ; y + + ) {
char * pixelPtr = linePtr ;
int extra_dot = 0 ;
for ( x = 0 ; x < 7 ; x + + ) {
if ( ascii_font [ ( glyph_no * 14 ) + y ] & ( 0x40 > > x ) ) {
* pixelPtr = ' 1 ' ;
extra_dot = 1 ;
} else {
if ( extra_dot ) {
* pixelPtr = ' 1 ' ;
}
extra_dot = 0 ;
}
+ + pixelPtr ;
}
if ( extra_dot ) {
* pixelPtr = ' 1 ' ;
}
linePtr + = image_width ;
}
}
break ;
default : // regular font 7x15
max_x = 7 ;
max_y = 14 ;
if ( xposn + max_x > = image_width ) {
max_x = image_width - xposn - 1 ;
}
if ( yposn + max_y > = image_height ) {
max_y = image_height - yposn - 1 ;
}
for ( y = 0 ; y < max_y ; y + + ) {
for ( x = 0 ; x < 7 ; x + + ) {
if ( ascii_font [ ( glyph_no * 14 ) + y ] & ( 0x40 > > x ) ) {
* ( pixelbuf + ( y * image_width ) + ( yposn * image_width ) + xposn + x ) = ' 1 ' ;
}
}
}
break ;
2016-02-20 17:38:40 +03:00
}
2016-02-20 13:50:15 +03:00
}
2016-02-17 13:52:48 +03:00
}
2016-02-20 13:50:15 +03:00
/* Plot a string into the pixel buffer */
2016-06-19 14:32:49 +03:00
void draw_string ( char * pixbuf , char input_string [ ] , int xposn , int yposn , int textflags , int image_width , int image_height ) {
2016-04-30 14:35:26 +03:00
int i , string_length , string_left_hand , letter_width = 7 ;
2016-02-17 13:52:48 +03:00
2016-06-19 14:32:49 +03:00
switch ( textflags ) {
case 1 : // small font 5x9
letter_width = 5 ;
break ;
case 2 : // bold font -> width of the regular font + 1 extra dot + 1 extra space
letter_width = 9 ;
break ;
default : // regular font 7x15
letter_width = 7 ;
break ;
2016-04-30 14:35:26 +03:00
}
2016-06-19 14:32:49 +03:00
2016-02-20 13:50:15 +03:00
string_length = strlen ( input_string ) ;
2016-04-30 14:35:26 +03:00
string_left_hand = xposn - ( ( letter_width * string_length ) / 2 ) ;
2016-02-17 13:52:48 +03:00
2016-02-20 13:50:15 +03:00
for ( i = 0 ; i < string_length ; i + + ) {
2016-06-19 14:32:49 +03:00
draw_letter ( pixbuf , input_string [ i ] , string_left_hand + ( i * letter_width ) , yposn , textflags , image_width , image_height ) ;
2016-02-20 13:50:15 +03:00
}
2016-02-17 13:52:48 +03:00
}
2016-02-20 13:50:15 +03:00
int maxi_png_plot ( struct zint_symbol * symbol , int rotate_angle , int data_type ) {
int i , row , column , xposn , yposn ;
int image_height , image_width ;
char * pixelbuf ;
int error_number ;
int xoffset , yoffset ;
xoffset = symbol - > border_width + symbol - > whitespace_width ;
yoffset = symbol - > border_width ;
image_width = 300 + ( 2 * xoffset * 2 ) ;
image_height = 300 + ( 2 * yoffset * 2 ) ;
if ( ! ( pixelbuf = ( char * ) malloc ( image_width * image_height ) ) ) {
printf ( " Insifficient memory for pixel buffer " ) ;
return ZINT_ERROR_ENCODING_PROBLEM ;
} else {
for ( i = 0 ; i < ( image_width * image_height ) ; i + + ) {
* ( pixelbuf + i ) = ' 0 ' ;
}
}
draw_bullseye ( pixelbuf , image_width , ( 2 * xoffset ) , ( 2 * yoffset ) ) ;
for ( row = 0 ; row < symbol - > rows ; row + + ) {
yposn = row * 9 ;
for ( column = 0 ; column < symbol - > width ; column + + ) {
xposn = column * 10 ;
if ( module_is_set ( symbol , row , column ) ) {
if ( row & 1 ) {
/* Odd (reduced) row */
xposn + = 5 ;
draw_hexagon ( pixelbuf , image_width , xposn + ( 2 * xoffset ) , yposn + ( 2 * yoffset ) ) ;
} else {
/* Even (full) row */
draw_hexagon ( pixelbuf , image_width , xposn + ( 2 * xoffset ) , yposn + ( 2 * yoffset ) ) ;
}
}
}
}
if ( ( ( symbol - > output_options & BARCODE_BOX ) ! = 0 ) | | ( ( symbol - > output_options & BARCODE_BIND ) ! = 0 ) ) {
/* boundary bars */
draw_bar ( pixelbuf , 0 , image_width , 0 , symbol - > border_width * 2 , image_width , image_height ) ;
draw_bar ( pixelbuf , 0 , image_width , 300 + ( symbol - > border_width * 2 ) , symbol - > border_width * 2 , image_width , image_height ) ;
}
if ( ( symbol - > output_options & BARCODE_BOX ) ! = 0 ) {
/* side bars */
draw_bar ( pixelbuf , 0 , symbol - > border_width * 2 , 0 , image_height , image_width , image_height ) ;
draw_bar ( pixelbuf , 300 + ( ( symbol - > border_width + symbol - > whitespace_width + symbol - > whitespace_width ) * 2 ) , symbol - > border_width * 2 , 0 , image_height , image_width , image_height ) ;
}
error_number = png_to_file ( symbol , image_height , image_width , pixelbuf , rotate_angle , data_type ) ;
free ( pixelbuf ) ;
return error_number ;
2016-02-17 13:52:48 +03:00
}
/* Convert UTF-8 to Latin1 Codepage for the interpretation line */
2016-02-20 13:50:15 +03:00
void to_latin1 ( unsigned char source [ ] , unsigned char preprocessed [ ] ) {
int j , i , input_length ;
input_length = ustrlen ( source ) ;
j = 0 ;
i = 0 ;
while ( i < input_length ) {
switch ( source [ i ] ) {
case 0xC2 :
/* UTF-8 C2xxh */
/* Character range: C280h (latin: 80h) to C2BFh (latin: BFh) */
i + + ;
preprocessed [ j ] = source [ i ] ;
j + + ;
break ;
case 0xC3 :
/* UTF-8 C3xx */
/* Character range: C380h (latin: C0h) to C3BFh (latin: FFh) */
i + + ;
preprocessed [ j ] = source [ i ] + 64 ;
j + + ;
break ;
default :
/* Process ASCII (< 80h), all other unicode points are ignored */
if ( source [ i ] < 128 ) {
preprocessed [ j ] = source [ i ] ;
j + + ;
}
break ;
}
i + + ;
}
preprocessed [ j ] = ' \0 ' ;
return ;
2016-02-17 13:52:48 +03:00
}
2016-02-20 13:50:15 +03:00
int png_plot ( struct zint_symbol * symbol , int rotate_angle , int data_type ) {
int textdone , main_width , comp_offset , large_bar_count ;
char textpart [ 10 ] , addon [ 6 ] ;
float addon_text_posn , preset_height , large_bar_height ;
int i , r , textoffset , yoffset , xoffset , latch , image_width , image_height ;
char * pixelbuf ;
2016-06-19 14:32:49 +03:00
int addon_latch = 0 , textflags = 0 ;
2016-02-20 13:50:15 +03:00
int this_row , block_width , plot_height , plot_yposn , textpos ;
float row_height , row_posn ;
int error_number ;
int default_text_posn ;
int next_yposn ;
2016-02-17 13:52:48 +03:00
# ifndef _MSC_VER
2016-02-20 13:50:15 +03:00
unsigned char local_text [ ustrlen ( symbol - > text ) + 1 ] ;
2016-02-17 13:52:48 +03:00
# else
2016-02-20 13:50:15 +03:00
unsigned char * local_text = ( unsigned char * ) _alloca ( ustrlen ( symbol - > text ) + 1 ) ;
2016-02-17 13:52:48 +03:00
# endif
2016-02-20 13:50:15 +03:00
if ( symbol - > show_hrt ! = 0 ) {
2016-06-19 13:59:09 +03:00
/* Copy text from symbol */
2016-02-20 13:50:15 +03:00
to_latin1 ( symbol - > text , local_text ) ;
} else {
2016-06-19 13:59:09 +03:00
/* No text needed */
switch ( symbol - > symbology ) {
case BARCODE_EANX :
case BARCODE_EANX_CC :
case BARCODE_ISBNX :
case BARCODE_UPCA :
case BARCODE_UPCE :
case BARCODE_UPCA_CC :
case BARCODE_UPCE_CC :
/* For these symbols use dummy text to ensure formatting is done
* properly even if no text is required */
for ( i = 0 ; i < ustrlen ( symbol - > text ) ; i + + ) {
if ( symbol - > text [ i ] = = ' + ' ) {
local_text [ i ] = ' + ' ;
} else {
local_text [ i ] = ' ' ;
}
local_text [ ustrlen ( symbol - > text ) ] = ' \0 ' ;
}
break ;
default :
/* For everything else, just remove the text */
local_text [ 0 ] = ' \0 ' ;
break ;
}
2016-02-20 13:50:15 +03:00
}
textdone = 0 ;
main_width = symbol - > width ;
strcpy ( addon , " " ) ;
comp_offset = 0 ;
addon_text_posn = 0.0 ;
row_height = 0 ;
if ( symbol - > output_options & SMALL_TEXT ) {
2016-06-19 14:32:49 +03:00
textflags = 1 ;
}
else if ( symbol - > output_options & BOLD_TEXT ) {
textflags = 2 ;
2016-02-20 13:50:15 +03:00
}
if ( symbol - > height = = 0 ) {
symbol - > height = 50 ;
}
large_bar_count = 0 ;
preset_height = 0.0 ;
for ( i = 0 ; i < symbol - > rows ; i + + ) {
preset_height + = symbol - > row_height [ i ] ;
if ( symbol - > row_height [ i ] = = 0 ) {
large_bar_count + + ;
}
}
if ( large_bar_count = = 0 ) {
symbol - > height = preset_height ;
large_bar_height = 10 ;
} else {
large_bar_height = ( symbol - > height - preset_height ) / large_bar_count ;
}
while ( ! ( module_is_set ( symbol , symbol - > rows - 1 , comp_offset ) ) ) {
comp_offset + + ;
}
/* Certain symbols need whitespace otherwise characters get chopped off the sides */
if ( ( ( ( symbol - > symbology = = BARCODE_EANX ) & & ( symbol - > rows = = 1 ) ) | | ( symbol - > symbology = = BARCODE_EANX_CC ) )
| | ( symbol - > symbology = = BARCODE_ISBNX ) ) {
switch ( ustrlen ( local_text ) ) {
case 13 : /* EAN 13 */
case 16 :
case 19 :
if ( symbol - > whitespace_width = = 0 ) {
symbol - > whitespace_width = 10 ;
}
main_width = 96 + comp_offset ;
break ;
default :
main_width = 68 + comp_offset ;
}
}
if ( ( ( symbol - > symbology = = BARCODE_UPCA ) & & ( symbol - > rows = = 1 ) ) | | ( symbol - > symbology = = BARCODE_UPCA_CC ) ) {
if ( symbol - > whitespace_width = = 0 ) {
symbol - > whitespace_width = 10 ;
main_width = 96 + comp_offset ;
}
}
if ( ( ( symbol - > symbology = = BARCODE_UPCE ) & & ( symbol - > rows = = 1 ) ) | | ( symbol - > symbology = = BARCODE_UPCE_CC ) ) {
if ( symbol - > whitespace_width = = 0 ) {
symbol - > whitespace_width = 10 ;
main_width = 51 + comp_offset ;
}
}
latch = 0 ;
r = 0 ;
/* Isolate add-on text */
if ( is_extendable ( symbol - > symbology ) ) {
for ( i = 0 ; i < ustrlen ( local_text ) ; i + + ) {
if ( latch = = 1 ) {
addon [ r ] = local_text [ i ] ;
r + + ;
}
if ( symbol - > text [ i ] = = ' + ' ) {
latch = 1 ;
}
}
}
addon [ r ] = ' \0 ' ;
if ( ustrlen ( local_text ) ! = 0 ) {
textoffset = 9 ;
} else {
textoffset = 0 ;
}
2016-06-19 13:59:09 +03:00
2016-02-20 13:50:15 +03:00
xoffset = symbol - > border_width + symbol - > whitespace_width ;
yoffset = symbol - > border_width ;
image_width = 2 * ( symbol - > width + xoffset + xoffset ) ;
image_height = 2 * ( symbol - > height + textoffset + yoffset + yoffset ) ;
if ( ! ( pixelbuf = ( char * ) malloc ( image_width * image_height ) ) ) {
printf ( " Insufficient memory for pixel buffer " ) ;
return ZINT_ERROR_ENCODING_PROBLEM ;
} else {
for ( i = 0 ; i < ( image_width * image_height ) ; i + + ) {
* ( pixelbuf + i ) = ' 0 ' ;
}
}
if ( ( ( symbol - > output_options & BARCODE_BOX ) ! = 0 ) | | ( ( symbol - > output_options & BARCODE_BIND ) ! = 0 ) ) {
default_text_posn = image_height - 17 ;
} else {
default_text_posn = image_height - 17 - symbol - > border_width - symbol - > border_width ;
}
row_posn = textoffset + yoffset ;
next_yposn = textoffset + yoffset ;
row_height = 0 ;
/* Plot the body of the symbol to the pixel buffer */
for ( r = 0 ; r < symbol - > rows ; r + + ) {
this_row = symbol - > rows - r - 1 ; /* invert r otherwise plots upside down */
row_posn + = row_height ;
plot_yposn = next_yposn ;
if ( symbol - > row_height [ this_row ] = = 0 ) {
row_height = large_bar_height ;
} else {
row_height = symbol - > row_height [ this_row ] ;
}
next_yposn = ( int ) ( row_posn + row_height ) ;
plot_height = next_yposn - plot_yposn ;
i = 0 ;
if ( module_is_set ( symbol , this_row , 0 ) ) {
latch = 1 ;
} else {
latch = 0 ;
}
do {
block_width = 0 ;
do {
block_width + + ;
} while ( module_is_set ( symbol , this_row , i + block_width ) = = module_is_set ( symbol , this_row , i ) ) ;
if ( ( addon_latch = = 0 ) & & ( r = = 0 ) & & ( i > main_width ) ) {
plot_height = ( int ) ( row_height - 5.0 ) ;
plot_yposn = ( int ) ( row_posn - 5.0 ) ;
addon_text_posn = row_posn + row_height - 8.0 ;
addon_latch = 1 ;
}
if ( latch = = 1 ) {
/* a bar */
draw_bar ( pixelbuf , ( i + xoffset ) * 2 , block_width * 2 , plot_yposn * 2 , plot_height * 2 , image_width , image_height ) ;
latch = 0 ;
} else {
/* a space */
latch = 1 ;
}
i + = block_width ;
} while ( i < symbol - > width ) ;
}
xoffset + = comp_offset ;
if ( ( ( ( symbol - > symbology = = BARCODE_EANX ) & & ( symbol - > rows = = 1 ) ) | | ( symbol - > symbology = = BARCODE_EANX_CC ) ) | | ( symbol - > symbology = = BARCODE_ISBNX ) ) {
/* guard bar extensions and text formatting for EAN8 and EAN13 */
switch ( ustrlen ( local_text ) ) {
case 8 : /* EAN-8 */
case 11 :
case 14 :
draw_bar ( pixelbuf , ( 0 + xoffset ) * 2 , 1 * 2 , ( 4 + ( int ) yoffset ) * 2 , 5 * 2 , image_width , image_height ) ;
draw_bar ( pixelbuf , ( 2 + xoffset ) * 2 , 1 * 2 , ( 4 + ( int ) yoffset ) * 2 , 5 * 2 , image_width , image_height ) ;
draw_bar ( pixelbuf , ( 32 + xoffset ) * 2 , 1 * 2 , ( 4 + ( int ) yoffset ) * 2 , 5 * 2 , image_width , image_height ) ;
draw_bar ( pixelbuf , ( 34 + xoffset ) * 2 , 1 * 2 , ( 4 + ( int ) yoffset ) * 2 , 5 * 2 , image_width , image_height ) ;
draw_bar ( pixelbuf , ( 64 + xoffset ) * 2 , 1 * 2 , ( 4 + ( int ) yoffset ) * 2 , 5 * 2 , image_width , image_height ) ;
draw_bar ( pixelbuf , ( 66 + xoffset ) * 2 , 1 * 2 , ( 4 + ( int ) yoffset ) * 2 , 5 * 2 , image_width , image_height ) ;
for ( i = 0 ; i < 4 ; i + + ) {
2016-06-19 13:59:09 +03:00
textpart [ i ] = local_text [ i ] ;
2016-02-20 13:50:15 +03:00
}
textpart [ 4 ] = ' \0 ' ;
textpos = 2 * ( 17 + xoffset ) ;
2016-06-19 14:32:49 +03:00
draw_string ( pixelbuf , textpart , textpos , default_text_posn , textflags , image_width , image_height ) ;
2016-02-20 13:50:15 +03:00
for ( i = 0 ; i < 4 ; i + + ) {
2016-06-19 13:59:09 +03:00
textpart [ i ] = local_text [ i + 4 ] ;
2016-02-20 13:50:15 +03:00
}
textpart [ 4 ] = ' \0 ' ;
textpos = 2 * ( 50 + xoffset ) ;
2016-06-19 14:32:49 +03:00
draw_string ( pixelbuf , textpart , textpos , default_text_posn , textflags , image_width , image_height ) ;
2016-02-20 13:50:15 +03:00
textdone = 1 ;
switch ( strlen ( addon ) ) {
case 2 :
textpos = 2 * ( xoffset + 86 ) ;
2016-06-19 14:32:49 +03:00
draw_string ( pixelbuf , addon , textpos , image_height - ( addon_text_posn * 2 ) - 13 , textflags , image_width , image_height ) ;
2016-02-20 13:50:15 +03:00
break ;
case 5 :
textpos = 2 * ( xoffset + 100 ) ;
2016-06-19 14:32:49 +03:00
draw_string ( pixelbuf , addon , textpos , image_height - ( addon_text_posn * 2 ) - 13 , textflags , image_width , image_height ) ;
2016-02-20 13:50:15 +03:00
break ;
}
break ;
case 13 : /* EAN 13 */
case 16 :
case 19 :
draw_bar ( pixelbuf , ( 0 + xoffset ) * 2 , 1 * 2 , ( 4 + ( int ) yoffset ) * 2 , 5 * 2 , image_width , image_height ) ;
draw_bar ( pixelbuf , ( 2 + xoffset ) * 2 , 1 * 2 , ( 4 + ( int ) yoffset ) * 2 , 5 * 2 , image_width , image_height ) ;
draw_bar ( pixelbuf , ( 46 + xoffset ) * 2 , 1 * 2 , ( 4 + ( int ) yoffset ) * 2 , 5 * 2 , image_width , image_height ) ;
draw_bar ( pixelbuf , ( 48 + xoffset ) * 2 , 1 * 2 , ( 4 + ( int ) yoffset ) * 2 , 5 * 2 , image_width , image_height ) ;
draw_bar ( pixelbuf , ( 92 + xoffset ) * 2 , 1 * 2 , ( 4 + ( int ) yoffset ) * 2 , 5 * 2 , image_width , image_height ) ;
draw_bar ( pixelbuf , ( 94 + xoffset ) * 2 , 1 * 2 , ( 4 + ( int ) yoffset ) * 2 , 5 * 2 , image_width , image_height ) ;
2016-06-19 13:59:09 +03:00
textpart [ 0 ] = local_text [ 0 ] ;
2016-02-20 13:50:15 +03:00
textpart [ 1 ] = ' \0 ' ;
textpos = 2 * ( - 7 + xoffset ) ;
2016-06-19 14:32:49 +03:00
draw_string ( pixelbuf , textpart , textpos , default_text_posn , textflags , image_width , image_height ) ;
2016-02-20 13:50:15 +03:00
for ( i = 0 ; i < 6 ; i + + ) {
2016-06-19 13:59:09 +03:00
textpart [ i ] = local_text [ i + 1 ] ;
2016-02-20 13:50:15 +03:00
}
textpart [ 6 ] = ' \0 ' ;
textpos = 2 * ( 24 + xoffset ) ;
2016-06-19 14:32:49 +03:00
draw_string ( pixelbuf , textpart , textpos , default_text_posn , textflags , image_width , image_height ) ;
2016-02-20 13:50:15 +03:00
for ( i = 0 ; i < 6 ; i + + ) {
2016-06-19 13:59:09 +03:00
textpart [ i ] = local_text [ i + 7 ] ;
2016-02-20 13:50:15 +03:00
}
textpart [ 6 ] = ' \0 ' ;
textpos = 2 * ( 71 + xoffset ) ;
2016-06-19 14:32:49 +03:00
draw_string ( pixelbuf , textpart , textpos , default_text_posn , textflags , image_width , image_height ) ;
2016-02-20 13:50:15 +03:00
textdone = 1 ;
switch ( strlen ( addon ) ) {
case 2 :
textpos = 2 * ( xoffset + 114 ) ;
2016-06-19 14:32:49 +03:00
draw_string ( pixelbuf , addon , textpos , image_height - ( addon_text_posn * 2 ) - 13 , textflags , image_width , image_height ) ;
2016-02-20 13:50:15 +03:00
break ;
case 5 :
textpos = 2 * ( xoffset + 128 ) ;
2016-06-19 14:32:49 +03:00
draw_string ( pixelbuf , addon , textpos , image_height - ( addon_text_posn * 2 ) - 13 , textflags , image_width , image_height ) ;
2016-02-20 13:50:15 +03:00
break ;
}
break ;
}
}
if ( ( ( symbol - > symbology = = BARCODE_UPCA ) & & ( symbol - > rows = = 1 ) ) | | ( symbol - > symbology = = BARCODE_UPCA_CC ) ) {
/* guard bar extensions and text formatting for UPCA */
latch = 1 ;
i = 0 + comp_offset ;
do {
block_width = 0 ;
do {
block_width + + ;
} while ( module_is_set ( symbol , symbol - > rows - 1 , i + block_width ) = = module_is_set ( symbol , symbol - > rows - 1 , i ) ) ;
if ( latch = = 1 ) {
/* a bar */
draw_bar ( pixelbuf , ( i + xoffset - comp_offset ) * 2 , block_width * 2 , ( 4 + ( int ) yoffset ) * 2 , 5 * 2 , image_width , image_height ) ;
latch = 0 ;
} else {
/* a space */
latch = 1 ;
}
i + = block_width ;
} while ( i < 11 + comp_offset ) ;
draw_bar ( pixelbuf , ( 46 + xoffset ) * 2 , 1 * 2 , ( 4 + ( int ) yoffset ) * 2 , 5 * 2 , image_width , image_height ) ;
draw_bar ( pixelbuf , ( 48 + xoffset ) * 2 , 1 * 2 , ( 4 + ( int ) yoffset ) * 2 , 5 * 2 , image_width , image_height ) ;
latch = 1 ;
i = 85 + comp_offset ;
do {
block_width = 0 ;
do {
block_width + + ;
} while ( module_is_set ( symbol , symbol - > rows - 1 , i + block_width ) = = module_is_set ( symbol , symbol - > rows - 1 , i ) ) ;
if ( latch = = 1 ) {
/* a bar */
draw_bar ( pixelbuf , ( i + xoffset - comp_offset ) * 2 , block_width * 2 , ( 4 + ( int ) yoffset ) * 2 , 5 * 2 , image_width , image_height ) ;
latch = 0 ;
} else {
/* a space */
latch = 1 ;
}
i + = block_width ;
} while ( i < 96 + comp_offset ) ;
2016-06-19 13:59:09 +03:00
textpart [ 0 ] = local_text [ 0 ] ;
2016-02-20 13:50:15 +03:00
textpart [ 1 ] = ' \0 ' ;
textpos = 2 * ( - 5 + xoffset ) ;
2016-06-19 14:32:49 +03:00
draw_string ( pixelbuf , textpart , textpos , default_text_posn , textflags , image_width , image_height ) ;
2016-02-20 13:50:15 +03:00
for ( i = 0 ; i < 5 ; i + + ) {
2016-06-19 13:59:09 +03:00
textpart [ i ] = local_text [ i + 1 ] ;
2016-02-20 13:50:15 +03:00
}
textpart [ 5 ] = ' \0 ' ;
textpos = 2 * ( 27 + xoffset ) ;
2016-06-19 14:32:49 +03:00
draw_string ( pixelbuf , textpart , textpos , default_text_posn , textflags , image_width , image_height ) ;
2016-02-20 13:50:15 +03:00
for ( i = 0 ; i < 5 ; i + + ) {
2016-06-19 13:59:09 +03:00
textpart [ i ] = local_text [ i + 6 ] ;
2016-02-20 13:50:15 +03:00
}
textpart [ 6 ] = ' \0 ' ;
textpos = 2 * ( 68 + xoffset ) ;
2016-06-19 14:32:49 +03:00
draw_string ( pixelbuf , textpart , textpos , default_text_posn , textflags , image_width , image_height ) ;
2016-06-19 13:59:09 +03:00
textpart [ 0 ] = local_text [ 11 ] ;
2016-02-20 13:50:15 +03:00
textpart [ 1 ] = ' \0 ' ;
textpos = 2 * ( 100 + xoffset ) ;
2016-06-19 14:32:49 +03:00
draw_string ( pixelbuf , textpart , textpos , default_text_posn , textflags , image_width , image_height ) ;
2016-02-20 13:50:15 +03:00
textdone = 1 ;
switch ( strlen ( addon ) ) {
case 2 :
textpos = 2 * ( xoffset + 116 ) ;
2016-06-19 14:32:49 +03:00
draw_string ( pixelbuf , addon , textpos , image_height - ( addon_text_posn * 2 ) - 13 , textflags , image_width , image_height ) ;
2016-02-20 13:50:15 +03:00
break ;
case 5 :
textpos = 2 * ( xoffset + 130 ) ;
2016-06-19 14:32:49 +03:00
draw_string ( pixelbuf , addon , textpos , image_height - ( addon_text_posn * 2 ) - 13 , textflags , image_width , image_height ) ;
2016-02-20 13:50:15 +03:00
break ;
}
}
if ( ( ( symbol - > symbology = = BARCODE_UPCE ) & & ( symbol - > rows = = 1 ) ) | | ( symbol - > symbology = = BARCODE_UPCE_CC ) ) {
/* guard bar extensions and text formatting for UPCE */
draw_bar ( pixelbuf , ( 0 + xoffset ) * 2 , 1 * 2 , ( 4 + ( int ) yoffset ) * 2 , 5 * 2 , image_width , image_height ) ;
draw_bar ( pixelbuf , ( 2 + xoffset ) * 2 , 1 * 2 , ( 4 + ( int ) yoffset ) * 2 , 5 * 2 , image_width , image_height ) ;
draw_bar ( pixelbuf , ( 46 + xoffset ) * 2 , 1 * 2 , ( 4 + ( int ) yoffset ) * 2 , 5 * 2 , image_width , image_height ) ;
draw_bar ( pixelbuf , ( 48 + xoffset ) * 2 , 1 * 2 , ( 4 + ( int ) yoffset ) * 2 , 5 * 2 , image_width , image_height ) ;
draw_bar ( pixelbuf , ( 50 + xoffset ) * 2 , 1 * 2 , ( 4 + ( int ) yoffset ) * 2 , 5 * 2 , image_width , image_height ) ;
2016-06-19 13:59:09 +03:00
textpart [ 0 ] = local_text [ 0 ] ;
2016-02-20 13:50:15 +03:00
textpart [ 1 ] = ' \0 ' ;
textpos = 2 * ( - 5 + xoffset ) ;
2016-06-19 14:32:49 +03:00
draw_string ( pixelbuf , textpart , textpos , default_text_posn , textflags , image_width , image_height ) ;
2016-02-20 13:50:15 +03:00
for ( i = 0 ; i < 6 ; i + + ) {
2016-06-19 13:59:09 +03:00
textpart [ i ] = local_text [ i + 1 ] ;
2016-02-20 13:50:15 +03:00
}
textpart [ 6 ] = ' \0 ' ;
textpos = 2 * ( 24 + xoffset ) ;
2016-06-19 14:32:49 +03:00
draw_string ( pixelbuf , textpart , textpos , default_text_posn , textflags , image_width , image_height ) ;
2016-06-19 13:59:09 +03:00
textpart [ 0 ] = local_text [ 7 ] ;
2016-02-20 13:50:15 +03:00
textpart [ 1 ] = ' \0 ' ;
textpos = 2 * ( 55 + xoffset ) ;
2016-06-19 14:32:49 +03:00
draw_string ( pixelbuf , textpart , textpos , default_text_posn , textflags , image_width , image_height ) ;
2016-02-20 13:50:15 +03:00
textdone = 1 ;
switch ( strlen ( addon ) ) {
case 2 :
textpos = 2 * ( xoffset + 70 ) ;
2016-06-19 14:32:49 +03:00
draw_string ( pixelbuf , addon , textpos , image_height - ( addon_text_posn * 2 ) - 13 , textflags , image_width , image_height ) ;
2016-02-20 13:50:15 +03:00
break ;
case 5 :
textpos = 2 * ( xoffset + 84 ) ;
2016-06-19 14:32:49 +03:00
draw_string ( pixelbuf , addon , textpos , image_height - ( addon_text_posn * 2 ) - 13 , textflags , image_width , image_height ) ;
2016-02-20 13:50:15 +03:00
break ;
}
}
xoffset - = comp_offset ;
/* Put boundary bars or box around symbol */
if ( ( ( symbol - > output_options & BARCODE_BOX ) ! = 0 ) | | ( ( symbol - > output_options & BARCODE_BIND ) ! = 0 ) ) {
/* boundary bars */
draw_bar ( pixelbuf , 0 , ( symbol - > width + xoffset + xoffset ) * 2 , textoffset * 2 , symbol - > border_width * 2 , image_width , image_height ) ;
draw_bar ( pixelbuf , 0 , ( symbol - > width + xoffset + xoffset ) * 2 , ( textoffset + symbol - > height + symbol - > border_width ) * 2 , symbol - > border_width * 2 , image_width , image_height ) ;
if ( ( symbol - > output_options & BARCODE_BIND ) ! = 0 ) {
if ( ( symbol - > rows > 1 ) & & ( is_stackable ( symbol - > symbology ) = = 1 ) ) {
/* row binding */
for ( r = 1 ; r < symbol - > rows ; r + + ) {
draw_bar ( pixelbuf , xoffset * 2 , symbol - > width * 2 , ( ( r * row_height ) + textoffset + yoffset - 1 ) * 2 , 2 * 2 , image_width , image_height ) ;
}
}
}
}
if ( ( symbol - > output_options & BARCODE_BOX ) ! = 0 ) {
/* side bars */
draw_bar ( pixelbuf , 0 , symbol - > border_width * 2 , textoffset * 2 , ( symbol - > height + ( 2 * symbol - > border_width ) ) * 2 , image_width , image_height ) ;
draw_bar ( pixelbuf , ( symbol - > width + xoffset + xoffset - symbol - > border_width ) * 2 , symbol - > border_width * 2 , textoffset * 2 , ( symbol - > height + ( 2 * symbol - > border_width ) ) * 2 , image_width , image_height ) ;
}
/* Put the human readable text at the bottom */
if ( ( textdone = = 0 ) & & ( ustrlen ( local_text ) ! = 0 ) ) {
textpos = ( image_width / 2 ) ;
2016-06-19 14:32:49 +03:00
draw_string ( pixelbuf , ( char * ) local_text , textpos , default_text_posn , textflags , image_width , image_height ) ;
2016-02-20 13:50:15 +03:00
}
error_number = png_to_file ( symbol , image_height , image_width , pixelbuf , rotate_angle , data_type ) ;
free ( pixelbuf ) ;
return error_number ;
2016-02-17 13:52:48 +03:00
}
# ifndef NO_PNG
2016-02-20 13:50:15 +03:00
int png_handle ( struct zint_symbol * symbol , int rotate_angle ) {
int error ;
if ( symbol - > symbology = = BARCODE_MAXICODE ) {
error = maxi_png_plot ( symbol , rotate_angle , PNG_DATA ) ;
} else {
2016-02-17 13:52:48 +03:00
2016-02-20 13:50:15 +03:00
error = png_plot ( symbol , rotate_angle , PNG_DATA ) ;
}
2016-02-17 13:52:48 +03:00
2016-02-20 13:50:15 +03:00
return error ;
2016-02-17 13:52:48 +03:00
}
# endif /* NO_PNG */
2016-02-20 13:50:15 +03:00
int bmp_handle ( struct zint_symbol * symbol , int rotate_angle ) {
int error ;
2016-02-17 13:52:48 +03:00
2016-02-20 13:50:15 +03:00
if ( symbol - > symbology = = BARCODE_MAXICODE ) {
error = maxi_png_plot ( symbol , rotate_angle , BMP_DATA ) ;
} else {
error = png_plot ( symbol , rotate_angle , BMP_DATA ) ;
}
2016-02-17 13:52:48 +03:00
2016-02-20 13:50:15 +03:00
return error ;
2016-02-17 13:52:48 +03:00
}