在内部系统根据Apple Store发布要求预先处理iOS审核需要的图片,使之符合所有的需求后再推送到审核平台。目前出现的错误是:图像不能包含alpha通道或者透明度(iOS: Images can't contain alpha channels or transparencies)。
重新了解alpha通道和透明度
JPG图片只有只有三个通道,RGB。
但是PNG有四个通道;除了前三个是RGB,第四个通道统一称为“alpha通道”。
如果第四个通道是透明度,则这种alpha通道就叫透明度通道,这也是最常见的RGBA方法。但是第四个通道也可以是其他值,比如光泽度之类的,这种alpha通道就叫光泽度通道。
2024-03-08
按照提示信息,上面图片中的报错信息中,alpha通道 or 透明度。猜测要求只是透明度通道,而不是其他类型的alpha通道。
根据透明度的解决方案
通过canvas读取--From StackOverflow
var canvas1=document.getElementById("canvas1");
var ctx1=canvas1.getContext("2d");
var canvas2=document.getElementById("canvas2");
var ctx2=canvas2.getContext("2d");
$p1=$('#results1');
$p2=$('#results2');
var img1=new Image();
img1.crossOrigin='anonymous'
img1.onload=start1;
img1.src="https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png";
function start1(){
canvas1.width=img1.width;
canvas1.height=img1.height;
ctx1.drawImage(img1,0,0);
var imgData=ctx1.getImageData(0,0,canvas1.width,canvas1.height);
var data=imgData.data;
var found1='Left canvas does not have transparency';
for(var i=0;i<data.length;i+=4) {
if(data[i+3]<255) {
found1='Left canvas does have transparency';
break;
}
}
$p1.text(found1);
}
var img2=new Image();
img2.crossOrigin='anonymous'
img2.onload=start2;
img2.src="https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png";
function start2() {
canvas2.width=img2.width;
canvas2.height=img2.height;
ctx2.drawImage(img2,0,0);
var imgData=ctx2.getImageData(0,0,canvas2.width,canvas2.height);
var data=imgData.data;
var found2='Right canvas does not have transparency';
for(var i=0;i<data.length;i+=4) {
if(data[i+3]<255){
found2='Right canvas does have transparency';
break;
}
}
$p2.text(found2);
}
body{ background-color: ivory; }
canvas{border:1px solid red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<p id=results1>Results:</p>
<p id=results2>Results:</p>
<canvas id="canvas1" width=300 height=300></canvas>
<canvas id="canvas2" width=300 height=300></canvas>
2024-03-08
下面的方法不对!!最近出现了两张图片都是colorType = 6, 但是从苹果后台的判断来看,其中一个被判断是不包含,但是另一个被判断是包含!
什么是alpha通道/透明度
goolge+百度了很多文章,发现alpha通道、透明度应该是一个东西。在一个介绍 alpha channel 的视频里面的解释我觉得可以验证这个逻辑
正常图片由R,G,B三个灰色通道组成。alpha通道是在这三个通道的基础上再叠加一个通道。
通过各种查询,发现alpha通道有很多好的用法:
- 去除一个图片的背景色
- 保存选取
- 给图片更换主题色等
含有alpha通道图片类型
iOS官方要求图片必须是JPG或者PNG格式,且必须采用RGB色彩空间
。
在Photoshop中保存图片时,可选择属性“透明度”只在PNG格式时可以勾选
由此判断alpha通道问题只需要判断图片类型为png类型时就可以了。
如何判断png图片是否含有alpha通道
用于测试的图片基本信息如下:
我们通过FileReader读取图片的数据流。然后根据文档查看PNG图片包含的基本信息。
const reader = new FileReader();
// 文件加载完成时的回调函数
reader.onload = function () {
// 创建一个新的img元素
const img = new Image();
// 图片加载完成时的回调函数
img.onload = function () {
// 获取图片的宽度和高度
const width = this.width;
const height = this.height;
// 从DOM中移除图像
img.parentNode.removeChild(img);
// 获取buffer
const buffers = reader.result;
const unit8Array = new Uint8Array(buffers, 0, 26);
let data = unit8Array;
const strs = String.fromCodePoint.apply(null, data); // 对应的字符信息
console.log("===未解析数据==",data);
console.log("===解析数据==",strs);
if (strs?.includes("PNG") && strs?.includes("IHDR")) {
const colorType = data[25]; // color type
// 判断有alpha通道4,6
if ([4,6]?.includes(colorType)) {
remind.notice({
type: "error",
content: (file.name + "图像不能有alpha通道或者透明度")
});
}
}
};
// 将图像的URL设置为FileReader结果
img.src = URL.createObjectURL(file);
};
// 读取文件数据
reader.readAsArrayBuffer(file);
上面代码的打印结果如下:
PNG图片的数据结构
根据文档可知,图片的头信息是8个16制的值。其对应的10进制即上面打印的前八个字节137, 80, 78, 71, 13, 10, 26, 10
通过解析可知其代表的是PNG类型。
紧接着,后面4个字节代表其后面的CHUNK DATA的长度(=13)
再后面CHNUK TYPE 四个字节73, 72, 68, 82
根据打印数据可知为IHDR
根据文档可知,类型有四种
通过查看各个类型包含的信息可知,只有IHDR类型含有alpha通道信息
其中IHDR具体信息如下:
可以知道后续的8个字节0, 0, 10, 236,0, 0, 5, 10
分别为图片的宽度和高度。
width: 0, 0, 10, 236
height: 0, 0, 5, 10
将其转为二进制和十进制后为:
// 对应我们使用的素材图片的基础宽度和高度
width: 101011101100 -- 2796
height: 10100001010 -- 1290
和我们alpha通道有关的是第26个字节Colour Type
根据表格信息可知,当其为4/6时,是含有alpha通道的。
而我们的素材图片对应的值是6, 说明是含有alpha通道的,不符合需求。
通过canvas的getImageData
方法判断PNG透明度
颜色rgba通过判断a是否全部是255来判断png是否有透明像素
// 图片绘制在画布上
context.drawImage(img, 0, 0);
// 获取图片像素信息
var imageData = context.getImageData(0, 0, width, height).data;
// 检测有没有透明数据
var isAlphaBackground = false;
for (var index = 3; index < imageData.length; index += 4) {
if (imageData[index] != 255) {
isAlphaBackground = true;
break;
}
}