Tengo un pequeño programa de pintura en el que estoy trabajando. Estoy usando SetPixel en un mapa de bits para hacer ese dibujo de líneas. Cuando el tamaño del pincel aumenta, al igual que 25 píxeles de ancho, se produce una notable disminución del rendimiento. Me pregunto si hay una forma más rápida de dibujar en un mapa de bits. Aquí hay un poco del trasfondo del proyecto:SetPixel es demasiado lento. ¿Hay una forma más rápida de dibujar en mapa de bits?
- Estoy usando mapas de bits para poder utilizar capas, como en Photoshop o The GIMP.
- Las líneas se dibujan manualmente porque con el tiempo se usará la presión de la tableta gráfica para modificar el tamaño de la línea en toda su longitud.
- Las líneas deberían eventualmente estar antialiadas/suavizadas a lo largo de los bordes.
Incluiré mi código de dibujo en caso de que sea esto lento y no del bit de Set-Pixel.
Esto es en las ventanas donde la pintura sucede:
private void canvas_MouseMove(object sender, MouseEventArgs e)
{
m_lastPosition = m_currentPosition;
m_currentPosition = e.Location;
if(m_penDown && m_pointInWindow)
m_currentTool.MouseMove(m_lastPosition, m_currentPosition, m_layer);
canvas.Invalidate();
}
Implementación de MouseMove:
public override void MouseMove(Point lastPos, Point currentPos, Layer currentLayer)
{
DrawLine(lastPos, currentPos, currentLayer);
}
Implementación de DrawLine:
// The primary drawing code for most tools. A line is drawn from the last position to the current position
public override void DrawLine(Point lastPos, Point currentPos, Layer currentLayer)
{
// Creat a line vector
Vector2D vector = new Vector2D(currentPos.X - lastPos.X, currentPos.Y - lastPos.Y);
// Create the point to draw at
PointF drawPoint = new Point(lastPos.X, lastPos.Y);
// Get the amount to step each time
PointF step = vector.GetNormalisedVector();
// Find the length of the line
double length = vector.GetMagnitude();
// For each step along the line...
for (int i = 0; i < length; i++)
{
// Draw a pixel
PaintPoint(currentLayer, new Point((int)drawPoint.X, (int)drawPoint.Y));
drawPoint.X += step.X;
drawPoint.Y += step.Y;
}
}
Implementación de PaintPoint:
public override void PaintPoint(Layer layer, Point position)
{
// Rasterise the pencil tool
// Assume it is square
// Check the pixel to be set is witin the bounds of the layer
// Set the tool size rect to the locate on of the point to be painted
m_toolArea.Location = position;
// Get the area to be painted
Rectangle areaToPaint = new Rectangle();
areaToPaint = Rectangle.Intersect(layer.GetRectangle(), m_toolArea);
// Check this is not a null area
if (!areaToPaint.IsEmpty)
{
// Go through the draw area and set the pixels as they should be
for (int y = areaToPaint.Top; y < areaToPaint.Bottom; y++)
{
for (int x = areaToPaint.Left; x < areaToPaint.Right; x++)
{
layer.GetBitmap().SetPixel(x, y, m_colour);
}
}
}
}
Muchas gracias por cualquier ayuda que puede proporcionar.
Gracias por esto. Creo que veo lo que está pasando; ptr es un conjunto de datos de mapa de bits que contiene los valores de píxel rojo, verde y azul y los configura manualmente. Voy a probar esto hoy y ver cómo funciona. Muchas gracias por esto, siento que mi entendimiento ha avanzado en otro nivel: P Sin embargo, solo una cosa, pensé que un mapa de bits en C# también tiene un canal alfa. Pensé que esto se manejaría en la información de color del píxel junto con el RGB. – Pyro
Debe especificar http://msdn.microsoft.com/en-us/library/system.drawing.imaging.pixelformat.aspx para incluir un componente alfa. Simplemente cambie 'PixelFormat.Format24bppRgb' a' PixelFormat.Format32bppArgb'. Creo que debería ser después de R, así que solo lo compensé con +3. Si usa 32 bits por píxel, necesitará cambiar 'x * 3' a' x * 4' ya que ahora será de 4 bytes por píxel. – Jack
Acabo de probar esto. ¡Ahora es encantador y rápido en todos los tamaños de pincel! Sin embargo, ahora hay algún comportamiento extraño: el dibujo real ocurre en un desplazamiento hacia donde se encuentra el mouse. Me pregunto si tiene algo que ver con esta línea aquí: BitmapData data = bmp.LockBits (new Rectangle (areaToPaint.Right, areaToPaint.Bottom), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); Tiene que haber una posición especificada para el rectángulo. Utilicé el valor 'posición' suministrado. ¿Está bien? – Pyro