打印

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

Kirikiri2系统的txt分割型立绘的合成问题

首先感谢resty大的插件
没有这插件也不能提取メルクリア~水の都に恋の花束を~

这几天合成从メルクリア~水の都に恋の花束を~提取出来的立绘
发现一个问题
其中一张合成图

全图: bst_02black.png

合成后眼泪是黑色的
开游戏看看
原本是这样的


经过几天研究
发现问题在于txt档内type栏
引用:
#layer_type        name        left        top        width        height        type        opacity        visible        layer_id        group_layer_id       
                                1100        1320                                               
0        顔原点        469        246        2        3        13        255        1        11816               
0        20_21_22_24_25_26_27_28        0        0        0        0        13        255        0        11893        2030       
0        01_02_03_04_05_06_07_08_09_10_11_12_13_14_15_17        0        0        0        0        13        255        0        11894        2030       
0        23        383        191        132        108        13        255        0        11899        2030       
0        涙        410        231        94        69        21        255        1        11901        711       
0        涙影        410        231        94        70        16        255        1        11900        711       
0        涙        419        242        79        20        21        255        1        11903        720       
0        涙k        419        242        80        21        16        255        1        11902        720       
0        涙 のコピー        414        243        88        23        21        255        1        11905        2041       
0        涙k のコピー        413        192        144        107        16        255        1        11904        2041       
2        28        0        0        0        0        13        255        0        484        2006       
2        27        0        0        0        0        13        255        0        482        2006       
2        21_22        0        0        0        0        13        255        0        480        2006       
2        頬hi        0        0        0        0        13        255        1        2020        1990       
2        頬デフォルト        0        0        0        0        13        255        1        2028        1990       
2        12_15        0        0        0        0        13        255        0        718        2028       
2        11_17_24        0        0        0        0        13        255        0        716        2028       
2        10_19_20_27        0        0        0        0        13        255        0        714        2028       
2        03_04_06_22_25_28        0        0        0        0        13        255        0        712        2028       
type栏是记载吉里吉里内部定义的合成模式
详细:
http://devdoc.kikyou.info/tvp/docs/kr2doc/contents/TPC.html
http://devdoc.kikyou.info/tvp/do ... /GraphicSystem.html

13=ltPsNormal
   普通的合成/Photoshop的Normal混合模式 (alpha blending?)
14=ltPsAdditive
   Photoshop的Linear Dodge (覆い焼き(リニア))混合模式
15=ltPsSubtractive
   Photoshop的Linear Burn (焼き込み(リニア))混合模式
16=ltPsMultiplicative
   Photoshop的Multiply (乗算)混合模式
17=ltPsScreen
   Photoshop的Screen (スクリーン)混合模式
18=ltPsOverlay
   Photoshop的Overlay (オーバーレイ)混合模式
19=ltPsHardLight
   Photoshop的Hard Light (ハードライト)混合模式
20=ltPsSoftLight
   Photoshop的Soft Light (ソフトライト)混合模式
21=ltPsColorDodge
   Photoshop的Color Dodge (覆い焼きカラー)混合模式
22=ltPsColorDodge5
   Photoshop 5.x以下的Color Dodge (覆い焼きカラー)混合模式
23=ltPsColorBurn
   Photoshop的Color Burn (焼き込みカラー)混合模式
24=ltPsLighten
   Photoshop的Lighten (比較(明))混合模式
25=ltPsDarken
   Photoshop的Darken (比較(暗))混合模式
26=ltPsDifference
   Photoshop的Difference (差の絶対値)混合模式
27=ltPsDifference5
   Photoshop 5.x以下的Difference (差の絶対値)混合模式
28=ltPsExclusion
   Photoshop的Exclusion (除外)混合模式

这张立绘的问题是眼泪那个图层的type是21
即是需要Color Dodge混合模式合成

在PS将那图层调回Color Dodge混合模式就没有问题了

全图: bst_02.png

合成这类立绘要注意一下

有兴趣研究的
JS set.rar
115

[ 本帖最后由 sfsuvival 于 2010-03-20 03:09 编辑 ]
...我对图像处理的认识不深
这只是研究出来的结果
我也不知道那些合成模式的原理...
引用:
原帖由 haibara 于 2010-03-20 01:51 发表
要命,要重写了,用ImageMagick肯定不行了

blend(dest, min(1.0, dest ÷ ( 1.0 - src ) ), α)

这可不是一般alpha blending...

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

        private static int blendColorDodge(int dest, int src, int alpha) {
                return blendNormal(dest, Math.min(255, dest / (255 - src)), alpha);
        }

src不会等于1.0?
这个可能是因为有用min
所以即使dest ÷ ( 1.0 - src ) 是无限大也不管了...
引用:
原帖由 haibara 于 2010-03-20 14:13 发表
sfsuvival, 我想问下,一般blending后最终图象的alpha怎么处理的

是与src的alpha一样,还是process(src alpha,dest alpha)这样的?

我想把alpha处理固定下来,把上面所有的blending模式加到directmuxer里面去
老实说我弄不清什么是alpha blending...
我觉得alpha blending的α是指整个图层的opacity
不是从图层的alpha channel拿出来的数值...
Value=(1-α)Value0+αValue1
Value0, Value1和Value是RGBA的数值

我看到一个更像是用alpha channel的数值合成图层的算式
http://en.wikipedia.org/wiki/Alpha_compositing
αoab(1-αa)
Co=(Caαa+Cbαb(1-αa))/ αo

αo是最终图象的alpha
Co是最终图象的RGB值
引用:
原帖由 haibara 于 2010-03-21 20:47 发表
private static int blendColorDodge(int dest, int src, int alpha) {
                return blendNormal(dest, src == 255 ? src : Math.min(255, (dest << 8) / (255 - src)), alpha);
        }

为什么dest要x256?
不知道你在哪里找到这算式...

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


我比较认同αo是255的opaque,而非来源f(alpha,alpha)


也就是你给的文章的Alpha blending
我也有这样想过
不过这样的话Alpha blending后的图和没有alpha一样(整张图的alpha都是255=整张图不透明=alpha没有用)
事件图合成还可以这样做
但立绘合成就麻烦了
合成后该透明的地方不透明了
我看见一些文章的Value0, Value1和Value是RGBA的数值
两张图的alpha和RGB值一样也去做alpha blending
不知道这是否正确...
引用:
java官方的desktop的BlendComposite也是这个实现(预乘alpha是个浮点参数,对像素做这样的操作,result做前期 blend处理,在AlphaBlending中result是否等于src?),而java的标准库里的AlphaComposite就比较晕头转向了

                    blender.blend(srcPixel, dstPixel, result);

                    // mixes the result with the opacity
                    dstPixels[x] = ((int) (dstPixel[3] + (result[3] - dstPixel[3]) * alpha) & 0xFF) << 24 |
                                   ((int) (dstPixel[0] + (result[0] - dstPixel[0]) * alpha) & 0xFF) << 16 |
                                   ((int) (dstPixel[1] + (result[1] - dstPixel[1]) * alpha) & 0xFF) <<  8 |
                                    (int) (dstPixel[2] + (result[2] - dstPixel[2]) * alpha) & 0xFF;
这个是将blend完的值再和alpha混合
和计算premultiplied alpha的原理相似
但是不是计算premultiplied alpha的方法
所以我不知道这是什么...
引用:
而BlendComposite的COLOR_DODGE是这样的
public void blend(int[] src, int[] dst, int[] result) {
                            result[0] = src[0] == 255 ? 255 :
                                Math.min((dst[0] << 8) / (255 - src[0]), 255);
                            result[1] = src[1] == 255 ? 255 :
                                Math.min((dst[1] << 8) / (255 - src[1]), 255);
                            result[2] = src[2] == 255 ? 255 :
                                Math.min((dst[2] << 8) / (255 - src[2]), 255);
                            result[3] = Math.min(255, src[3] + dst[3] - (src[3] * dst[3]) / 255);
                        }

与kr2doc区别就在dest要x256

x256我看与ps效果是一样的,不乘明显错误
kr2doc的dest和src是[0,1]
blend(dest, min(1.0, dest ÷ ( 1.0 - src ) ), α)
所以当你的dest和src是[0,255] 的话要x255
至于x256的原因我看到的解释是因为x256比x255快(只需位移位(bit shifting))
我看到其它大同小异的计算方法
如GIMP的Dodge
http://docs.gimp.org/2.6/en/gimp-concepts-layer-modes.html
多了+1应该是为了避免除0

SVG的alpha compositing有记下composite后的alpha值
你可以去看看
http://www.w3.org/TR/2004/WD-SVG12-20041027/rendering.html

[ 本帖最后由 sfsuvival 于 2010-03-22 16:06 编辑 ]
引用:
原帖由 haibara 于 2010-03-23 00:17 发表


以extractdata为例,它alpha blending就当alpha none,只保留rgb...

最后关于alpha blending,还是MS看的爽眼,实在不高兴折腾了
http://msdn.microsoft.com/en-us/library/dd183393%28VS.85%29.aspx

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

当SourceConstantAlpha=0xFF (合成时不需要改整张图的opacity)
Dst.Red = Src.Red + (1 - Src.Alpha) * Dst.Red
Dst.Green = Src.Green + (1 - Src.Alpha) * Dst.Green
Dst.Blue = Src.Blue + (1 - Src.Alpha) * Dst.Blue
Dst.Alpha = Src.Alpha + (1 - SrcAlpha) * Dst.Alpha
因为Src和Dst是用premultiplied alpha
所以即是
Dst.Alpha * Dst.Color = Src.Alpha * Src.Color + (1 – Src.Alpha) * Dst.Alpha * Dst.Color
αoCo=(αaCa+(1-αabCb)


Dst.Alpha = Src.Alpha + (1 - SrcAlpha) * Dst.Alpha


x256的原因应该就是x256比x255快
Java的是正常做法
GIMP那+1比较

[ 本帖最后由 sfsuvival 于 2010-03-23 12:38 编辑 ]
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
可信性较高?
看不到有什么问题
用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 编辑 ]
引用:
原帖由 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 编辑 ]
引用:
原帖由 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 编辑 ]
http://www.java2s.com/Code/Java/ ... ndCompositeDemo.htm
这是你找到的BlendComposite源码来源?
引用:
* <h2>Opacity</h2>
* <p>Each blending mode has an associated opacity, defined as a float value
* between 0.0 and 1.0. Changing the opacity controls the force with which the
* compositing operation is applied. For instance, a composite with an opacity
* of 0.0 will not draw the source onto the destination. With an opacity of
* 1.0, the source will be fully drawn onto the destination, according to the
* selected blending mode rule.</p>
* <p>The opacity, or alpha value, is used by the composite instance to mutiply
* the alpha value of each pixel of the source when being composited over the
* destination.</p>
引用:
blender.blend(srcPixel, dstPixel, result);

// mixes the result with the opacity
dstPixels[x] = ((int) (dstPixel[3] + (result[3] - dstPixel[3]) * alpha) & 0xFF) << 24 |
                           ((int) (dstPixel[0] + (result[0] - dstPixel[0]) * alpha) & 0xFF) << 16 |
                           ((int) (dstPixel[1] + (result[1] - dstPixel[1]) * alpha) & 0xFF) <<  8 |
                                (int) (dstPixel[2] + (result[2] - dstPixel[2]) * alpha) & 0xFF;
2nd里的alpha应该是指整张图层的opacity
不是指像素内的alpha值
现在DirectMuxer设所有图层的opacity为255 => alpha = 1.0
dstPixel[3] + (result[3] - dstPixel[3]) * alpha = result[3]
现在2nd就是普通设像素值的方法

2nd与blend方式无关
你可以先实现BlendComposite的SUBTRACT和ps对比一下结果

[ 本帖最后由 sfsuvival 于 2010-04-05 01:26 编辑 ]
引用:
原帖由 haibara 于 2010-04-05 23:13 发表
还有个大问题

目前按照SVG来的alpha blending虽然目测与ps的normal一样

但实际取读字节数据,有发现相当多的点的RGB不同呀

这个我烦恼了很长时间了
PS的blending太复杂
又有opacity/fill/layer mask/adjustment layer等东西
即使opacity=100%,fill=100%,没有layer mask和adjustment layer
是否只根据blend mode合成
假设的确是只根据blend mode合成
而且blend mode是和SVG的标准一样
也不知道PS会否对合成前/时/后做些特别处理,如优化速度/合成效果等
要做到和PS的合成完全一样似乎十分困难

做了些测试
随意选两张用
DirectMuxer (Alpha blending/Complex composite)
GIMP 2.6.8
ImageMagick 6.5.8-8
Photoshop CS2
PicComposite
pngmux
SAI 1.1.0
进行普通合成
虽然目测所有合成图是一样的
但事实是没有两张所有像素完全相同的合成图…
上述的软件都输出不同的合成图…
看来也没有其它软件能做到和PS的合成一样
没有通用标准的东西就是这样?

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

快速回复主题

选项

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

当前时区 GMT+8, 现在时间是 2024-04-27 06:38

Processed in 0.018668 second(s), 6 queries.