0

C# winform アプリで。テキストをログファイルに記録するクリップボードログマネージャーを作成しています(Ctrl + c / xが押されるたびに、コピー/カットされたテキストがファイルに追加されます)画像に対しても同じことを行いました。 「prtScreen」を押すと、撮ったスクリーンショットもフォルダに移動します。

私はタイマーを使用してそれを行います。内部には、次のような「外観」があります。

if (Clipboard.ContainsImage())
{
  if (IsClipboardUpdated())
  {
    LogData();
    UpdateLastClipboardData();
  }
}

残りのメソッドは次のようになります。

public void UpdateLastClipboardData()
{
  // ... other updates
  LastClipboardImage = Clipboard.GetImage();
}
// This is how I determine if there's a new image in the clipboard...
public bool IsClipboardUpdated()
{
  return (LastClipboardImage != Clipboard.GetImage());
}
public void LogData()
{
  Clipboard.GetImage().Save(ImagesLogFolder + "\\Image" + now_hours + "_" + now_mins + "_" + now_secs + ".jpg");  
}

問題は、更新メソッド内で、「LastClipboardImage != Clipboard.GetImage()」が常に true を返すことです!

update メソッド内で次のことも行いました。

Image img1 = Clipboard.GetImage();
Image img2 = Clipboard.GetImage();
Image img3 = img2;
bool b1 = img1 == img2; // this returned false. WHY??
bool b2 = img3 == img2; // this returned true. Makes sense.

助けてください、比較が機能していません...なぜですか?

4

3 に答える 3

1

ちょっとテスト。同じ画像に対して GetImage メソッドを 2 回呼び出す

void Main()
{
    Image bmp1 = Clipboard.GetImage();
    Image bmp2 = Clipboard.GetImage();

    if(bmp1 != null && bmp1 == bmp2)
        Console.WriteLine("True");
    else
        Console.WriteLine("False");
}

常に false を返します。したがって、Clipboard.GetImage() を呼び出すたびに異なるイメージ インスタンスが取得されるため、単純な方法を使用して比較することはできません。== operator

Image オブジェクトの 2 つの異なるインスタンスを比較していますが、もちろん同じではありません。

画像をピクセルレベルまで比較したい場合は、このようなより侵襲的な(そしてパフォーマンスに飢えた方法)必要があります

bool ImagesAreDifferent(Image img1, Image img2)
{
    Bitmap bmp1 = new Bitmap(img1);
    Bitmap bmp2 = new Bitmap(img2);

    bool different = false;
    if (bmp1.Width == bmp2.Width && bmp1.Height == bmp2.Height)
    {
        for (int i = 0; i < bmp1.Width; i++)
        {
            for (int j = 0; j < bmp1.Height; j++)
            {
                Color col1 = bmp1.GetPixel(i, j);
                Color col2 = bmp2.GetPixel(i, j);
                if (col1 != col2)
                {
                    i = bmp1.Width + 1;
                    different = true;
                    break;
                }
            }
        }
    }    
    return different;
}

Color 構造体は、色の RGB 値が 2 つの色間で同じかどうかをチェックするEquality 演算子を定義しているため、これがどのように可能であるかに注目してください。

于 2012-12-08T17:15:52.350 に答える
0

Imageとの等価性をチェックします。これは、セマンティックの等価性ではなく、参照型との参照Object.equalsの等価性をテストします。以前に の参照を にコピーしたように、これが理由です。ただし、 と については、 whichを呼び出して新しいイメージ オブジェクトを作成しました。img2 == img3trueimg2img3img1img2Clipboard.GetImage

2 つの画像オブジェクトに同じデータが含まれているかどうかを実際にテストしたい場合は、独自のメソッドを作成する必要があります。サブクラス化したくない場合は、おそらく拡張メソッドですImage

public static class ImageExtensions
{
    public static bool MyEquals(this Image x, Image y)
    {
        // compute and return your definition of equality here
    }
}

==オペレーターはこのメソッドを自動的に呼び出さないことに注意してくださいImage.MyEquals

于 2012-12-08T17:24:20.343 に答える
0

画像を比較するのではなく、プログラムのロジックを変更してこの問題を克服できると思います。クリップボードに追加された新しいアイテムのイベントをキャプチャして、ログに書き込むのはどうですか?

以下のリンクからコードサンプルコードを試すことができます

http://www.codeproject.com/Tips/467361/Using-Clipboard-Csharp-4-0-Wrapper-inside

// Use the "ClipboardManager" to manage in a more comprehensive the clipboard
// I assume that "this" is a Form
ClipboardManager manager = new ClipboardManager(this);
// Use "All" to handle all kinds of objects from the clipboard
// otherwise use "Files", "Image" or "Text"
manager.Type = ClipboardManager.CheckType.All;
// Use events to manage the objects in the clipboard
manager.OnNewFilesFound += (sender, eventArg) => 
{
    foreach (String item in eventArg)
    {
        Console.WriteLine("New file found in clipboard : {0}", item);
    }
};
manager.OnNewImageFound += (sender, eventArg) =>
{
    Console.WriteLine("New image found in clipboard -> Width: {0} , Height: {1}", 
                      eventArg.Width, eventArg.Height);
};
manager.OnNewTextFound += (sender, eventArg) =>
{
    Console.WriteLine("New text found in clipboard : {0}", eventArg);
};
// Use the method "StartChecking" to start capturing objects in the clipboard
manager.StartChecking();
// Close the capturing
manager.Dispose();
于 2012-12-08T17:38:59.843 に答える