打印

[讨论] Kirikiri2系统的txt分割型立绘的合成问题

引用:
原帖由 sfsuvival 于 2010-03-23 12:35 发表


M$这个不是和维基alpha compositing的公式一样吗?

当SourceConstantAlpha=0xFF (合成时不需要改整张图的opacity)
Dst.Red = Src.Red + (1 - Src.Alpha) * Dst.Red
Dst.Green = Src.Green + (1 - Src.Alpha) ...
好麻烦。还是用这个好了


刚才看了IM的实现,我的妈呀,大概是SVG标准那个实现

00088 static inline void MagickPixelCompositeOver(const MagickPixelPacket *p,
00089   const MagickRealType alpha,const MagickPixelPacket *q,
00090   const MagickRealType beta,MagickPixelPacket *composite)
00091 {
00092   MagickRealType
00093     gamma;
00094
00095   if (alpha == TransparentOpacity)
00096     {
00097       *composite=(*q);
00098       return;
00099     }
00100   gamma=1.0-QuantumScale*QuantumScale*alpha*beta;
00101   composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
00102   gamma=1.0/(gamma <= MagickEpsilon ? 1.0 : gamma);
00103   composite->red=gamma*MagickOver_(p->red,alpha,q->red,beta);
00104   composite->green=gamma*MagickOver_(p->green,alpha,q->green,beta);
00105   composite->blue=gamma*MagickOver_(p->blue,alpha,q->blue,beta);
00106   if ((p->colorspace == CMYKColorspace) && (q->colorspace == CMYKColorspace))
00107     composite->index=gamma*MagickOver_(p->index,alpha,q->index,beta);
00108 }


00038 static inline MagickRealType MagickOver_(const MagickRealType p,
00039   const MagickRealType alpha,const MagickRealType q,const MagickRealType beta)
00040 {
00041   MagickRealType
00042     pixel;
00043
00044   pixel=(1.0-QuantumScale*alpha)*p+(1.0-QuantumScale*beta)*q*QuantumScale*alpha;
00045   return(pixel);
00046 }

[ 本帖最后由 haibara 于 2010-03-23 23:29 编辑 ]
alpha = deltaPixel[i + 3] & 0xff;
                                        beta = basicPixel[i + 3] & 0xff;
                                        resultPixel = (byte) blend(basicPixel & 0xff, deltaPixel & 0xff, alpha);
                                        resultPixel[i + 1] = (byte) blend(basicPixel[i + 1] & 0xff, deltaPixel[i + 1] & 0xff, alpha);
                                        resultPixel[i + 2] = (byte) blend(basicPixel[i + 2] & 0xff, deltaPixel[i + 2] & 0xff, alpha);
                                       

        private static int blend(int dest, int src, int alpha) {
                return dest + (src - dest) * alpha / 255;
        }

若基本图无alpha,或者是opaque alpha,这个就够了

[ 本帖最后由 haibara 于 2010-03-25 07:09 编辑 ]
alpha = deltaPixel[i + 3] & 0xff;
                                        beta = basicPixel[i + 3] & 0xff;
                                        gramma = alpha + beta - alpha * beta / 255;
                                        if (gramma == 0) {
                                                delta = 1;
                                        } else {
                                                delta = gramma;
                                        }
                                        resultPixel = (byte) (composite(deltaPixel & 0xff, basicPixel & 0xff, alpha, beta) / delta);
                                        resultPixel[i + 1] = (byte) (composite(deltaPixel[i + 1] & 0xff, basicPixel[i + 1] & 0xff, alpha, beta) / delta);
                                        resultPixel[i + 2] = (byte) (composite(deltaPixel[i + 2] & 0xff, basicPixel[i + 2] & 0xff, alpha, beta) / delta);
                                        resultPixel[i + 3] = (byte) gramma;

        private static int composite(int src, int dest, int alpha, int beta) {
                return src * alpha + dest * beta - dest * alpha * beta / 255;
        }

按照svg那个来完整的是这样,不过速度居然差不多,vm优化的厉害

[ 本帖最后由 haibara 于 2010-03-25 00:45 编辑 ]
im的好像和svg不同
翻了一下
如果图是8位/色彩通道
TransparentOpacity = QuantumRange = 255
QuantumScale = 1/255
MagickEpsilon = 2.0*1.1920928955078125e-07
MagickRealType = double
im合成后的α是alpha*beta...

svg的不又是和维基的alpha compositing一样...
结果svg的src-over=M$的AC_SRC_OVER=维基的alpha compositing
可信性较高?
引用:
原帖由 sfsuvival 于 2010-03-25 18:41 发表
im的好像和svg不同
翻了一下
如果图是8位/色彩通道
TransparentOpacity = QuantumRange = 255
QuantumScale = 1/255
MagickEpsilon = 2.0*1.1920928955078125e-07
MagickRealType = double
im合成后的α是alp ...
我程序已经改成svg的src-over,M$的AC_SRC_OVER,维基的alpha compositing

        private static int blend(int src, int dest, int alpha) {
                if (alpha == 0) {
                        return dest;
                }
                if (alpha == 255) {
                        return src;
                }
                return dest + (src - dest) * alpha / 255;
        }

        private static int blend(int src, int dest, int alpha, int beta) {
                if (alpha == 0) {
                        return dest;
                }
                if (alpha == 255 || beta == 0) {
                        return src;
                }
                if (beta == 255) {
                        return blend(src, dest, alpha);
                }
                return (src * alpha * 255 + dest * beta * 255 - dest * alpha * beta) / (alpha * 255 + beta * 255 - alpha * beta);
        }

[ 本帖最后由 haibara 于 2010-03-26 14:49 编辑 ]
看不到有什么问题
用java实现svg的src-over/M$的AC_SRC_OVER/维基的alpha compositing
应该就是这样...

blending是需要2张图
但blend mode是一张图的属性
haibara你是怎样处理?
看PS是用src的blend mode将src和dst合成
然后将合成后的图的blend mode设为dst的...

[ 本帖最后由 sfsuvival 于 2010-03-26 23:40 编辑 ]
引用:
原帖由 sfsuvival 于 2010-03-26 22:37 发表
看不到有什么问题
用java实现svg的src-over/M$的AC_SRC_OVER/维基的alpha compositing
应该就是这样...

blending是需要2张图
但blend mode是一张图的属性
haibara你是怎样处理?
看PS是用src的blend mode将sr ...
我不太懂ps

directmuxer合成模式从差分图那边取

目前还有个问题:

我测试
整数的算法(alpha blending),即
(src * alpha * 255 + dest * beta * (255 - alpha)) / (alpha * 255 + beta * 255 - alpha * beta);
浮点数的算法(complex composite的normal),即
Sa = alpha / 255D;
Da = beta / 255D;
Sc = src / 255D;
Dc = dest / 255D;
Sca = Sa * Sc;
Dca = Da * Dc;
Ra = Sa + Da - Sa * Da;
(Sca + Dca * (1 - Sa)) / Ra * 255

目测看边缘锯齿差别很大,为什么,精度?

[ 本帖最后由 haibara 于 2010-04-02 12:01 编辑 ]
引用:
原帖由 haibara 于 2010-04-02 11:08 发表


我不太懂ps

directmuxer合成模式从差分图那边取

目前还有个问题:

我测试
整数的算法(alpha blending),即
(src * alpha * 255 + dest * beta * (255 - alpha)) / (alpha * 255 + beta * 255 - alpha ...
double的精确度已经很高
会否你在处理运算时做了些减低精确度的动作?

我用你给的源码写了个试试
两种方法输出的数字一样,没有问题
复制内容到剪贴板
代码:
import java.util.Random;

public class TestRange {
        public static void main(String[] args) {
                Random randomGenerator = new Random();
                int src = randomGenerator.nextInt(256);
                int dest = randomGenerator.nextInt(256);
                int alpha = randomGenerator.nextInt(256);
                int beta = randomGenerator.nextInt(256);
                double Sa, Da, Sc, Dc, Sca, Dca, Ra, Rc;
               
                int gamma = alpha * 255 + beta * 255 - alpha * beta;
                int res = (src * alpha * 255 + dest * beta * (255 - alpha)) / gamma;
                gamma /= 255;
                System.out.println(res);
                System.out.println(gamma);
               
                Sa = alpha / 255D;
                Da = beta / 255D;
                Sc = src / 255D;
                Dc = dest / 255D;
                Sca = Sa * Sc;
                Dca = Da * Dc;
                Ra = Sa + Da - Sa * Da;
                Rc = (Sca + Dca * (1 - Sa)) / Ra;
                System.out.println((int)(Rc * 255));
                System.out.println((int)(Ra * 255));
        }
}
[ 本帖最后由 sfsuvival 于 2010-04-03 04:41 编辑 ]
引用:
原帖由 sfsuvival 于 2010-04-03 01:57 发表


double的精确度已经很高
会否你在处理运算时做了些减低精确度的动作?

我用你给的源码写了个试试
两种方法输出的数字一样,没有问题

import java.util.Random;

public class TestRange {
        public sta ...
我觉得没有,而且我尽量减少除法的,所以上下同时比一般多乘了次255,才有(src * alpha * 255 + dest * beta * (255 - alpha)) / (alpha * 255 + beta * 255 - alpha * beta)

而且也应该与非算法部分无法,我在这2个算法相互替换写法,结果还是有异常

总之就是锯齿部分有差别

还有

http://www.w3.org/TR/2009/WD-SVGCompositing-20090430/
http://www.w3.org/TR/2004/WD-SVG12-20041027/rendering.html

这2个不同版本,应该选择哪个,按照目测ps里colordodge是2004的,softlight是2009的

而且Subtractive/LinearBurn在SVG没有实现怎么办

[ 本帖最后由 haibara 于 2010-04-03 20:55 编辑 ]
引用:
原帖由 haibara 于 2010-04-03 10:22 发表


我觉得没有,而且我尽量减少除法的,所以上下同时比一般多乘了次255,才有(src * alpha * 255 + dest * beta * (255 - alpha)) / (alpha * 255 + beta * 255 - alpha * beta)

而且也应该与非算法部分无法,我在这2个算法相互替换写法,结果还是有异常

总之就是锯齿部分有差别
既然你觉得是算法的问题
可以像我那样抽出来试试
也许会发现问题所在...

我上面写的java测试过没有问题
也许你可以对比一下?
这个问题既然隐藏得这么好
没有完整源码很难推测哪里有问题...
引用:
还有

http://www.w3.org/TR/2009/WD-SVGCompositing-20090430/
http://www.w3.org/TR/2004/WD-SVG12-20041027/rendering.html

这2个不同版本,应该选择哪个,按照目测ps里colordodge是2004的,softlight是2009的
既然这种立绘是由psd分割出来的
用ps的方法将其合并是最好的
因为我不懂这些合成模式的原理
只看算法我也看不出实际会有什么不同的效果
你觉得那种和ps的效果相近就用那种吧
你是用那个版本的ps
我的是cs2
不同版本的ps合成效果应该不会不同吧...
引用:
而且Subtractive/LinearBurn在SVG没有实现怎么办
...svg没有也没有办法
唯有选别的...
之前你提到的java的BlendComposite没有Subtractive/LinearBurn的源码吗?
难道效果和ps的差很远?

[ 本帖最后由 sfsuvival 于 2010-04-04 06:11 编辑 ]
查看积分策略说明

快速回复主题

选项

[完成后可按 Ctrl+Enter 发布]  预览帖子  恢复数据  清空内容

当前时区 GMT+8, 现在时间是 2020-06-03 15:36

Processed in 0.028548 second(s), 5 queries.