大きな画像(約2000x2000)をすばやく処理しようとしています。私はTrackBarを使ってイメージの全体的な明るさを変更しています。問題は、あなたが知っているようにTrackBarを非常に素早く動かすことができることです。 の画像を処理する必要がないため、TrackBarのすべてのティックがOKですが、合理的に応答する必要があります。イメージエディタにある明るさトラックバーを考えてみましょう。複数のスレッドを使用してセクション内の画像を処理する方法は?
私は、動作する別のスレッドですべての処理を試みましたが、それでもビットマップでLockBitsを使用しても遅すぎます。 ColorMatrixを使用することはできません。なぜなら、コンポーネントのオーバーフローが発生し、255でクリップするための値が必要なのです。したがって、私はThreadPoolを使用してイメージをセクションに分割することで、良いパフォーマンスを達成できると考えています。
このアプローチの問題は、私は複数のtrheadedアプリケーションで多くの経験を持っていないと私は競争条件(ロックされたイメージなどLockBitsを呼び出すなど)を回避する方法を知りません。 )。誰でも私にこれを行う方法の例を教えてもらえますか?
これまでのコードは次のとおりです。私はそれが良いから遠いことを知っているが、私はそれを働いていると、この時点でさまざまなことをしようとしています。基本的なコンセプトは、ベースイメージをソースとして使用し、各ピクセルで何らかの操作を実行し、処理されたピクセルを表示Bitmapに描画することです。どんな助けも素晴らしいだろう。
public Form1()
{
InitializeComponent();
testPBox1.Image = Properties.Resources.test;
trackBar1.Value = 100;
trackBar1.ValueChanged += trackBar1_ValueChanged;
}
void trackBar1_ValueChanged(object sender, EventArgs e)
{
testPBox1.IntensityScale = (float) trackBar1.Value/100;
}
class TestPBox : Control
{
private const int MIN_SAT_WARNING = 240;
private Bitmap m_srcBitmap;
private Bitmap m_dispBitmap;
private float m_scale;
public TestPBox()
{
this.DoubleBuffered = true;
IntensityScale = 1.0f;
}
public Bitmap Image
{
get
{
return m_dispBitmap;
}
set
{
if (value != null)
{
m_srcBitmap = value;
m_dispBitmap = (Bitmap) value.Clone();
Invalidate();
}
}
}
[DefaultValue(1.0f)]
public float IntensityScale
{
get
{
return m_scale;
}
set
{
if (value == 0.0 || m_scale == value)
{
return;
}
if (!this.DesignMode)
{
m_scale = value;
ProcessImage();
}
}
}
private void ProcessImage()
{
if (Image != null)
{
int sections = 10;
int sectionHeight = (int) m_srcBitmap.Height/sections;
for (int i = 0; i < sections; ++i)
{
Rectangle next = new Rectangle(0, i * sectionHeight, m_srcBitmap.Width, sectionHeight);
ThreadPool.QueueUserWorkItem(new WaitCallback(delegate { ChangeIntensity(next); }));
}
}
}
private unsafe void ChangeIntensity(Rectangle rect)
{
BitmapData srcData = m_srcBitmap.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format32bppRgb);
BitmapData dspData = m_dispBitmap.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format32bppRgb);
byte* pSrc = (byte*) srcData.Scan0;
byte* pDsp = (byte*) dspData.Scan0;
for (int y = 0; y < rect.Height; ++y)
{
for (int x = 0; x < rect.Width; ++x)
{
// we are dealing with a monochrome image, so r = g = b.
// We only need to get one component value to use for all r, g, and b.
byte b = (byte) CompMinMax(0, 255, (int) (pSrc[0] * m_scale));
Color c = (b > MIN_SAT_WARNING) ? Color.FromArgb(b, Color.Red) : Color.FromArgb(255, b, b, b);
// windows stores images internally in
// reverse byte order, i.e., Bgra, not Argb.
pDsp[3] = (byte) c.A;
pDsp[2] = (byte) c.R;
pDsp[1] = (byte) c.G;
pDsp[0] = (byte) c.B;
pSrc += 4;
pDsp += 4;
}
}
m_srcBitmap.UnlockBits(srcData);
m_dispBitmap.UnlockBits(dspData);
this.Invalidate();
}
private int CompMinMax(int min, int max, int value)
{
if (value > max) return max;
if (value < min) return min;
return value;
}
protected override void OnPaint(PaintEventArgs e)
{
if (Image != null)
{
Graphics g = e.Graphics;
Rectangle drawingRect = PaintUtils.CenterInRect(ClientRectangle, PaintUtils.ScaleRect(ClientRectangle, Image.Size).Size);
g.DrawImage(Image, drawingRect, 0, 0, Image.Width, Image.Height, GraphicsUnit.Pixel);
}
base.OnPaint(e);
}
}
私はそれについて考えている...試してみる... –
優秀な 'アウトオブボックスの'思考! – Jack