PHP修改PNG图片DPI

最近使用PHP生成图片用于打印,但是浏览器默认输出为72DPI,打印要求为300DPI,如果直接打印,图片会比较模糊。

在网上找了一圈,大部分链接都指向ImageMagick,但是我的项目部署在新浪SAE,新浪SAE不支持它。继续找,发现了《PHP 使用GD函式庫更改圖片DPI》这篇文章,提供了修改JPG图片分辨率的方法,亲测可行。但是我的项目必须使用PNG图片,因为用的是透明背景,所以上面的方法还不行,但是可以参考思路。后来又找到了另外一篇文章《PHP: Dpi of a png image》,这篇文章提供了获取PNG图片分辨率的方法,遗憾的是作者并没有给出设置分辨率的方法。

最后,被逼无奈,硬着头皮自己写啦,挣扎一番终于成功了。这是我写的测试例子:

 

<?php
$filename = 'img/example.png';
// ob_start();
// $im = imagecreatefrompng($filename);
// imagepng($im);
// $file = ob_get_contents();
// ob_end_clean();
$file = file_get_contents($filename);

//数据块长度为9
$len = pack("N", 9);
//数据块类型标志为pHYs
$sign = pack("A*", "pHYs");
//X方向和Y方向的分辨率均为300DPI(1像素/英寸=39.37像素/米),单位为米(0为未知,1为米)
$data = pack("NNC", 300 * 39.37, 300 * 39.37, 0x01);
//CRC检验码由数据块符号和数据域计算得到
$checksum = pack("N", crc32($sign . $data));
$phys = $len . $sign . $data . $checksum;

$pos = strpos($file, "pHYs");
if ($pos > 0) {
	//修改pHYs数据块
	$file = substr_replace($file, $phys, $pos - 4, 21);
} else {
	//IHDR结束位置(PNG头固定长度为8,IHDR固定长度为25)
	$pos = 33;
	//将pHYs数据块插入到IHDR之后
	$file = substr_replace($file, $phys, $pos, 0);
}

header("Content-type: image/png");
header('Content-Disposition: attachment; filename="' . basename($filename) . '"');
echo $file;
?>

这篇文章应该也可以作为《各位兄弟姐妹,php 怎么可以生成一张300分辨率的图片,谢谢》的一个答案。

本文参考的其他资料:

在网上搜索的过程中还遇到了一些有用的资料,也放在这里吧:

最后说一句,有条件还是使用ImageMagick,没必要这么折腾!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
修改 PNG 图片DPI 值,可以使用 Java 的 ImageIO 类库和 Apache 的 Sanselan 库。 下面是一个示例代码,它可以读取 PNG 图片修改 DPI 值,并将修改后的图片保存到指定的文件路径: ```java import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; import org.apache.commons.imaging.ImageFormat; import org.apache.commons.imaging.ImageReadException; import org.apache.commons.imaging.ImageWriteException; import org.apache.commons.imaging.Imaging; import org.apache.commons.imaging.common.IImageMetadata; import org.apache.commons.imaging.common.RationalNumber; import org.apache.commons.imaging.common.RationalNumberUtilities; import org.apache.commons.imaging.formats.png.PngImageMetadata; import org.apache.commons.imaging.formats.png.PngTextMetadata; import org.apache.commons.imaging.formats.png.chunks.PngChunkType; import org.apache.commons.imaging.formats.png.chunks.PngHeaderChunk; import org.apache.commons.imaging.formats.png.chunks.PngTextChunk; public class ModifyPNGDPI { public static void main(String[] args) throws ImageReadException, IOException, ImageWriteException { // 读取 PNG 图片 BufferedImage image = ImageIO.read(new File("input.png")); // 获取 PNG 图片的元数据 IImageMetadata metadata = Imaging.getMetadata(image, null); // 如果是 PNG 图片,就修改 DPI 值 if (metadata instanceof PngImageMetadata) { PngImageMetadata pngMetadata = (PngImageMetadata) metadata; // 获取 DPI 值 RationalNumber xPixelSize = pngMetadata.getPhysicalPixelWidth(); RationalNumber yPixelSize = pngMetadata.getPhysicalPixelHeight(); // 修改 DPI 值为 300 RationalNumber newPixelSize = RationalNumberUtilities.getRationalNumber(300); // 更新元数据 pngMetadata.setPhysicalPixelWidth(newPixelSize); pngMetadata.setPhysicalPixelHeight(newPixelSize); // 更新文本元数据 PngHeaderChunk headerChunk = pngMetadata.getPngHeader(); PngTextChunk[] textChunks = headerChunk.getTextChunks(); for (PngTextChunk textChunk : textChunks) { if (textChunk.getChunkType().equals(PngChunkType.tEXt)) { PngTextMetadata textMetadata = new PngTextMetadata(textChunk.getKeyword(), textChunk.getText()); if (textMetadata.getKeyword().equals("pHYs")) { textMetadata.setValue("x_pixels_per_unit", "300"); textMetadata.setValue("y_pixels_per_unit", "300"); textMetadata.setValue("unit_specifier", "1"); headerChunk.removeChunk(textChunk); headerChunk.addChunk(new PngTextChunk(textMetadata.getKeyword(), textMetadata.getText())); break; } } } } // 保存修改后的 PNG 图片 ImageIO.write(image, "png", new File("output.png")); } } ``` 上面的代码使用了 Apache 的 Sanselan 库来修改 PNG 图片DPI 值。如果你不想使用这个库,也可以使用 Java 自带的 ImageIO 类库来修改 DPI 值。具体的方法是创建一个新的 PNG 图片,将原图片绘制到新图片上,并设置新图片DPI 值。这种方法的代码如下: ```java import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; public class ModifyPNGDPI { public static void main(String[] args) throws IOException { // 读取 PNG 图片 BufferedImage image = ImageIO.read(new File("input.png")); // 创建新的 PNG 图片 BufferedImage newImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB); // 绘制原图片到新图片上 Graphics2D g = newImage.createGraphics(); g.drawImage(image, 0, 0, null); // 设置新图片DPI 值 int dpi = 300; int dotsPerMeter = (int) Math.round(dpi / 0.0254); newImage.setDPI(dotsPerMeter, dotsPerMeter); // 保存修改后的 PNG 图片 ImageIO.write(newImage, "png", new File("output.png")); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值