На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: maxim84_
  
> FastBitmap , класс облегчающий работу с изображениями в usafe коде
    Просматривая примеры, поставляемые к Microsoft Parallel Extension CTP June 2007, обнаружил довольно полезный класс FastBitmap. Он в значительной мере может облегчить работу с unsafe обработкой изображений. Ниже приводится полный исходный код класса из примера.

    ExpandedWrap disabled
      //--------------------------------------------------------------------------
      //
      //  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();
              }
          }
      }


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

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

      Этот класс можно существенно улучшить. Так как основной смысл в написании подобных оболочек это максимально быстрые 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; Для попиксельной обработки изображения это существенный выигрыш.
      Сообщение отредактировано: i++ -
        Для таких случаев лучше использовать чистый BitBlt. Это не намного сложнее работы с этой библиотекой а скорость выше.
        0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
        0 пользователей:


        Рейтинг@Mail.ru
        [ Script execution time: 0,0184 ]   [ 15 queries used ]   [ Generated: 28.03.24, 20:36 GMT ]