压缩透明图片 alpha合成规则

	public static byte [] reduceImg(byte [] imgData,  int widthdist, int heightdist) {
ByteArrayOutputStream outputStream = null;
ByteArrayInputStream inputStream = null;
try {
inputStream = new ByteArrayInputStream(imgData);
Image src = javax.imageio.ImageIO.read(inputStream);
//TYPE_INT_ARGB 2
//TYPE_4BYTE_ABGR 6
//TYPE_4BYTE_ABGR_PRE 7
BufferedImage bufferedImage = new BufferedImage(widthdist, heightdist,
BufferedImage.TYPE_4BYTE_ABGR_PRE);


bufferedImage.getGraphics().drawImage(
src.getScaledInstance(widthdist, heightdist,
Image.SCALE_REPLICATE), 0, 0, null);

outputStream = new ByteArrayOutputStream();

ImageIO.write(bufferedImage, "png",outputStream);
// JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(outputStream);
// encoder.encode(bufferedImage);

return outputStream.toByteArray();

} catch (Exception ex) {
logger.error("Reduce user avatar failed!", ex);
return null;
} finally{
if( null != outputStream){
try {
outputStream.close();
} catch (IOException e) {
logger.error("", e);
}
}

if( null != inputStream){
try {
inputStream.close();
} catch (IOException e) {
logger.error("", e);
}
}
}
}



TYPE_INT_ARGB 2
public static final int TYPE_INT_ARGB表示一个图像,它具有合成整数像素的 8 位 RGBA 颜色分量。
该图像具有带 alpha 的 DirectColorModel。认为此图像中的颜色数据没有预乘以 alpha。当使用此类型
作为 BufferedImage 构造方法的 imageType 参数时,所创建的图像与 JDK1.1 和更早期版本中创建的图
像一致。


TYPE_4BYTE_ABGR 6
public static final int TYPE_4BYTE_ABGR表示一个具有 8 位 RGBA 颜色分量的图像,具有用 3 字节存
储的 Blue、Green 和 Red 颜色以及 1 字节的 alpha。该图像具有带 alpha 的 ComponentColorModel。
认为此图像中的颜色数据没有预乘以 alpha。按照每个像素中字节地址从低到高的顺序 A、B、G、R 将字节
数据插入单个字节数组中。


TYPE_4BYTE_ABGR_PRE 7
public static final int TYPE_4BYTE_ABGR_PRE表示一个具有 8 位 RGBA 颜色分量的图像,具有用 3 字节
存储的 Blue、Green 和 Red 颜色以及 1 字节的 alpha。该图像具有带 alpha 的 ComponentColorModel。
认为此图像中的颜色数据已预乘以 alpha。按照每个像素中字节地址从低到高的顺序 A、B、G、R 将字节数据
插入单个字节数组中。

=======================================================
参考JDK中java.awt.AlphaComposite
=======================================================

类实现一些基本的 alpha 合成规则,将源色与目标色组合,在图形和图像中实现混合和透明效果。此类实现的特定规则是 T. Porter 和 T. Duff 合著的 "Compositing Digital Images", SIGGRAPH 84, 253-259 中描述的 12 条基本规则集。本文档的其余部分假定读者熟悉上述论文中概括的定义和概念。

此类扩展了 Porter 和 Duff 定义的方程,包含一个额外的因子。AlphaComposite 类的实例可以包含一个 alpha 值,在将该值用于混合方程之前,可以用它来修改不透明度和每个源像素的覆盖率。

要重点注意的是,Porter 和 Duff 的论文中定义的方程完全是为颜色分量方面的操作定义的,这些颜色分量都要用它们对应的 alpha 分量预乘。因为 ColorModel 和 Raster 类允许以预乘和非预乘的方式存储像素数据,所以在将所有输入数据应用到方程之前,必须将它们标准化为预乘形式,并且在存储像素值之前,可能需要将所有结果都调整回目标所需的形式。

还要注意的是,此类只定义了以纯数学方式组合颜色和 alpha 值的方程。方程的具体应用取决于从数据源中检索数据和将它们存储到其目标中的方式。有关更多信息,请参阅实现警告事项。

Porter 和 Duff 的论文在混合方程的描述中使用了以下因子:

因子 定义
As 源像素的 alpha 分量
Cs 源像素的预乘形式的颜色分量
Ad 目标像素的 alpha 分量
Cd 目标像素的预乘形式的颜色分量
Fs 用于输出的源像素的分数值
Fd 用于输出的目标像素的分数值
Ar 结果 alpha 分量
Cr 结果预乘形式的颜色分量

使用这些因子,Porter 和 Duff 定义了 12 种选择混合因子 Fs 和 Fd 的方法,从而产生了 12 种令人满意的可视效果。在对 12 个指定可视效果的静态字段的描述中,给出了具有确定 Fs 和 Fd 值的方程。例如,对 SRC_OVER 的描述指定了 Fs = 1 和 Fd = (1-As)。一旦已知一组确定混合因子的方程,就可以使用以下方程组将它们应用于每个像素以生成结果:

Fs = f(Ad)
Fd = f(As)
Ar = As*Fs + Ad*Fd
Cr = Cs*Fs + Cd*Fd在我们对 Porter 和 Duff 论文混合方程的扩展中,用到了以下因子:

因子 定义
Csr 源像素的原始颜色分量之一
Cdr 目标像素的原始颜色分量之一
Aac 取自 AlphaComposite 实例的“额外的”alpha 分量
Asr 源像素的原始 alpha 分量
Adr 目标像素的原始 alpha 分量
Adf 目标中存储的最终 alpha 分量
Cdf 目标中存储的最终原始颜色分量

准备输入
AlphaComposite 类定义一个应用于源 alpha 的额外 alpha 值。应用此值就好像首先将隐式的 SRC_IN 规则应用于源像素(通过将原始源 alpha 和原始源色乘以 AlphaComposite 中的 alpha 值获得),而不是应用于具有指定 alpha 值的像素。这产生了以下方程,该方程生成 Porter 和 Duff 的混合方程中使用的 alpha 值:

As = Asr * Aac 所有这些原始源色分量都必须乘以 AlphaComposite 实例中的 alpha 值。此外,如果源色分量不是预乘形式的,那么还需要将颜色分量乘以源 alpha 值。因此,用来生成 Porter 和 Duff 方程源色分量的方程取决于源像素是否已经被预乘:
Cs = Csr * Asr * Aac (如果源像素没有被预乘)
Cs = Csr * Aac (如果源像素被预乘) 无需对目标 alpha 进行调整:
Ad = Adr 仅当目标色分量不是预乘形式时,才需要对它们进行调整:

Cd = Cdr * Ad (如果目标色分量没有被预乘)
Cd = Cdr (如果目标色分量被预乘) 应用混合方程
调整后的 As、Ad、Cs 和 Cd 将用于标准的 Porter 和 Duff 方程,以计算混合因子 Fs 和 Fd,然后计算得到的预乘分量 Ar 和 Cr。


准备结果
仅当结果要存储回保存未预乘数据的目标缓冲区时,才需要使用以下方程调整结果:

Adf = Ar
Cdf = Cr (如果目标数据被预乘)
Cdf = Cr / Ar (如果目标数据没有被预乘) 注意,在所得 alpha 为零时除法是不明确的,所以在这种情况下会忽略除法以避免“除以零”的情况,此时颜色分量都将为零。

性能考虑事项
出于性能方面的原因,传递给 CompositeContext 对象(由 AlphaComposite 类创建) compose 方法的 Raster 对象最好有预乘数据。不过,如果源 Raster 或目标 Raster 没有被预乘,那么可以在合成操作之前或之后执行适当的转换。

实现警告事项
许多源图像,比如 BufferedImage 类中列出的一些不透明图像类型,没有为它们的像素存储 alpha 值。这类源图像为它们所有的像素提供了值为 1.0 的 alpha 值。

许多目标也没有地方存储 alpha 值(这些值是此类执行混合计算的结果)。这类目标会隐式丢弃此类产生的 alpha 值。建议这类目标将它们存储的颜色值作为未预乘的值对待,并在存储颜色值和丢弃 alpha 值之前,将得到的颜色值除以得到的 alpha 值。

结果的精度取决于将像素存储到目标中的方式。对于一连串十二种合成操作中的少数操作,将为每种颜色和 alpha 分量提供至少 8 个存储位的图像格式作为目标无论如何都应该足够了。在舍入误差支配结果之前,为每个分量提供少于 8 个存储位的图像格式仅限用于一或两个合成操作。对于任何半透明混合的类型而言,不单独存储颜色分量的图像格式不是一个好的候选方式。例如,不应将 BufferedImage.TYPE_BYTE_INDEXED 用作混合操作的目标,因为需要从限定的调色板选择像素,以匹配混合方程的结果,所以每个操作都可能引入大量错误。

几乎所有的格式都将像素存储为离散整数,而不是将它们存储为上述方程中使用的浮点值。该实现可以将整数像素值缩放成范围在 0.0 到 1.0 之间的浮点值,或者使用稍作修改的方程,完全在整数域内操作,从而生成与上述方程类似的结果。
通常,整数值与浮点值存在某种相关性:整数 0 等于浮点值 0.0,整数 2^n-1(其中 n 是表示形式中的位数)等于 1.0。对于 8 位的表示形式,这意味着 0x00 表示 0.0,0xff 表示 1.0。


内部实现可能近似于某些方程,它们也可以消除一些步骤,以避免不必要的操作。例如,可以考虑一个离散整数图像,它带有未预乘的 alpha 值,并为存储每个分量使用了 8 个位。接近透明的暗红色存储的值可能是:
(A, R, G, B) = (0x01, 0xb0, 0x00, 0x00)如果正在使用整数运算,并且此值在 SRC 模式下没有与任何 alpha 值合成,则该运算将指示此运算的结果为(整数格式):

(A, R, G, B) = (0x01, 0x01, 0x00, 0x00)注意中间的值,它总是以已预乘的形式出现,并且只允许整数 red 分量为 0x00 或 0x01。当试图将此结果存储回未预乘的目标中时,用 alpha 值相除之后,对于未预乘的 red 值,可进行的选择很少。在这种情况下,在整数空间内执行运算(没有快捷方式)的实现最后可能提供以下最终像素值:

(A, R, G, B) = (0x01, 0xff, 0x00, 0x00)(注意,0x01 除以 0x01 得到的是 1.0,等于 8 位存储格式的值 0xff。)

另一方面,使用浮点运算的实现可以生成更精确的结果,并以返回原始像素值结束,该值有可能带有少量的舍入误差。或者,使用整数运算的实现可能决定是否可以将未涉及的像素传输给目标,完全避免所有运算。因为如果在浮点空间内执行运算,方程可简单归结为颜色值上的一个虚拟 NOP。

这些实现都试图遵守相同的方程,但使用经过权衡的不同整数和浮点运算,并使用部分的或全部的方程。为了说明这些不同之处,可能最好只期望获得已预乘形式的结果,以在实现和图像格式之间进行匹配。在这种情况下,以预乘形式表示的两种答案将等同于:

(A, R, G, B) = (0x01, 0x01, 0x00, 0x00)并且它们将是完全匹配的。


因为那些通过简化方程使计算更有效的技术,在非预乘的目标上遇到值为 0.0 的结果 alpha 值时,一些实现的执行可能会有所不同。注意,如果分母 (alpha) 为 0,则在 SRC 规则下移除除以 alpha 这一简化操作技术上是不合法的。但是,因为在以预乘形式查看时只期望结果是精确的,所以,结果为 0 的 alpha 值呈现的实质上是所得到的不相关颜色分量,因此,在这种情况下,具体的行为应该是无法预料的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值