pixelbuffer.cs
来自「Fireball.CodeEditor is an source code ed」· CS 代码 · 共 1,714 行 · 第 1/4 页
CS
1,714 行
// Copyright (C) 2005/2006 Riccardo Marzi <riccardo@dotnetfireball.org>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Fireball.Collections.Generic;
namespace Fireball.Drawing.Drawing2D
{
public class PixelBuffer : IDisposable
{
#region Nested Classes
public unsafe class PixelIterator
{
private int* _pixel;
private int _startX;
private int _startY;
private int _width;
private int _height;
private int _startIndex;
private int _count;
private int _relativeX;
private int _relativeY;
private int _relativeIndex;
private int _lineOffset;
internal PixelIterator(int* buffer, int x, int y,int width,int height, int bufferWidth)
{
_startIndex = ((bufferWidth * y) + x);
buffer += _startIndex;
_pixel = buffer;
_startX = x;
_startY = y;
_width = width;
_height = height;
_count = _width * _height;
_relativeX = 0;
_relativeY = 0;
_relativeIndex = 0;
_lineOffset = bufferWidth - _width;
}
public int RelativeX
{
get
{
return _relativeX;
}
}
public int RelativeY
{
get
{
return _relativeY;
}
}
public int RelativeIndex
{
get
{
return _relativeIndex;
}
}
public int CurrentX
{
get
{
return _startX + _relativeX;
}
}
public int CurrenY
{
get
{
return _startY + _relativeY;
}
}
public int CurrentIndex
{
get
{
return _startIndex + _relativeIndex;
}
}
public int* CurrentPixel
{
get
{
return _pixel;
}
}
public bool MoveNext()
{
_relativeIndex++;
if (_relativeIndex < _count)
{
_relativeX++;
if (_relativeX == _width)
{
_relativeX = 0;
_relativeY++;
_pixel += _lineOffset;
}
_pixel++;
return true;
}
return false;
}
public void Reset()
{
_pixel -= _relativeIndex;
_relativeX = 0;
_relativeY = 0;
_relativeIndex = 0;
}
public int GetAlpha()
{
return ((*(_pixel)) >> 24) & 0xff;
}
public int GetRed()
{
return ((*(_pixel)) >> 16) & 0xff;
}
public int GetGreen()
{
return ((*(_pixel)) >> 8) & 0xff;
}
public int GetBlue()
{
return (*(_pixel)) & 0xff;
}
}
#endregion
#region Enums
public enum FlipMode
{
FlipHorizontal = 1,
FlipVertical = 2,
FlipBoth = 3
}
public enum ResizePivot
{
TopLeft=0,
TopCenter=1,
TopRight=2,
MiddleLeft=3,
MiddleCenter=4,
MiddleRight=5,
BottomLeft=6,
BottomCenter=7,
BottomRight=8
}
#endregion
#region Fields
private int[] _buffer;
private int _width;
private int _height;
private int _bytesCount;
private int _pixelsCount;
private PixelBufferGraphics _graphics;
private PixelBufferRenderer _renderer;
#endregion
#region Constructors
private unsafe PixelBuffer(int width, int height, int* buffer)
{
Initialize(width, height);
fixed (int* dest = _buffer)
{
CopyBuffer(dest, buffer, _buffer.Length);
}
}
internal unsafe PixelBuffer(int width, int height, int[] buffer)
{
Initialize(width, height);
fixed (int* dest = _buffer)
{
fixed (int* src = buffer)
{
CopyBuffer(dest, src, _buffer.Length);
}
}
}
public PixelBuffer(int width, int height)
{
Initialize(width, height);
}
public PixelBuffer(Bitmap bmp)
: this(bmp.Width, bmp.Height)
{
CopyBitmapToBuffer(bmp);
}
#endregion
#region Destructors
~PixelBuffer()
{
this.Dispose();
}
public void Dispose()
{
_graphics.Dispose();
_buffer = null;
}
#endregion
#region Initialize
private unsafe void Initialize(int width, int height)
{
_width = width;
_height = height;
_pixelsCount = _width * _height;
_bytesCount = _pixelsCount * 4;
_buffer = new int[_pixelsCount];
_renderer = new PixelBufferManagedRenderer(this);
//_graphics = new PixelBufferGraphics(this);
_graphics = new PixelBufferManagedGraphics(this);
}
#endregion
#region Private Members
private int BlendColorByAlpha(int backColor, int foreColor)
{
int foreBlue = foreColor & 0xff;
int foreGreen = (foreColor >> 8) & 0xff;
int foreRed = (foreColor >> 16) & 0xff;
int foreAlpha = (foreColor >> 24) & 0xff;
int backBlue = backColor & 0xff;
int backGreen = (backColor >> 8) & 0xff;
int backRed = (backColor >> 16) & 0xff;
int backAlpha = (backColor >> 24) & 0xff;
int displayAlpha = foreAlpha * foreAlpha / 255 + backAlpha * (255 - foreAlpha) / 255;
int displayRed = foreRed * foreAlpha / 255 + backRed * (255 - foreAlpha) / 255;
int displayGreen = foreGreen * foreAlpha / 255 + backGreen * (255 - foreAlpha) / 255;
int displayBlue = foreBlue * foreAlpha / 255 + backBlue * (255 - foreAlpha) / 255;
int color = ((displayAlpha << 24) | (displayRed << 16) | (displayGreen << 8) | displayBlue);
return color;
}
private unsafe void BlendBufferColor(int* dest, int color)
{
for (int i = 0; i < _pixelsCount; i++)
{
int cDest = *((int*)dest);
*((int*)dest) = BlendColorByAlpha(cDest, color);
dest++;
}
}
private unsafe void BlendBufferRectBuffer(int* dest, int* src, int x, int y, int width, int height)
{
int lineOffset = (_width - width);
int start = GetPixelBytesIndex(x, y,_width);
dest += start;
for (int iy = 0; iy < height; iy++)
{
for (int ix = 0; ix < width; ix++)
{
int cDest = *((int*)dest);
int cSrc = *((int*)src);
*((int*)dest) = BlendColorByAlpha(cDest, cSrc);
dest++;
src++;
}
dest += lineOffset;
}
}
private unsafe void BlendBufferRectBufferOutside(int[] srcBuffer, int x, int y, int width, int height)
{
int sx = 0;
int sy = 0;
int sw = width;
int sh = height;
if (x < 0)
{
sx = -x;
sw += x;
}
else if ((x + width) > _width)
{
sx = 0;
sw = _width - x;
}
if (y < 0)
{
sy = -y;
sh += y;
}
else if ((y + height) > _height)
{
sy = 0;
sh = _height - y;
}
if (sw <= 0 || sh <= 0)
{
return;
}
//TODO: problema con l'indice del pixel di un buffer senza istanza
//
//int[] blitBufferArray = new int[sw * sh];
//fixed (int* src = srcBuffer)
//{
// fixed (int* dest = blitBufferArray)
// {
// CopyBufferRect(dest, src, sx, sy, sw, sh);
// }
//}
PixelBuffer srcBufferHelper = new PixelBuffer(width, height, srcBuffer);
PixelBuffer blitBufferArray = srcBufferHelper.GetSubBuffer(sx, sy, sw, sh);
int fx = x;
int fy = y;
if (x < 0) fx = 0;
if (y < 0) fy = 0;
fixed (int* src = blitBufferArray.InternalBuffer)
{
fixed (int* dest = _buffer)
{
BlendBufferRectBuffer(dest, src, fx, fy, sw, sh);
}
}
srcBufferHelper.Dispose();
blitBufferArray.Dispose();
}
private unsafe void BlendBufferRectColor(int* dest, int color, int x, int y, int width, int height)
{
int lineOffset = (_width - width);
int start = GetPixelBytesIndex(x, y,_width);
dest += start;
for (int iy = 0; iy < height; iy++)
{
for (int ix = 0; ix < width; ix++)
{
int cDest = *((int*)dest);
*((int*)dest) = BlendColorByAlpha(cDest, color);
dest++;
}
dest += lineOffset;
}
}
private unsafe void BlendBufferRectColorOutside(int color, int x, int y, int width, int height)
{
int sx = x;
int sy = y;
int sw = width;
int sh = height;
if (x < 0)
{
sx = 0;
sw += x;
}
else if ((x + width) > _width)
{
sw = _width - x;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?