[Perl]生成Code39条码图片(BMP格式)

There's more than one way to do it!
https://metacpan.org http://perlmonks.org
回复
头像
523066680
Administrator
Administrator
帖子: 573
注册时间: 2016年07月19日 12:14
联系:

[Perl]生成Code39条码图片(BMP格式)

帖子 523066680 »

=info
Edit: vicyang
Mail: 523066680@163.com
Date: 2016-06
=cut

use utf8;
use IO::Handle;
STDOUT->autoflush(1);
binmode(STDOUT, ":encoding(gbk)");

$inp = "0101000078";

my $file = "${inp}.bmp";
open $WRT, ">:raw", $file or die $!;

our $multiple = 2.0; #缩放比例
our $width = 805;
our $height = 156;
our @coord;
our @code = split("", "*${inp}*");

our @scale =
(4,4,4,4,4,4,4,4,4, 2);

our %list =
(
'0' => [1,1,1,2,2,1,2,1,1, 1],
'1' => [2,1,1,2,1,1,1,1,2, 1],
'2' => [1,1,2,2,1,1,1,1,2, 1],
'3' => [2,1,2,2,1,1,1,1,1, 1],
'4' => [1,1,1,2,2,1,1,1,2, 1],
'5' => [2,1,1,2,2,1,1,1,1, 1],
'6' => [1,1,2,2,2,1,1,1,1, 1],
'7' => [1,1,1,2,1,1,2,1,2, 1],
'8' => [2,1,1,2,1,1,2,1,1, 1],
'9' => [1,1,2,2,1,1,2,1,1, 1],
'*' => [1,2,1,1,2,1,2,1,1, 1],
);

my $sum = 0;
for my $e ( @code )
{
for my $i ( 0 .. $#{$list{$e}} )
{
$sum += $list{$e}->[$i] * $scale[$i];
}
}

$width = $sum;
printf "width: %d, height: %d, bytes in line: %d\n", $width, $height, $width * 3;

#补充字节长度(每行字节数必须整除4)
our $byte_plus;

if ( ($width * 3) % 4 != 0 ) #每个像素包含24位色深 = 3 bytes
{
$byte_plus = 4 - ($width * 3) % 4;
}
else
{
$byte_plus = 0;
}

printf "byte plus: %d\n", $byte_plus;

FILL_ZERO(\@coord, $width, $height);

my $x = 0.0;
my $y = 0.0; #起点
my $h = $height; #高度 同图片高度
my $color;

my $i = 0;
my $next_x;

for my $e ( @code )
{
for my $idx ( 0 .. $#{ $list{$e} } )
{
if ($i == 0)
{
$color = "\x00\x00\x00";
}
else
{
$color = "\xFF\xFF\xFF";
}

$next_x = $list{$e}->[$idx] * $scale[$idx];

DRAW_RECT(\@coord, $x, $x + $next_x, $y, $y+$h, $color);

$x += $next_x;
$i = 1 - $i;
}
}

WRITE_HEAD($width, $height, $file);
WRITE_BMP(\@coord, $width, $height, $file);

exit;

sub WRITE_HEAD
{
my ($width, $height, $file) = @_;

open $WRT, ">>:raw", $file or die $!;

our $v;
our ($type, $bfSize, $res1, $res2, $offset) =
(0x4d42, 0, 0, 0, 122 );

$v = pack '(SLSSL)', ($type, $bfSize, $res1, $res2, $offset);

print $WRT $v;

our ($headSize, $piWidth, $piHeight, $planes, $bitCount, $Compress, $PixSize, $BC, $BD, $BE, $BF) =
(108, $width, $height, 1, 24, 0, 0, 0, 0, 0, 0);
#Compress = 0 时, PixSize可以填0

$v = pack '(L3S2L6)',
($headSize, $piWidth, $piHeight, $planes, $bitCount, $Compress, $PixSize, $BC, $BD, $BE, $BF);

print $WRT $v;

#Windows的BMP规定一行所占的字节数须是 4字节的倍数,不足的以0填充
print $WRT "\x00"x(122-54); #文件头部分补充

close $WRT;
}

sub DRAW_RECT
{
my ($ref, $x1, $x2, $y1, $y2, $color) = @_;

for my $ROW ( $y1 .. $y2 )
{
for my $COL ( $x1 .. $x2 )
{
$coord[$ROW][$COL] = $color;
}
}
}

sub FILL_ZERO
{
my ($ref, $width, $height) = @_;

for my $ROW (0 .. $height-1 )
{
for my $COL (0 .. $width - 1 )
{
$ref->[$ROW][$COL] = "\xFF\xFF\xFF";
}
}
}

sub WRITE_BMP
{
our $byte_plus;
my ($ref, $width, $height, $file) = @_;
open $WRT, ">>:raw", $file or die $!;

for my $ROW (0 .. $height-1)
{
for my $COL (0 .. $width - 1 )
{
print $WRT $ref->[$ROW][$COL];
}
print $WRT "\x00"x$byte_plus;
}

close $WRT;
}
回复

在线用户

正浏览此版面之用户: 没有注册用户 和 3 访客