SetPixel est trop lent. Existe-t-il un moyen plus rapide de dessiner sur bitmap?
J'ai un petit programme de dessin que je suis en train de travailler sur. Je suis à l'aide de SetPixel sur un bitmap à faire pour que le dessin des lignes. Lorsque la taille de la brosse est grande, à l'instar de 25 pixels à travers, il est notable de la chute des performances. Je me demande si il existe un moyen plus rapide de faire une image bitmap. Ici c'est un peu du contexte du projet:
- Je suis en utilisant des images pour que je puisse utiliser des couches, comme dans Photoshop ou The GIMP.
- Lignes sont dessinées manuellement car ce sera finalement l'utilisation de la tablette graphique de la pression de modifier la taille de la ligne sur toute sa longueur.
- Les lignes devraient finalement être anti-aliaced/lissé sur les bords.
Je vais l'inscrire mon code de dessin juste au cas où c'est ce qui est lent et non pas sur l'Ensemble de Pixels bits.
C'est dans les fenêtres où la peinture se passe:
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();
}
Mise en œuvre de MouseMove:
public override void MouseMove(Point lastPos, Point currentPos, Layer currentLayer)
{
DrawLine(lastPos, currentPos, currentLayer);
}
Mise en œuvre 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;
}
}
Mise en œuvre 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);
}
}
}
}
Merci beaucoup pour toute aide que vous pouvez fournir.
source d'informationauteur Pyro
Vous devez vous connecter pour publier un commentaire.
Vous pouvez verrouiller les données de l'image et utiliser des pointeurs pour définir manuellement les valeurs. C'est beaucoup plus rapide. Si vous aurez à utiliser le code unsafe.
SetPixel fait ceci:
est verrouille l'ensemble de l'image, fixe le pixel et il se déverrouille
essayer de le faire: vous acquérir un verrou pour l'ensemble de la mémoire d'image avec lockbits, le processus de mise à jour et de libérer le verrou après.
lockbits
J'ai l'habitude d'utiliser un tableau pour représenter les premières données de pixels. Et puis les copier entre ce tableau et le bitmap avec le code unsafe.
Du tableau de
Color
est une mauvaise idée, car leColor
struct est relativement importante(12 octets+). Ainsi, vous pouvez définir votre propre 4 octets struct(c'est celui que j'ai choisi) ou simplement utiliser un tableau deint
oubyte
.Vous devez aussi réutiliser votre tableau, car GC sur la liturgie des heures a tendance à être coûteux.
Mon code peut être trouvé à:
https://github.com/CodesInChaos/ChaosUtil/blob/master/Chaos.Image/
Une alternative est d'écrire tout votre code à l'aide de pointeurs dans le bitmap directement. C'est un peu plus rapide, mais peut rendre le code plus laide et plus enclins à faire des erreurs.
Juste une idée: Remplir un écran bitmap avec votre Brosse pixels. Vous avez seulement besoin de régénérer cette image lorsque le pinceau, la taille ou la couleur est modifiée. Et puis il suffit de dessiner cette image sur votre bitmap, où la souris se trouve.
Si vous pouvez moduler une image avec une couleur, vous pouvez définir les pixels en niveaux de gris et de moduler avec le pinceau de la couleur.
Vous appelez GetBitmap au sein de votre imbriqués pour la boucle. On dirait que ce n'est pas nécessaire, vous devez GetBitmap à l'extérieur de la pour les boucles comme la référence n'est pas près de changer.
Aussi regarder @fantasticfix réponse, Lockbits presque toujours des sortes de ralentir les performances des problèmes avec l'obtention de réglage/pixels