Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.207.98.249] |
|
Сообщ.
#1
,
|
|
|
Просматривая примеры, поставляемые к Microsoft Parallel Extension CTP June 2007, обнаружил довольно полезный класс FastBitmap. Он в значительной мере может облегчить работу с unsafe обработкой изображений. Ниже приводится полный исходный код класса из примера.
//-------------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. All rights reserved. // // File: FastBitmap.cs // //-------------------------------------------------------------------------- using System; using System.Drawing; using System.Drawing.Imaging; namespace Microsoft.ParallelComputingPlatform.ParallelExtensions.Samples { internal struct PixelData { public byte B; public byte G; public byte R; } internal unsafe class FastBitmap : IDisposable { private readonly Bitmap _bitmap; private int _width; private BitmapData _bitmapData = null; private byte* _pBase = null; private PixelData* _pInitPixel = null; private Point _size; private bool _locked = false; public FastBitmap(Bitmap bmp) { if (bmp == null) throw new ArgumentNullException("bitmap"); _bitmap = bmp; _size = new Point(bmp.Width, bmp.Height); LockBitmap(); } public PixelData* GetInitialPixelForRow(int rowNumber) { return (PixelData*)(_pBase + rowNumber * _width); } public PixelData* this[int x, int y] { get { return (PixelData*)(_pBase + y * _width + x * sizeof(PixelData)); } } public Color GetColor(int x, int y) { PixelData* data = this[x, y]; return Color.FromArgb(data->R, data->G, data->B); } public void SetColor(int x, int y, Color c) { PixelData* data = this[x, y]; data->R = c.R; data->G = c.G; data->B = c.B; } private void LockBitmap() { if (_locked) throw new InvalidOperationException("Already locked"); var bounds = new Rectangle(0, 0, _bitmap.Width, _bitmap.Height); // Figure out the number of bytes in a row. This is rounded up to be a multiple // of 4 bytes, since a scan line in an image must always be a multiple of 4 bytes // in length. _width = bounds.Width * sizeof(PixelData); if (_width % 4 != 0) _width = 4 * (_width / 4 + 1); _bitmapData = _bitmap.LockBits(bounds, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); _pBase = (byte*)_bitmapData.Scan0.ToPointer(); _locked = true; } private void InitCurrentPixel() { _pInitPixel = (PixelData*)_pBase; } private void UnlockBitmap() { if (!_locked) throw new InvalidOperationException("Not currently locked"); _bitmap.UnlockBits(_bitmapData); _bitmapData = null; _pBase = null; _locked = false; } public void Dispose() { if (_locked) UnlockBitmap(); } } } Мне кажется, код не требует дополнительных комментариев и не должно возникнуть проблем с его использованием. Надеюсь информация оказалась для Вас полезной. |
Сообщ.
#2
,
|
|
|
В общем недавно тоже возникала необходимость в написании быстрого битмапа.
Этот класс можно существенно улучшить. Так как основной смысл в написании подобных оболочек это максимально быстрые SetPixel для ручной реализации алгоритмов. Поэтому от вызова метода SetPixel вообще лучше отказаться, а сделать метод возвращающий указатель (Int32*)_bitmapData.Scan0. Клиент сможет работать с изображением как с массивом целых чисел, где каждый элемент будет представлять цвет одного пиксела. Преобразовать цвет в целое можно экземплярным методом Color.ToArgb(). Таким образом экономия существенна, ведь вместо 4ех обращений к каждому из каналов data->R = c.R; data->G = c.G; data->B = c.B; data->A= c.A; Выполняется лишь одно data[index] = color; Для попиксельной обработки изображения это существенный выигрыш. |
Сообщ.
#3
,
|
|
|
Для таких случаев лучше использовать чистый BitBlt. Это не намного сложнее работы с этой библиотекой а скорость выше.
|