मैं एक बिटमैप sourceImage.bmpसाथ सी # BitmapData से एक क्षेत्र फसल
है ताला लगा यह बिट्स है:
Bitmap originalClone = AForge.Imaging.Image.Clone(dataOriginal);
:
BitmapData dataOriginal = sourceImage.LockBits(new Rectangle(0, 0, sourceImage.Width, sourceImage.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
विश्लेषण करते हैं, एक क्लोन मिल बिट्स अनलॉकिंग:
sourceImage.UnlockBits(dataOriginal);
क्या यह निर्दिष्ट करना संभव है कि "डेटाऑरिगिनल" का प्रति भाग कॉपी करने के लिए (x, y, w, h)? या डेटा से नया डेटा बनाने के लिए मूल, एक्स और वाई निर्देशांक के साथ-साथ एच और डब्ल्यू निर्दिष्ट करते हैं?
इसका उद्देश्य इस छवि से एक छोटे से क्षेत्र की प्रतिलिपि बनाना है। यह विधि DrawImage से तेज हो सकती है, इसलिए मैं बाद वाले का उपयोग नहीं करता हूं।
संपादित करें:
तो मैं 29 एमबी बिटमैप ले लिया और कुछ कट्टर परीक्षण किया! पूर्ण आकार की फसल (मूल रूप से एक प्रति) + 100 पुनरावृत्तियों।
कोड:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using AForge;
using AForge.Imaging;
using System.Diagnostics;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;
namespace testCropClone
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private unsafe Bitmap Clone(Bitmap bmp, int startX, int startY, int width, int height)
{
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
BitmapData rawOriginal = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
int origByteCount = rawOriginal.Stride * rawOriginal.Height;
byte[] origBytes = new Byte[origByteCount];
Marshal.Copy(rawOriginal.Scan0, origBytes, 0, origByteCount);
int BPP = 4; //4 Bpp = 32 bits, 3 = 24, etc.
byte[] croppedBytes = new Byte[width * height * BPP];
//Iterate the selected area of the original image, and the full area of the new image
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width * BPP; j += BPP)
{
int origIndex = (startX * rawOriginal.Stride) + (i * rawOriginal.Stride) + (startY * BPP) + (j);
int croppedIndex = (i * width * BPP) + (j);
//copy data: once for each channel
for (int k = 0; k < BPP; k++)
{
croppedBytes[croppedIndex + k] = origBytes[origIndex + k];
}
}
}
//copy new data into a bitmap
Bitmap croppedBitmap = new Bitmap(width, height);
BitmapData croppedData = croppedBitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
Marshal.Copy(croppedBytes, 0, croppedData.Scan0, croppedBytes.Length);
bmp.UnlockBits(rawOriginal);
croppedBitmap.UnlockBits(croppedData);
return croppedBitmap;
}
private Bitmap cloneBitmap(Bitmap bmp, int startX, int startY, int width, int height)
{
Rectangle srcRect = Rectangle.FromLTRB(startX, startY, width, height);
Bitmap cloneBitmap = bmp.Clone(srcRect, bmp.PixelFormat);
return cloneBitmap;
}
private Bitmap cloneRectangle(Bitmap bmp, int startX, int startY, int width, int height)
{
Rectangle srcRect = Rectangle.FromLTRB(startX, startY, width, height);
Bitmap dest = new Bitmap(srcRect.Width, srcRect.Height);
Rectangle destRect = new Rectangle(0, 0, srcRect.Width, srcRect.Height);
using (Graphics graphics = Graphics.FromImage(dest))
{
graphics.DrawImage(bmp, destRect, srcRect, GraphicsUnit.Pixel);
}
return dest;
}
private Bitmap cloneAforge(Bitmap bmp, int startX, int startY, int width, int height)
{
BitmapData rawOriginal = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
Bitmap cloneBitmap = AForge.Imaging.Image.Clone(rawOriginal);
bmp.UnlockBits(rawOriginal);
return cloneBitmap;
}
private void button1_Click(object sender, EventArgs e)
{
Bitmap source = new Bitmap(@"C:\9\01.bmp");
Stopwatch s1 = Stopwatch.StartNew();
for (int i = 0; i < 100; i++)
{
Bitmap Clone1 = cloneAforge(source, 0, 0, source.Width, source.Height);
Clone1.Dispose();
}
/*Bitmap Clone1 = cloneAforge(source, 0, 0, source.Width, source.Height);
Clone1.Save(@"C:\9\01_aforge.bmp");
Clone1.Dispose();*/
s1.Stop();
source.Dispose();
textBox1.Text = ("" + s1.ElapsedMilliseconds/100 + " ms");
}
private void button2_Click(object sender, EventArgs e)
{
Bitmap source = new Bitmap(@"C:\9\01.bmp");
Stopwatch s1 = Stopwatch.StartNew();
for (int i = 0; i < 100; i++)
{
Bitmap Clone1 = cloneBitmap(source, 0, 0, source.Width, source.Height);
Clone1.Dispose();
}
/*Bitmap Clone1 = cloneBitmap(source, 0, 0, source.Width, source.Height);
Clone1.Save(@"C:\9\01_bitmap.bmp");
Clone1.Dispose();*/
s1.Stop();
source.Dispose();
textBox2.Text = ("" + s1.ElapsedMilliseconds/100 + " ms");
}
private void button3_Click(object sender, EventArgs e)
{
Bitmap source = new Bitmap(@"C:\9\01.bmp");
Stopwatch s1 = Stopwatch.StartNew();
for (int i = 0; i < 100; i++)
{
Bitmap Clone1 = Clone(source, 0, 0, source.Width, source.Height);
Clone1.Dispose();
}
/*Bitmap Clone1 = Clone(source, 0, 0, source.Width, source.Height);
Clone1.Save(@"C:\9\01_bits.bmp");
Clone1.Dispose();*/
s1.Stop();
source.Dispose();
textBox3.Text = ("" + s1.ElapsedMilliseconds/100 + " ms");
}
private void button4_Click(object sender, EventArgs e)
{
Bitmap source = new Bitmap(@"C:\9\01.bmp");
Stopwatch s1 = Stopwatch.StartNew();
for (int i = 0; i < 100; i++)
{
Bitmap Clone1 = cloneRectangle(source, 0, 0, source.Width, source.Height);
Clone1.Dispose();
}
/*Bitmap Clone1 = cloneRectangle(source, 0, 0, source.Width, source.Height);
Clone1.Save(@"C:\9\01_rect.bmp");
Clone1.Dispose();*/
s1.Stop();
source.Dispose();
textBox4.Text = ("" + s1.ElapsedMilliseconds/100 + " ms");
}
}
}
EDIT2: (Aforge पूर्ण आकार फसल ..) विधि सं। 2
for (int i = 0; i < 100; i++)
{
Crop crop = new Crop(new Rectangle(0, 0, source.Width, source.Height));
var source2 = crop.Apply(source);
source2.Dispose();
}
औसत = 62ms (40ms कम कि 1 Aforge दृष्टिकोण)
परिणाम:
- BitmapClone (0 एमएस) ?? (धोखा दे, हैं ना?)
- Aforge # 2 (65 एमएस)
- Aforge # 1 (105 एमएस)
- आयत (170 एमएस)
- ताला बिट्स (803 एमएस) (फिक्स के लिए इंतजार/नई परीक्षण के परिणाम ..)
जवाब है हां, लेकिन आप एक समारोह लिखने के लिए क्या करना है, तो अगर आप इसे करना चाहते करने जा रहे हैं जल्दी करो। आपको वांछित आकार का एक नया बिटमैपडाटा बनाना होगा, और बाइट्स के रूप में मूल डेटा पर पुनरावृत्ति करना होगा, एक नई बाइट सरणी में कॉपी करना होगा, जिसे आप नए बिटमैपडेटा में मार्शल कर सकते हैं। – Fopedush
यह सवाल बेहद अंतर्दृष्टिपूर्ण है। मैं एक बड़ी छवि को कई छोटे 8x8 में फसल लगाने की कोशिश कर रहा हूं। ग्राफिक्स.ड्राइमेज() और बिटमैप.क्लोन() विधियां इसके लिए बेहद धीमी हैं। – JBeurer