在PHP中创建1位位图(单色)。

11

我正在寻找一种从具有以下内容的字符串中编写1位图像的可能性:

$str = "001011000111110000";

0代表白色,1代表黑色。BMP文件将是18 x 1像素。

我不想要一个24位的BMP,而是一个真正的1位BMP。

有人知道在PHP中如何编写头文件和转换方法吗?

3个回答

5

这是一个有点奇怪的请求 :)

首先,你需要使用php-gd。一般来说,在安装拥有良好软件源的操作系统上安装php时会自动包含它,但如果没有自动包含,你可以在这里获取安装指南;

http://www.php.net/manual/zh/image.setup.php

首先,我们需要确定图片的宽度大小,而高度显然总是为1。

所以;

$str = $_GET['str'];
$img_width = strlen($str);

strlen函数将告诉我们$str字符串中有多少个字符,并且由于我们为每个字符提供一个像素,因此字符的数量将给出所需的宽度。

为了方便起见,将字符串拆分为数组-每个元素对应于每个单独的像素。

$color_array = str_split($str);

现在,让我们设置一个“指针”,用于确定我们正在绘制的像素。这是PHP,所以您不需要初始化它,但保持整洁会更好。
$current_px = (int) 0;

现在您可以初始化GD并开始制作图像;

$im = imagecreatetruecolor($img_width, 1);
// Initialise colours;
$black = imagecolorallocate($im, 0, 0, 0);
$white = imagecolorallocate($im, 255, 255, 255);
// Now, start running through the array
foreach ($color_array as $y)
{
  if ($y == 1)
  {
    imagesetpixel ( $im, $current_px , 1 , $black );
  }
  $current_px++; // Don't need to "draw" a white pixel for 0. Just draw nothing and add to the counter.
}

这将绘制您的图像,然后您只需要显示它即可。
header('Content-type: image/png');
imagepng($im);
imagedestroy($im);

请注意,$white声明根本不需要 - 我只是留下它来让你了解如何使用gd声明不同的颜色。
在使用它之前,您可能需要对其进行一些调试 - 我已经很久没有使用GD了。无论如何,希望这可以帮助到您!

谢谢您的回复,但我正在寻找一个能够以纯php生成1位单色位图的工具。最终,我找到了正确的方法和解决方案,现在我可以生成一个正确的1位单色位图!通过这个解决方案,我可以生成一个尺寸最小、适合打印输出的条码光栅图像。 - htmlandrea
啊,我明白了。好的,我找到了一些类可以帮助你使用GD创建BMP图像;你可以在这里找到它们:http://www.phpclasses.org/package/5991-PHP-Load-and-save-images-in-the-BMP-format.html我希望剩下的信息对你有用 :) - Eoghan

2

这并不是一个奇怪的要求。

我完全同意问题的目的,事实上我需要处理一些1位单色图像。

答案是:

  • 在PHP网站上,GD文档不是很好。
  • 当你想从头创建一张图片时,你必须使用imagecreate()imagecreatetruecolor()
  • 似乎刚才提到的两种方法(函数)都不能从头创建1位图像。
  • 我通过创建一个外部图像,1位单色png,用imagecreatefrompng()加载它来解决了这个问题。

此外:我刚刚从官方Bitbucket仓库下载了官方库的开源代码。

我在gd.h中发现了什么?:

上述函数的定义:

/* Functions to manipulate images. */

/* Creates a palette-based image (up to 256 colors). */
BGD_DECLARE(gdImagePtr) gdImageCreate (int sx, int sy);

/* An alternate name for the above (2.0). */
 \#define gdImageCreatePalette gdImageCreate

/* Creates a truecolor image (millions of colors). */
BGD_DECLARE(gdImagePtr) gdImageCreateTrueColor (int sx, int sy);

所以,“官方”的解决方案是:使用imagecreate()(它封装了gdImageCreate() GD函数)创建一个双色调调色板图像。
“替代”方案是创建一个外部图像,1位单色调png,并像上面所说的那样使用imagecreatefrompng()

你能否给出一个代码示例:“我通过创建一个外部图像,1位单色PNG,使用imagecreatefrompng()函数加载它来解决问题。” - Orlin Bobchev

1

如果没有gd或imagemagick,您可以使用pack来将机器字节顺序转换为小端字节顺序,并使用一些处理字符串的函数创建单色位图像。有关参考和更多详细信息,您可以查看维基百科页面位图文件格式或此脚本在3v4l上。

对于这个示例,我将使用更复杂的输入,这只是为了更好地解释创建位图时每行应如何对齐;

<?php
$pixelDataArray = array(
    "11101010111",
    "10101010101",
    "11101110111",
    "10001010100",
    "10001010100",
);

首先将输入转换为像素数组或位图数据,像素数组上的每一行都应该是dword/32bit/4bytes对齐的。

$pixelWidth = strlen($pixelDataArray[0]);
$pixelHeight = count($pixelDataArray);

$dwordAlignment = 32 - ($pixelWidth % 32);
if ($dwordAlignment == 32) {
    $dwordAlignment = 0;
}
$dwordAlignedLength = $pixelWidth + $dwordAlignment;

现在我们可以适当地对齐字符串,然后将其转换为1字节整数数组,最后转换为二进制字符串。
$pixelArray = '';
foreach (array_reverse($pixelDataArray) as $row) {
    $dwordAlignedPixelRow = str_pad($row, $dwordAlignedLength, '0', STR_PAD_RIGHT);
    $integerPixelRow = array_map('bindec', str_split($dwordAlignedPixelRow, 8));
    $pixelArray .= implode('', array_map('chr', $integerPixelRow));
}
$pixelArraySize = \strlen($pixelArray);

然后让我们建立颜色表

$colorTable = pack(
    'CCCxCCCx',
    //blue, green, red
    255,  255,   255, // 0 color
    0,    0,     0    // 1 color
);
$colorTableSize = \strlen($colorTable);

现在,为了更好地支持BITMAPINFOHEADER(40字节的头部),将使用位图信息头。

$dibHeaderSize = 40;
$colorPlanes = 1;
$bitPerPixel = 1;
$compressionMethod = 0; //BI_RGB/NONE
$horizontal_pixel_per_meter = 2835;
$vertical_pixel_per_meter = 2835;
$colorInPalette = 2;
$importantColors = 0;
$dibHeader = \pack('VVVvvVVVVVV', $dibHeaderSize, $pixelWidth, $pixelHeight, $colorPlanes, $bitPerPixel, $compressionMethod, $pixelArraySize, $horizontal_pixel_per_meter, $vertical_pixel_per_meter, $colorInPalette, $importantColors);

最后一部分是文件头

$bmpFileHeaderSize = 14;
$pixelArrayOffset = $bmpFileHeaderSize + $dibHeaderSize + $colorTableSize;
$fileSize = $pixelArrayOffset + $pixelArraySize;
$bmpFileHeader = pack('CCVxxxxV', \ord('B'), \ord('M'), $fileSize, $pixelArrayOffset);

现在只需要将所有内容串联成一个字符串,它就可以被使用了。
$bmpFile = $bmpFileHeader . $dibHeader . $colorTable . $pixelArray;
$bmpBase64File = base64_encode($bmpFile);
?>
<img src="data:image/bitmap;base64, <?= $bmpBase64File ?>" style="image-rendering: crisp-edges;width: 100px;"/>

<img src="data:image/bitmap;base64, Qk1SAAAAAAAAAD4AAAAoAAAACwAAAAUAAAABAAEAAAAAABQAAAATCwAAEwsAAAIAAAAAAAAA////AAAAAACKgAAAioAAAO7gAACqoAAA6uAAAA==" style="image-rendering: crisp-edges;width: 100px;height: ;"/>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接