将BASE64编码的图像打印到FPDF文档中


print BASE64 coded image into a FPDF document

我在数据库中存储了一些基于base64的图像。是否可以使用FPDF将这些数据直接打印在PDF文档中?

图像的数据结构

data:image/png;base64,iVBORw0KGgoAAAANSUhEUg7AAAfQAAACWCAYAAAAonXpvAAAfgUlEQVR4Ae2dC9BuVVnHuSN3QaBENA9h5A2IcJxMj8hUkymoQDfClIkmrQZr1EydMqapnKRMc8JmHLBBHadJJaV0lKQDZCmCQiqQ2KERUFARDhcFDpx /33W tznPe/ 3ttaa9/ a2Z9/32Xvt5nvVbl2evtdfee9dtS27bt4mACJmACJm8ACJtBvArv123xbbwImYAImYAImIAJ26K4HJmACJmACJjAAAnboAyhEZ8EETMAETMAE7NBdB0zABEzABExgAATs0AdQiM6CCZiACZiACdihuw6YgAmYgAmYwAAI2KEPoBCdBRMwARMwAROwQ3cdMAETMAETMIEBELBDH0AhOgsmYAImYAImYIfuOmACJm

我认为$pdf->imagepng()应该是FPDF中正确的函数。

虽然评论建议使用TCPDF解决方案,但我确实想声明,有一种方法可以完全使用FPDF来实现这一点。思维过程是这样的:

  1. 使用explode从URI中剥离data:image/png;base64,
  2. base64_decode解码URI
  3. 使用file_put_contents将解码后的数据保存到PNG文件中
  4. 生成PDF并使用Image添加PNG文件
  5. unlink删除PNG文件

永远记得检查错误。如果映像未能保存到服务器,您显然不想继续执行。请务必始终严格检查函数是否返回false!

这是我的解决方案。在这个例子中,我使用了一个小图像作为一个小URI。

const TEMPIMGLOC = 'tempimg.png';
$dataURI    = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAPCAMAAADarb8dAAAABlBMVEUAAADtHCTeKUOwAAAAF0lEQVR4AWOgAWBE4zISkMbDZQRyaQkABl4ADHmgWUYAAAAASUVORK5CYII=";
$dataPieces = explode(',',$dataURI);
$encodedImg = $dataPieces[1];
$decodedImg = base64_decode($encodedImg);
//  Check if image was properly decoded
if( $decodedImg!==false )
{
    //  Save image to a temporary location
    if( file_put_contents(TEMPIMGLOC,$decodedImg)!==false )
    {
        //  Open new PDF document and print image
        $pdf = new FPDF();
        $pdf->AddPage();
        $pdf->Image(TEMPIMGLOC);
        $pdf->Output();
        //  Delete image from server
        unlink(TEMPIMGLOC);
    }
}

我知道这是一个老话题,但有一种更简单的方法可以解决这个问题。只需尝试以下简单步骤:

  1. 剥离数据:image/png;base64使用爆炸从URI
  2. data://text/plain;base64,与剥离的URI中剩下的内容连接起来
  3. 使用结果字符串(base64)作为FPDF Image()的参数

示例:

$dataURI = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAPCAMAAADarb8dAAAABlBMVEUAAADtHCTeKUOwAAAAF0lEQVR4AWOgAWBE4zISkMbDZQRyaQkABl4ADHmgWUYAAAAASUVORK5CYII=";
$img = explode(',',$dataURI,2)[1];
$pic = 'data://text/plain;base64,'. $img;
$pdf = new FPDF();
$pdf->AddPage();
$pdf->Image($pic, 10,30,0,0,'png');
$pdf->Output();

请记住为Image()方法调用选择正确的图像类型。

为了确保图像与FPDF一起工作并避免错误,这里是@pedro soares代码的修改版本:

function getImage($dataURI){
  $img = explode(',',$dataURI,2);
  $pic = 'data://text/plain;base64,'.$img[1];
  $type = explode("/", explode(':', substr($dataURI, 0, strpos($dataURI, ';')))[1])[1]; // get the image type
  if ($type=="png"||$type=="jpeg"||$type=="gif") return array($pic, $type);
  return false;
}

因为FPDF只允许这三种文件类型,所以检查它是否有效很重要。使用:

$pic = getImage($Base64StringGoesHere);
if ($pic!==false) $pdf->Image($pic[0], 10,30,0,0, $pic[1]);

不知道为什么到目前为止还没有人写这个解决方案,但我已经成功地将base64字符串直接传递给FPDF的Image()函数。只需确保base64字符串的开头有data:image/png;base64,即可。

$data = "base64_string.........";
$pdf -> Image($data, 0, 0, 0, 0, "PNG");

请注意,您必须明确指定图像类型";PNG";。40分别表示图像的X、Y宽度和高度。将FPDF的宽度和高度设置为0,以自动使用图像的尺寸。

为了给Mari M的答案添加更多内容,我只添加了几行代码来处理任何类型的图像。(对于我来说,如果图像是jpeg,FPDF会抱怨,并且我试图加载tempimg.png)

$this->tempImgLoc = 'tempimg';    // Here I just remove the file extension
$dataPieces = explode(',',$dataURI);
$encodedImg = $dataPieces[1];
$decodedImg = base64_decode($encodedImg);
// extract the image type from data:image/png;base64
$extension = explode('/', $dataPieces[0]);
$extension = explode(';', $extension[1]);
$this->tempImgLoc .= '.' . $extension[0];

我相信用正则表达式有更好的方法可以做到这一点,但老实说,regexp不是我喜欢的。。。

好吧,我浪费了半天时间来测试这个问题。我必须告诉大家,这个解决方案是直接从数据库行打印图像,而不将它们存储在临时文件中。

我将写一些需要考虑的要点:

  • 我在数据库中使用blob类型来存储用于打印pdf文档的人工签名
  • 我正在通过post方法从画布节点向数据库发送要存储的签名
  • 当我打印数据库blob中的字符串时,它没有加号"+",这使我无法正确打印签名。为了解决这个问题,我制作了一个"str_replace"来删除空格并插入加号

那么你唯一要做的就是:

$pdf->Image(str_replace(' ','+',$dbRow['blobImage']),160,150,20,10,'png');

如果你像我一样需要从数据库打印几个图像,你必须看看它们是否出现,因为如果图像为空,你就会出错。

我只是把这个添加到最后一个代码中:

if( $dbRow['blobImage'] ){
                 $pdf->Image(str_replace(' ','+',$dbRow['blobImage']),160,150,20,10,'png');
            }

注:

  • 160->图像的X位置
  • 150->图像的Y位置
  • 20->图像的X比例
  • 10->图像的Y比例
  • 'png'->我的Base64图像类型的基本格式

带有imagecreatefromstring()的新解决方案2019年夏季

  • 删除临时.png(如果存在)
  • 创建临时.png文件
  • 使用$pdf->图像(fpdf)

My Api返回1234的Datamatrix作为Byte Array。下面的代码向您展示了如何使用Fpdf中的字节数组作为Png

我的$响应="iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAXNSR0IArs4c6QAAAARnQU1BAACxjv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAABJSURBVChTjYwBCgAgCAP9/6dNrevUgg7Gps3EUOfD5Q4Au6YdAGcH8ygyVKrFnhmbc9FL7qRxWRxEkXWW4Q691UsGpZPzt7EFyY47RMW+x2LAAAAAElFTkSuQmCC"

$filename = '/lk_Reptool/printing/tmp/tmppng.png';
if (file_exists($filename)) {
    unlink($filename);
}
$response = file_get_contents('https://myapi.com/TwoDCode/GetDatamatrixAsPngByteArray?datamatrixText=' . $RepID . '&pixelSize=100');
$response = base64_decode($response);
$img = imagecreatefromstring($response);
imagepng($img, $filename);

pdf 代码

$pdf = new PDF('P', 'mm', 'A4');
$pdf->AddPage();
$pdf->Image('/lk_Reptool/printing/tmp/tmppng.png', 180, 20, 10, 10);

只需使用以下功能扩展Fpdf(在1.8.1上测试):

protected function _parsepngdata($data) {
    $f = tmpfile();
    fwrite($f, base64_decode(substr($data, strpos($data,",")+1)));
    fseek($f, 0);
    $info = $this->_parsepngstream($f,"pngdata");
    fclose($f);
    return $info;
}

并以这种方式使用它:(提供base64数据而不是文件名,并将类型设置为"pngdata"而不是"png")

$pdf->Image("data:image/png;base64,iVBORw0KGgo...", $x, $y, $w, $h, "pngdata");

它将创建一个临时文件,向/从中写入/读取数据,然后将其删除。