Что состоит в том, чтобы сказать эффективный путь, является ли битовый массив совершенно черным?

Я задаюсь вопросом, существует ли суперэффективный способ подтвердить, что Объект изображения ссылается на совершенно черное изображение, таким образом, каждый пиксель в битовом массиве является ARGB (255, 0, 0, 0).

Что Вы порекомендуете? Большинство этих битовых массивов составит 1024 x 6 000 пикселей (хотя не безопасно предположить, что они всегда будут тем размером).

Мне нужно это, потому что у нас есть проблемы с PrintWindow API. Мы находим, что почти 20% времени, по крайней мере некоторая часть изображения будет черным квадратом (последующее получение успешно выполнится). Моя идея работать вокруг этого состояла в том, чтобы назвать PrintWindow или WM_PRINT с каждым дочерним окном, затем соединить целое изображение окна назад вместе. Если я могу найти эффективный способ обнаружить, что PrintWindow возвратил черное изображение для конкретного дочернего окна, то я могу быстро назвать PrintWindow снова на том получении. Это сосет, но PrintWindow является единственным методом получения окна, которое работает над всеми окнами (что я хочу, так или иначе), и окна получения поддержек, которые скрыты и/или вне экрана.

Когда PrintWindow перестал работать, он не устанавливает код ошибки или возвращает что-либо, что указывает, что он перестал работать. Когда это имеет эту черную квадратную проблему, это всегда - все окно или дочернее окно, которое возвращается черный. Таким образом путем получения каждого дочернего окна отдельно, я могу быть уверен, что каждое из моих получений будет работать, если это содержит по крайней мере один нечерный пиксель.

PrintWindow лучше в Vista и выше, по-видимому, но в этом случае мы ограничены Сервером 2003.

21
задан Matt Brindley 31 March 2010 в 21:26
поделиться

9 ответов

Я бы рекомендовал вам заблокировать растровое изображение в памяти с помощью метода LockBits типа System.Drawing.Bitmap. Этот метод возвращает тип BitmapData, из которого можно получить указатель на заблокированную область памяти. Затем выполните итерацию по памяти, ища ненулевые байты (на самом деле, быстрее, сканируя значения Int32 или даже Int64, в зависимости от используемой платформы). Код будет выглядеть следующим образом:

// Lock the bitmap's bits.  
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
BitmapData bmpData =bmp.LockBits(rect, ImageLockMode.ReadWrite, bmp.PixelFormat);

// Get the address of the first line.
IntPtr ptr = bmpData.Scan0;

// Declare an array to hold the bytes of the bitmap.
int bytes  = bmpData.Stride * bmp.Height;
byte[] rgbValues = new byte[bytes];

// Copy the RGB values into the array.
Marshal.Copy(ptr, rgbValues, 0, bytes);

// Scanning for non-zero bytes
bool allBlack = true;
for (int index = 0; index < rgbValues.Length; index++)
    if (rgbValues[index] != 0) 
    {
       allBlack = false;
       break;
    }
// Unlock the bits.
bmp.UnlockBits(bmpData);

Рассмотрим использование небезопасного кода и прямого доступа к памяти (с использованием указателей) для повышения производительности.

20
ответ дан 29 November 2019 в 20:06
поделиться

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

6
ответ дан 29 November 2019 в 20:06
поделиться

Всего лишь несколько случайных мыслей:

  • Возможно, вы могли бы применить ColorMatrix к исходному растровому изображению (чтобы полностью превратить его в черный) . Затем сравните результат с оригиналом.
  • Или создайте растровое изображение идентичного размера (заполненное чистым черным цветом), а затем сравните его с исходным растровым изображением.
1
ответ дан 29 November 2019 в 20:06
поделиться

Было бы проще, если бы вы знали больше об условиях, при которых изображение не будет черным. Например, как выглядят края или центр изображения, если оно не черное. По сути, то, что вы создаете, является эвристическим, чтобы угадать не-черное изображение и выбрать те области, которые позволят вам быстрее всего его прочитать. Если ваша эвристика указывает на полностью черное изображение, вы можете решить, что оно полностью черное, или выполнить полную проверку всех пикселей. Однако это сильно зависит от ваших изображений. Если вам нужно различать полностью черное изображение и изображение, содержащее один не черный пиксель в случайном месте, вам придется проверить их все.

7
ответ дан 29 November 2019 в 20:06
поделиться

Использование библиотеки AForgeNET ( http: // www .aforgenet.com ) также может быть решением:

public bool IsNotBlackImage()
{
    Assembly assembly = this.GetType().Assembly;
    var imgTest = new Bitmap(assembly.GetManifestResourceStream("TestImage.png"));
    var imgStatistics = new ImageStatistics(imgTest);             
    return imgStatistics.PixelsCountWithoutBlack != 0;
}

Для ссылки на класс ImageStatistics AForge.Imaging.dll в вашем проекте.

http://code.google.com/p/aforge/source/browse/trunk/Sources/Imaging/ImageStatistics.cs

3
ответ дан 29 November 2019 в 20:06
поделиться

Нарисуйте битмап с помощью ColorMatrix, которая имеет 3 x 255 в диагонали, что приведет к тому, что любой нечерный пиксель станет чисто белым. Затем перерисуйте этот битмап в меньший, ширина которого кратна 4 и имеет формат Format24bppRgb. Это устранит альфу, уменьшит размер и оставит только нули, если растровая карта действительно черная.

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

2
ответ дан 29 November 2019 в 20:06
поделиться

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

Если вы знаете тип файла, вы знаете некоторые основные вещи о средних коэффициентах сжатия. И вы можете легко определить размеры файла, не просматривая весь файл.

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

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

Если у вас много случаев, когда не полностью черные изображения довольно близки к полностью черным, очевидно, что этот метод не будет работать.

1
ответ дан 29 November 2019 в 20:06
поделиться

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

1
ответ дан 29 November 2019 в 20:06
поделиться

У меня есть нестандартная идея.

А как насчет контрольной суммы CRC ? Вы можете сначала проверить размеры изображения, затем вычислить контрольную сумму и сравнить ее с известными (предварительно вычисленными) контрольными суммами полностью черного изображения тех же размеров.

РЕДАКТИРОВАТЬ: Я сомневаюсь, что это будет быстрее, чем метод @leonard. Единственная причина, по которой это могло быть, заключается в том, что исходный файл не был растровым, а был сжатым форматом изображения. Таким образом, алгоритму контрольной суммы CRC не пришлось бы распаковывать изображение перед запуском.

1
ответ дан 29 November 2019 в 20:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: