打印

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

引用:
原帖由 sfsuvival 于 2010-04-04 05:59 发表

既然你觉得是算法的问题
可以像我那样抽出来试试
也许会发现问题所在...

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


既然这种立 ...
昨天与soul1000测试了下,结果发现整数我做了提前优化的关系,即我做了当alpha,beta等于0,255时,化简了公式,所以与浮点产生了差别

对于colordodge,softlight,那就以ps为标准,本来想提供选项SVG 2004,SVG 2009的

BlendComposite是有Subtractive的

case SUBTRACT:
                    return new Blender() {
                        @Override
                        public void blend(int[] src, int[] dst, int[] result) {
                            result[0] = Math.max(0, src[0] + dst[0] - 256);
                            result[1] = Math.max(0, src[1] + dst[1] - 256);
                            result[2] = Math.max(0, src[2] + dst[2] - 256);
                            result[3] = Math.min(255, src[3] + dst[3] - (src[3] * dst[3]) / 255);
                        }
                    };

                    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;

1st计算出2nd需要的result,问题是2nd里的alpha,在我这里应该是result的alpha,它原来是自定义的预乘系数
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 编辑 ]
引用:
原帖由 sfsuvival 于 2010-04-05 01:16 发表
http://www.java2s.com/Code/Java/ ... ndCompositeDemo.htm
这是你找到的BlendComposite源码来源?




2nd里的alpha应该是指整张图层的opacity
不是指像素内的alpha值
现在DirectMuxer设所有 ...
是,来自官方的swinglabs,http://swingx.dev.java.net/

那算法里面的alpha,是自定义的图层alpha,如果写成我这里的情况,应该是结构图的alpha吧

明天测试看减法

[ 本帖最后由 haibara 于 2010-04-05 12:25 编辑 ]
还有个大问题

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

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

这个我烦恼了很长时间了
引用:
原帖由 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 编辑 ]
哎,不同软件有不同的算法优化,有得喜欢精度是浮点的,有的是整形的,有得可能会进行4舍5入什么的,不要再为某一点算出来是0xFFFFFF又还是0xFFFFFE而去计较了 = =  反正也看不出,只要公式正确就可以了。。。
public int lineardodge() {
                Ra = Math.min(1D, Sa + Da);
                return (int) (Ra * 255);
        }

        public int lineardodge(int src, int dest) {
                Sc = Math.min(1D, (src / 255D) + (dest / 255D));
                Dc = dest / 255D;
                Sca = Sa * Sc;
                Dca = Da * Dc;
                return (int) ((Sca + Dca * (1 - Sa)) / Ra * 255);
        }

        public int linearburn() {
                Ra = Sa + Da - Sa * Da;
                return (int) (Ra * 255);
        }

        public int linearburn(int src, int dest) {
                Sc = Math.max(0D, (src / 255D) + (dest / 255D) - 1D);
                Dc = dest / 255D;
                Sca = Sa * Sc;
                Dca = Da * Dc;
                return (int) ((Sca + Dca * (1 - Sa)) / Ra * 255);
        }

以上猜测虽然目测很象PS了,但是总有小部分不一样

下面我看IM的源码写了lineardodge

        private final long QuantumRange = 65535L;
        private final double QuantumScale = 1D / 65535L;
        private final double MagickEpsilon = 1.0e-10;

        public int lineardodge() {               
                  Sa=1D-QuantumScale*alpha;
                  Da=1D-QuantumScale*beta;
                  gamma=RoundToUnity(Sa+Da-Sa*Da);
                  return (int) (QuantumRange*(1D-gamma));  
        }

        public int lineardodge(int src, int dest) {
                  gamma=1D/(Math.abs(gamma) <= MagickEpsilon ? 1D : gamma);
                  return (int) (gamma*(src*Sa+dest*Da));
        }

        private double RoundToUnity(double value) {
                return (value < 0D ? 0D : (value > 1D) ? 1D : value);
        }

我觉得应该是等价的,但是合成出来差太多了,不知怎么搞的

IM源码:
static inline void CompositeLinearDodge(const MagickPixelPacket *p,
  const MagickRealType alpha,const MagickPixelPacket *q,
  const MagickRealType beta,MagickPixelPacket *composite)
{
  MagickRealType
    Da,
    gamma,
    Sa;

  Sa=1.0-QuantumScale*alpha;  /* simplify and speed up equations */
  Da=1.0-QuantumScale*beta;
  gamma=RoundToUnity(Sa+Da-Sa*Da); /* over blend, as per SVG doc */
  composite->opacity=(MagickRealType) QuantumRange*(1.0-gamma);
  /*
    Operation performed directly - not need for sub-routine.
  */
  gamma=1.0/(fabs(gamma) <= MagickEpsilon ? 1.0 : gamma);
  composite->red=gamma*(p->red*Sa+q->red*Da);
  composite->green=gamma*(p->green*Sa+q->green*Da);
  composite->blue=gamma*(p->blue*Sa+q->blue*Da);
  if (q->colorspace == CMYKColorspace)
    composite->index=gamma*(p->index*Sa+q->index*Da);
}

[ 本帖最后由 haibara 于 2010-04-06 22:58 编辑 ]
引用:
原帖由 haibara 于 2010-04-06 14:26 发表
        public int lineardodge(int src, int dest) {
                Sc = Math.min(1D, (src / 255D) + (dest / 255D));
                Dc = dest / 255D;
                Sca = Sa * Sc;
                Dca = Da * Dc;
                return (int) ((Sca + Dca * (1 - Sa)) / Ra * 255);
        }
看不懂你为何将部分blending先算到Sc内...
引用:
        private final long QuantumRange = 65535L;
        private final double QuantumScale = 1D / 65535L;
        private final double MagickEpsilon = 1.0e-10;
你这个是每通道16位的定义
每通道8位的话
QuantumRange = 255
QuantumScale = 1 / 255
MagickEpsilon = 1.0e-6

参考:
http://www.imagemagick.org/RMagick/doc/constants.html
http://www.imagemagick.org/api/M ... type_8h-source.html
引用:
00039 #if (MAGICKCORE_QUANTUM_DEPTH == 8)
00040 #define MagickEpsilon  1.0e-6
00041 #define MagickHuge     1.0e6
00042 #define MaxColormapSize  256UL
00043 #define MaxMap  255UL
00044
00045 typedef double MagickRealType;
00046 #if defined(MAGICKCORE_HDRI_SUPPORT)
00047 typedef float Quantum;
00048 #define QuantumRange  255.0
00049 #define QuantumFormat  "%g"
00050 #else
00051 typedef unsigned char Quantum;
00052 #define QuantumRange  255UL
00053 #define QuantumFormat  "%u"
00054 #endif
引用:
原帖由 sfsuvival 于 2010-04-07 00:23 发表

看不懂你为何将部分blending先算到Sc内...


你这个是每通道16位的定义
每通道8位的话
QuantumRange = 255
QuantumScale = 1 / 255
MagickEpsilon = 1.0e-6

参考:
http://www.imagemagick.org/RMagick/ ...
因为我看blendcomposite是先混合出result再与dest进行blending的

奇怪,我搜索的怎么是那样的(/www/api/MagickCore/magick-type_8h.html),不过即使换成8位,结果仍然很大不同

[ 本帖最后由 haibara 于 2010-04-07 07:15 编辑 ]
引用:
原帖由 haibara 于 2010-04-07 07:12 发表


因为我看blendcomposite是先混合出result再与dest进行blending的

奇怪,我搜索的怎么是那样的(/www/api/MagickCore/magick-type_8h.html),不过即使换成8位,结果仍然很大不同
不是指这段吧...
引用:
// 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;
我找不到其它先混合出result再与dest进行blending的地方...

IM可能还有其它处理
只用CompositeLinearDodge做不到效果...
查看积分策略说明

快速回复主题

选项

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

当前时区 GMT+8, 现在时间是 2020-07-02 16:33

Processed in 0.027963 second(s), 5 queries.