Comment utiliser les valeurs calculées couleur avec ColorMatrix?
-
26-09-2019 - |
Question
Je change les valeurs de couleur de chaque pixel dans une image basée sur un calcul. Le problème est que cela prend plus de 5 secondes sur ma machine avec une image 1000x1333 et je suis à la recherche d'une façon d'optimiser à être beaucoup plus rapide.
Je pense que ColorMatrix
peut être une option, mais je vais avoir un chiffre moment difficile comment je recevrais un ensemble de pixels valeurs RVB, utiliser pour calculer et définir la nouvelle valeur de pixel. Je peux voir comment cela peut se faire que si je ne faisais que de modification (multiplication, soustraction, etc.) la valeur originale avec ColorMatrix, mais maintenant comment je peux utiliser les pixels retournés valeur à utiliser pour calculer et nouvelle valeur.
Par exemple:
Sub DarkenPicture()
Dim clrTestFolderPath = "C:\Users\Me\Desktop\ColorTest\"
Dim originalPicture = "original.jpg"
Dim Luminance As Single
Dim bitmapOriginal As Bitmap = Image.FromFile(clrTestFolderPath + originalPicture)
Dim Clr As Color
Dim newR As Byte
Dim newG As Byte
Dim newB As Byte
For x = 0 To bitmapOriginal.Width - 1
For y = 0 To bitmapOriginal.Height - 1
Clr = bitmapOriginal.GetPixel(x, y)
Luminance = ((0.21 * (Clr.R) + (0.72 * (Clr.G)) + (0.07 * (Clr.B))/ 255
newR = Clr.R * Luminance
newG = Clr.G * Luminance
newB = Clr.B * Luminance
bitmapOriginal.SetPixel(x, y, Color.FromArgb(newR, newG, newB))
Next
Next
bitmapOriginal.Save(clrTestFolderPath + "colorized.jpg", ImageFormat.Jpeg)
End Sub
La valeur de Luminance
est celui calculé. Je sais que je peux mettre M00, M11, M22 à 0 de ColorMatrix
, 0, 0, respectivement, et puis mettre une nouvelle valeur dans M40, M41, M42, mais cette nouvelle valeur est calculée à partir d'une multiplication de la valeur et l'ajout de (((0.21 * (Clr.R) + (0.72 * (Clr.G)) + (0.07 * (Clr.B))
composants de ce pixel et le résultat de cette - Luminance
-. est multipliée par la composante de couleur)
Est-ce même possible avec ColorMatrix
?
La solution
. Faire une quelconque des composantes de couleur étant multipliée par elle-même ou tout autre composant est pas possible avec un ColorMatrix. Vous pouvez ony multiplier les composants avec des constantes, puis ajoutez les pièces ensemble.
Mais ce que vous peut faire est d'écrire cela en C # et l'utilisation .LockBits au lieu de GetPixel / SetPixel. Ce serait encore plus rapide que ce que vous pourriez obtenir avec un ColorMatrix.
UPDATE : un exemple de code:
private static void myVerySpecialSepia(
IntPtr source,
IntPtr destination,
int height,
int width,
int sourceStride,
int destinationStride,
int sourceBytesPerPixel,
int destinationBytesPerPixel )
{
unsafe
{
for ( int y = 0 ; y < height ; y++ )
{
byte* pOrig = (byte*)source.ToPointer() + sourceStride * y;
byte* pDest = (byte*)destination.ToPointer() + destinationStride * y;
for ( int x = width ; x > 0 ; x-- )
{
float b = pOrig[0];
float g = pOrig[1];
float r = pOrig[2];
float b2 = b * b;
float g2 = g * g;
float r2 = r * r;
pDest[0] = (byte)(
b * 0.400367618f + b2 * 0.00011502471f +
g * (-0.0337239578f) + g2 * 0.00056673412f +
r * 0.221445322f + r2 * 0.0008506606f +
6.2766808485f);
pDest[1] = (byte)(
b * 0.493460029f + b2 * (-0.00023297003f) +
g * (-0.008577178f) + g2 * 0.00031247039f +
r * 0.5043012 + r2 * (-0.00006892065f) +
0.2746957206f);
pDest[2] = (byte)(
b * 0.617727f + b2 * (-0.00070876251f) +
g * 0.00271902746f + g2 * 0.00007401942f +
r * 0.6954346f + r2 * (-0.00065937551f) +
0.116103285f);
pOrig += sourceBytesPerPixel;
pDest += destinationBytesPerPixel;
}
}
}
}