Учитывая следующий код, я могу получить доступ к пикселям изображения и сопоставить их с структурой Color
.Советы по производительности, отображающие указатели на объекты
На мой взгляд, это выглядит неэффективно, так как каждый раз, когда я обращаюсь к индексу, я читаю его из массива четыре раза. Для запуска компьютера требуется около 9 секунд.
То, что я ищу, является примером того, как кто-то будет оптимизировать код. Я предполагаю, что могу получить некоторую ссылку на массив с использованием небезопасного кода и читать за один ход, но мне еще предстоит найти достойный путеводитель, чтобы объяснить, как вы это сделаете и как применить подход к другим ситуациям.
Хотя пример кода сам по себе поможет мне, объяснение того, что происходит, и почему это я бы улучшил производительность, было бы более полезным для меня и для любого читателя.
public class Program
{
public static void Main(string[] args)
{
Image img = new Image(10000,10000);
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
for (int y = 0; y < img.Height; y++)
{
for (int x = 0; x < img.Width; x++)
{
Color color = img[x,y];
}
}
stopwatch.Stop();
Console.WriteLine(
string.Format("Time: {0} ms", stopwatch.ElapsedMilliseconds));
Console.ReadKey();
}
}
// Define other methods and classes here
public class Image {
private float[] pixels;
public Image (int width, int height){
pixels = new float[width * height * 4];
this.Width = width;
this.Height = height;
}
public int Width { get; private set; }
public int Height { get; private set; }
public Color this[int x, int y]
{
get
{
int start = ((y * this.Width) + x) * 4;
return new Color(this.pixels[start],
this.pixels[start + 1],
this.pixels[start + 2],
this.pixels[start + 3]);
}
set
{
int start = ((y * this.Width) + x) * 4;
this.pixels[start] = value.R;
this.pixels[start + 1] = value.G;
this.pixels[start + 2] = value.B;
this.pixels[start + 3] = value.A;
}
}
}
public struct Color {
public Color (float r, float g, float b, float a):this(){
this.R = r;
this.G = g;
this.B = b;
this.A = a;
}
public float R {get;set;}
public float G {get;set;}
public float B {get;set;}
public float A {get;set;}
}
UPDATE
Так что с некоторым исследованием я был в состоянии выполнить некоторые улучшения с использованием небезопасного кода.
Вот один подход к моему индексатору:
public unsafe class Image {
private byte* pixels;
public Image (int width, int height){
fixed(byte* p = &(new byte[width * height * 4])[0]){
this.pixels = p;
}
this.Width = width;
this.Height = height;
}
public int Width { get; private set; }
public int Height { get; private set; }
public Color this[int x, int y]
{
get { return *((Color*)(this.pixels + ((y * this.Width) + x) * 4)); }
set {
Color* c = (Color*)(this.pixels + (((y * this.Width) + x) * 4));
c->R = value.R;
c->G = value.G;
c->B = value.B;
c->A = value.A;
}
}
}
Это примерно 50% быстрее, но я обеспокоен тем, что происходит с pixels
собственности. Это когда-нибудь очищается сборщиком мусора? Должен ли образ реализовывать IDisposable
, чтобы я мог установить значение null?
Вот второй подход:
public unsafe class Image {
private byte[] pixels;
public Image (int width, int height){
pixels = new byte[width * height * 4];
this.Width = width;
this.Height = height;
}
public int Width { get; private set; }
public int Height { get; private set; }
public Color this[int x, int y]
{
get
{
fixed(byte* p = &this.pixels[0]){
return *((Color*)(p + ((y * this.Width) + x) * 4));
}
}
set
{
fixed(byte* p = &this.pixels[0]){
Color* c = (Color*)(p + (((y * this.Width) + x) * 4));
c->R = value.R;
c->G = value.G;
c->B = value.B;
c->A = value.A;
}
}
}
}
Это примерно 28% быстрее, и, насколько я могу определить, это означает, что я не должен ничего делать для дальнейшего управления памятью.
Есть ли очевидные недостатки в любом подходе?
Это тот, который, вероятно, лучше подходит для [Обзор кода] (http://codereview.stackexchange.com/). –
Я думал, что, но я осмотрелся и увидел подобный вопрос на этом сайте, а также вопрос о механизмах небезопасного кода. Я уверен, что администратор перенесет его, если они подумают, что там лучше, и я не буду иметь проблемы, если они это сделают. –
Используйте LockBits, если вам нужна скорость. Более подробную информацию можно найти здесь [http://stackoverflow.com/questions/190385/how-to-manipulate-images-at-pixel-level-in-c](http://stackoverflow.com/questions/190385/how-to-manipulate-images-at-pixel-level-in-c) – Dbuggy