ImageMagick の不具合報告

2件報告しました。同僚に英語を治して貰ったり、タイトルは貰ったものだったりと、ありがたや。ありがたや。

quantize_error を足しこむ計算が間違っている件

同僚が見つけた不具合なので、僕が報告するのは悪いのですが、どうぞと言われたので遠慮なく。><;

減色処理で複数の色を代表する色に落とし込む際、色ツリーのノード毎に色のばらつき具合を計算しますが、同じ色でも複数使う場合は使われてる分だけ足し込みます。



(http://labs.gree.jp/blog/2012/09/4824/ から引用)

足す場合に色距離を計算するので 6.4.1-3 では色をカウントして、色距離の計算を一度だけにする高速化がされているのですが、sqrt の外でなく中に count の乗算が入っていて前と違う結果になっていました。

  • 6.4.1-2
 node_info->quantize_error+=sqrt((double) (error.red*error.red+
   error.green*error.green+error.blue*error.blue+error.opacity*
   error.opacity));
  • 6.4.1-3
 if (IsColorSimilar(image,p,p+count) == MagickFalse)
   break;
     (略)
 node_info->quantize_error+=sqrt((double) (count*error.red*error.red+
   count*error.green*error.green+count*error.blue*error.blue+
   count*error.opacity*error.opacity));

正しくはこれ

 if (IsColorSimilar(image,p,p+count) == MagickFalse)
   break;
     (略)
 node_info->quantize_error+=count*sqrt((double) (error.red*error.red+
   error.green*error.green+error.blue*error.blue+
   error.opacity*error.opacity));

ディザ処理で減色ツリーを辿る処理が間違えている件

RiemersmaDither 関数にこんな処理がありまして、

/*
  Identify the deepest node containing the pixel's color.
*/
node_info=p->root;
for (index=MaxTreeDepth-1; (ssize_t) index > 0; index--)
{
  id=ColorToNodeId(cube_info,&pixel,index);
  if (node_info->child[id] == (NodeInfo *) NULL)
    break;
  node_info=node_info->child[id];
}
node_info=node_info->parent;
/*
  Find closest color among siblings and their children.
*/
p->target=pixel;
p->distance=(MagickRealType) (4.0*(QuantumRange+1.0)*((MagickRealType)
  QuantumRange+1.0)+1.0);
ClosestColor(image,p,node_info->parent);
p->cache[i]=(ssize_t) p->color_number;

コメントには兄弟ノードとその子供を探索とあります。図ではこんな感じ。(透明の立方体が元のノードで矢印が指すのが辿りつきたいノード)




なのですが、->parent を二回辿っていて実際には叔父ノードを見てしまっています。
実はそっくりな処理が AssignImageColors にもありまして、こっちも前は同じ不具合があったのですが、いつの間にか治っていました。(これを見て間違いだと確信しました)
同じ処理が複数あって片方だけ治すという、ありがちな罠ですね。