QA@IT

.net(C#)で画像のexifを削除してresponseする方法

3678 PV

初投稿失礼します。
現在、Windows環境でのWebアプリの開発をしていまして、IISのサーバにある
画像ファイルをexifを全て削除した状態でresponseするアプリを作ろうとしています。
オリジナル画像をできる限り劣化させない状態でexifだけ取りたいだけの要件です。
下記サイトを参考にしたり、RemovePropertyItemを使ってexifを削除しようとしたのですが、
メモリ上は削除されたかのように見えるのですがresponseへ出力するとexifが復活してしまいます。
ちょっとハマってしまっているので何か良い方法はないでしょうか?
環境としては.net2.0なのですが、それ以上のframeworkでも良いです。

参考:http://dobon.net/vb/dotnet/graphics/getexifinfo.html

  • QA@IT では、回答以外は「ノート」でやりとりすることになっています。この内容は、質問本文を編集して下さい。
    もっとも、先の私の「回答」も、ノートに記すべきモノでしたけど。
    先の「回答」を書き換えましたので、ご覧下さい。
    -

回答

 ローカル アプリケーションで確認しました。
 結果としては、「全部削除すると、復活(?)する。一部削除だと、項目はあるが内容は消えている。」様です。

 まず、ご提示のコードのように、全ての ID を削除しました。
ご提示のコードでは、PropertyItems を列挙しながら削除しています。これがおかしい、ここで例外が発生していると考えました。通常、列挙子の操作中にそれが指す項目を増減すると、例外が発生します。そこで、一旦別の List に PropertyItem.ID を保存し、別のループで削除したのですが、全ての EXIF 項目が以前の内容を保持していました。
 次に、カメラの製造元だけ削除してみました。すると、ファイルのプロパティでは、項目はありますが、内容は空白になっていました。
 よって、消したい項目だけ選択して削除することを薦めます。
参考:http://cachu.xrea.jp/perl/ExifTAG.html
確認時のコード

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication5
{
    // 新しい WindowsForms プロジェクト
    // Button, PictureBox, OpenFileDialog を1つずつ配置
    public partial class Form1 : Form
    {
        List<int> removeList = new List<int>()
        {
            270,
            271,
            272,
            273,
            274,
            305,
            306,
            315,
            33432,
            37510,
            42016,
            50708,
            50709,
            50735,
            50740,
            50827,
            50828,
        };

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (this.openFileDialog1.ShowDialog(this) == System.Windows.Forms.DialogResult.OK)
            {
                string fn = this.openFileDialog1.FileName;
                Bitmap bmp = new Bitmap(fn);
                Image old = this.pictureBox1.Image;
                this.pictureBox1.Image = bmp;
                if (old != null)
                {
                    old.Dispose();
                }

                // リストにある ID の情報を削除する
                foreach (var item in removeList)
                {
                    var cnt = bmp.PropertyIdList.Select((x) => x).Where((x) => x == item);
                    if (cnt.Count() > 0)
                    {
                        bmp.RemovePropertyItem(item);
                    }
                }

                // "ファイル.jpg" を "ファイル.remove.jpg" として保存
                fn = Path.Combine(
                    Path.GetDirectoryName(fn),
                    string.Format(
                    "{0}.remove{1}",
                    Path.GetFileNameWithoutExtension(fn),
                    Path.GetExtension(fn)));
                bmp.Save(fn);
            }
        }
    }
}
編集 履歴 (1)

ご回答いただきありがとうございます。
すみません。説明が不足していました。
文章で書くよりコードを書いた方が伝わると思いますので
サンプルコードを記載致します。
以下のコードをデバッグするとメモリ上はPropertyItemは削除されている
ように見えるのですが、bmp.Saveでresponseを返して表示された画像のexifを
見るとまだ残っているという状態になっています。

private void Page_Load(object sender, EventArgs e)
{
    //読み込む画像ファイル名
    string imgFile = "C:\\1.jpg";

    //画像を読み込む
    Bitmap bmp = new Bitmap(imgFile);

    //Exif削除
    foreach (PropertyItem item in bmp.PropertyItems)
    {
        bmp.RemovePropertyItem(item.id);
    }

    //Responseを返す
    Response.ContentType = "image/jpeg";
    Response.Clear();
    Response.BufferOutput = true;
    bmp.Save(Response.OutputStream, ImageFormat.Jpeg);

    bmp.Dispose();
    Response.Flush();
}
編集 履歴 (0)
ウォッチ

この質問への回答やコメントをメールでお知らせします。