KDP(電子出版)のメモ 急急如律令

Amazon Kindleダイレクト・パブリッシングでの電子出版や電子書籍の作成販売について、文章やイラストの作成や編集方法について書いています。

ImageUtils.javaのバグ?

あなた:

次のコードを説明して

        try {
            if (imageType == BufferedImage.TYPE_BYTE_BINARY && imageType == BufferedImage.TYPE_BYTE_INDEXED && imageType == BufferedImage.TYPE_INT_ARGB) {
                g.setColor(Color.WHITE);
                g.fillRect(0, 0, scaledW, scaledH);
            }
            g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
            g.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
            AffineTransform at = AffineTransform.getScaleInstance(scale, scale);
            int x = 0;
            int y = 0;
            if (imageInfo.rotateAngle == 0) {
                if (margin != null) {
                    x = (int)(-margin[0]*scale+0.5);
                    y = (int)(-margin[1]*scale+0.5);
                }
            } else if (imageInfo.rotateAngle == 90) {
                at.rotate(Math.toRadians(imageInfo.rotateAngle), 0, 0);
                at.translate(0, -imgH);
                if (margin != null) {
                    x = (int)(-margin[3]*scale+0.5);
                    y = (int)(-margin[0]*scale+0.5);
                }
            } else {
                at.quadrantRotate(-1, 0, 0);
                at.translate(-imgW, 0);
                if (margin != null) {
                    x = (int)(-margin[1]*scale+0.5);
                    y = (int)(-margin[2]*scale+0.5);
                }
            }
            AffineTransformOp ato = new AffineTransformOp(at, AffineTransformOp.TYPE_BICUBIC);
            g.drawImage(srcImage, ato, x, y);
        } finally {
            g.dispose();
        }

ChatGPT:

このコードは、画像のスケーリング(拡大・縮小)と回転を行い、新しい BufferedImage に描画 する処理を実装しています。

try {
    // 画像のスケーリング & 回転処理
} finally {
    g.dispose(); // リソースの開放
}
  • try ブロック内で 画像の変換処理(スケール & 回転) を行う。
  • finally で Graphics2D g を解放(dispose() を呼び出し、メモリを適切に管理)。
if (imageType == BufferedImage.TYPE_BYTE_BINARY && imageType == BufferedImage.TYPE_BYTE_INDEXED && imageType == BufferedImage.TYPE_INT_ARGB) {
    g.setColor(Color.WHITE);
    g.fillRect(0, 0, scaledW, scaledH);
}

問題点: この if 条件式は && を使用しているため、常に false になる(imageType は1つの値しか取らない)。 おそらく ||(または)にするべき だったと考えられる。

意図:

  • 画像が モノクロ(TYPE_BYTE_BINARY)、インデックスカラー(TYPE_BYTE_INDEXED)、または アルファ付き画像(TYPE_INT_ARGB) の場合、 背景を白で塗りつぶしてから画像を描画 する。
g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
  • 画像の描画品質を向上 させるため、アンチエイリアス処理 などのレンダリングオプションを設定。
AffineTransform at = AffineTransform.getScaleInstance(scale, scale);
  • 画像を scale 倍に拡大・縮小する アフィン変換行列 (AffineTransform) を作成。
int x = 0;
int y = 0;
if (imageInfo.rotateAngle == 0) {
    if (margin != null) {
        x = (int)(-margin[0] * scale + 0.5);
        y = (int)(-margin[1] * scale + 0.5);
    }
} else if (imageInfo.rotateAngle == 90) {
    at.rotate(Math.toRadians(imageInfo.rotateAngle), 0, 0);
    at.translate(0, -imgH);
    if (margin != null) {
        x = (int)(-margin[3] * scale + 0.5);
        y = (int)(-margin[0] * scale + 0.5);
    }
} else {
    at.quadrantRotate(-1, 0, 0);
    at.translate(-imgW, 0);
    if (margin != null) {
        x = (int)(-margin[1] * scale + 0.5);
        y = (int)(-margin[2] * scale + 0.5);
    }
}
  1. 回転しない場合 (rotateAngle == 0) マージン(余白)を考慮して位置調整 するだけ。
  2. マージン(余白)を考慮して位置調整 するだけ。
  3. 90度回転する場合 回転行列を適用 (rotate(90°)) 画像の高さ方向にずらす (translate(0, -imgH)) マージンを考慮してオフセット補正
  4. 回転行列を適用 (rotate(90°))
  5. 画像の高さ方向にずらす (translate(0, -imgH))
  6. マージンを考慮してオフセット補正
  7. その他の回転(-90度など) quadrantRotate(-1, 0, 0) を適用(270度回転) 画像の横方向にずらす (translate(-imgW, 0)) マージンを考慮してオフセット補正
  8. quadrantRotate(-1, 0, 0) を適用(270度回転)
  9. 画像の横方向にずらす (translate(-imgW, 0))
  10. マージンを考慮してオフセット補正

  11. マージン(余白)を考慮して位置調整 するだけ。

  12. 回転行列を適用 (rotate(90°))

  13. 画像の高さ方向にずらす (translate(0, -imgH))
  14. マージンを考慮してオフセット補正

  15. quadrantRotate(-1, 0, 0) を適用(270度回転)

  16. 画像の横方向にずらす (translate(-imgW, 0))
  17. マージンを考慮してオフセット補正
AffineTransformOp ato = new AffineTransformOp(at, AffineTransformOp.TYPE_BICUBIC);
g.drawImage(srcImage, ato, x, y);
  • AffineTransformOp.TYPE_BICUBIC を指定し、高品質なバイキュービック補間でスケーリング。
  • g.drawImage() を使って、変換後の画像を描画。

✅ 画像をスケーリング(拡大・縮小)して高品質な描画を行う ✅ 回転(0°・90°・270°)を適用し、オフセットを調整 ✅ 特定の画像タイプ(モノクロ・インデックスカラー・アルファ付き)には白背景を適用

❌ if (imageType == TYPE_BYTE_BINARY && TYPE_BYTE_INDEXED && TYPE_INT_ARGB) は 常に false になるため修正が必要 (→ ||(または)で結合するのが正しい)

if (imageType == BufferedImage.TYPE_BYTE_BINARY || imageType == BufferedImage.TYPE_BYTE_INDEXED || imageType == BufferedImage.TYPE_INT_ARGB) {
    g.setColor(Color.WHITE);
    g.fillRect(0, 0, scaledW, scaledH);
}

この修正により、対象の画像タイプで白背景を適用する処理が正しく動作 するように