Требование, которое подходит для использования указателя, небезопасного кода в .net? Обработка изображений достаточно требовательна к ресурсам, чтобы пойти на высококлассную оптимизацию?

Недавно у нас было несколько потоков (ниже) на SO, где одним из распространенных предложений было не использовать указатель.

фиксированный блок в .net

В .NET есть есть ли разница между использованием указателей в качестве параметров функции и использованием ключевого слова ref?

строки в .net меняются?? есть какая-то ошибка?

Недавно мне потребовалось преобразовать белый фон растровых изображений в прозрачный. Я попробовал, и наиболее оптимальная реализация, которую я мог придумать, приведена ниже.

public unsafe Bitmap MakeWhiteAreaTransparent(Bitmap source)
{
    Bitmap bitmap = new Bitmap(source.Width, source.Height, PixelFormat.Format32bppArgb);
    BitmapData bitmapdata = source.LockBits(new Rectangle(0, 0, source.Width, source.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
    BitmapData data2 = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
    int* numPtr = (int*)bitmapdata.Scan0;
    int* numPtr2 = numPtr + (bitmapdata.Width * bitmapdata.Height);
    int* numPtr3 = (int*)data2.Scan0;
    int num = Color.FromArgb(1, Color.White).ToArgb();
    while (numPtr < numPtr2)
    {
        numPtr++;
        Color color = Color.FromArgb(numPtr[0]);
        if (((color.R < 200) || (color.G < 200)) || (color.B < 200))
        {
            numPtr3[0] = color.ToArgb();
        }
        else
        {
            numPtr3[0] = num;
        }
        numPtr3++;
    }
    source.UnlockBits(bitmapdata);
    bitmap.UnlockBits(data2);
    return bitmap;
}

Мне было интересно, правильно ли я предъявляю иск к указателю, или я должен использовать массив байтов и System.Runtime.InteropServices.Marshal.Copy, а не кружиться с указателями ???


person Pritesh    schedule 20.04.2012    source источник
comment
Называние переменных numPtr, numPtr2 и numPtr3 при написании небезопасного кода должно быть наказуемо.   -  person Niki    schedule 20.04.2012
comment
@nikie Я согласен, что плохая привычка не следовать правилам кодирования редко ходит :(   -  person Pritesh    schedule 20.04.2012


Ответы (2)


Нет ничего плохого в использовании небезопасного кода. Вы используете правильный инструмент для работы. В язык встроена поддержка небезопасного кода и указателей, а это значит, что разработчики посчитали это полезной вещью — достаточно полезной для реализации за счет реализации некоторых других функций.

Есть место для небезопасного кода. Как вы обнаружили, это самый быстрый способ доступа к необработанным данным в растровом изображении. Да, есть способы сделать это в безопасном коде, но они намного медленнее. Небезопасный код также является единственным способом работы с буферами памяти размером более двух гигабайт.

И да, есть приложения, в которых вам действительно нужен один объект размером в несколько гигабайт. Вы можете сколько угодно спорить с этим, а я просто посмеюсь над вами, как смеялся над идиотами в 80-х, которые говорили что-то вроде: «Кому нужен целый мегабайт оперативной памяти?»

Кто-то скажет, что если вам нужен небезопасный код, вам следует написать собственную DLL на C++ и вызвать ее из вашей .NET-программы. Это глупая идея. Во-первых, у вас может не быть инструментов или знаний для создания собственной DLL. Во-вторых, это добавляет больше зависимостей в ваш проект. В-третьих, особой пользы нет. Это "безопаснее"? Нет.

Используйте то, что вам нужно для выполнения работы. Приложите все усилия, чтобы использовать безопасный код. Но если вы, перепробовав все остальное, обнаружите, что то, что вам нужно сделать, требует небезопасного кода... используйте его! Поэтому его поддержка была добавлена ​​в платформу.

person Jim Mischel    schedule 20.04.2012
comment
просто супер!! Я также считаю, что .Net (CLI) был разработан таким образом, чтобы разработчик мог решить, когда ему нужна стабильность (управляемый код), а когда ему нужна производительность (небезопасно). - person Pritesh; 20.04.2012

Мое мнение таково: вы должны использовать язык так, как он должен использоваться. Предполагается, что C# используется с безопасным кодом, оставляя небезопасный в крайнем случае, когда некоторый код должен быть очень быстрым и вызывается слишком часто.

Позвольте мне привести несколько примеров.

  1. Вам нужно сделать какую-то медленную операцию, но она может работать где-то в фоне, не так часто, и ее скорость не очень критична. В этом случае вы можете просто использовать безопасный код: хотя этот подход может и не выжимать последние биты производительности из вашего процессора, он требует значительно меньших усилий при реализации и (что более важно) при обслуживании.

  2. Нужно ускорить операцию, безопасная реализация недопустимо медленная. И вы пытались улучшить алгоритм, вы сделали все возможное, но он по-прежнему работает медленно. И вы попробовали и увидели, что неуправляемая реализация работает достаточно быстрее. Ну, так .NET не является подходящей платформой для реализации именно этой части вашего кода. Вы реализуете код в собственной DLL или любой другой доступной на вашей платформе (возможно, на чистом C) и используете ее через P/Invoke. Таким образом, ваш небезопасный код закодирован на соответствующем языке, и вы можете использовать его, просто вызвав метод с помощью P/Invoke, или добавив оболочку C++/CLI, или любым другим способом взаимодействия в C#. Вы получаете (1) четкое разделение между управляемой бизнес-логикой и собственным очень быстрым кодом обработки, (2) лучшую ремонтопригодность, потому что теперь ваш быстрый код обработки чисел или перетасовки данных находится в соответствующей среде.

  3. Ну, вы видите, что даже такой подход почему-то не работает. Что ж, в этом исключительном случае вам, возможно, следует подумать об использовании небезопасного кода на C#. Но велика вероятность, что и это не поможет.

person Vlad    schedule 20.04.2012
comment
лучше ли делать interop, писать код c/c++ и пересекать границу .net framework, а затем идти на небезопасную территорию??? Мне было интересно, делаем ли мы взаимодействие, тогда мы теряем надежду на переносимость (для работы на Mono) - person Pritesh; 20.04.2012
comment
@Pritesh: не совсем так. Код C также является переносимым, поэтому единственной отличной частью является объявление P/Invoke (которое можно безопасно переключать с помощью препроцессора). - person Vlad; 20.04.2012