Cómo utilizar valores de color calculados con ColorMatrix?
-
26-09-2019 - |
Pregunta
Estoy cambiando los valores de color de cada píxel de una imagen basada en un cálculo. El problema es que esto toma más de 5 segundos en mi máquina con una imagen de 1000x1333 y estoy buscando una manera de optimizar que sea mucho más rápido.
Creo ColorMatrix
puede ser una opción, pero estoy teniendo una figura difícil momento cómo me gustaría tener un conjunto de valores RGB de píxeles, el uso que para calcular y establecer el nuevo valor de píxel. Puedo ver cómo esto se puede hacer si sólo estaba modificando (multiplicar, restar, etc.) el valor original con ColorMatrix, pero ahora cómo puedo usar los píxeles devueltos valor a utilizar para calcular y nuevo valor.
Por ejemplo:
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
El valor Luminance
es la calculada. Sé que puedo fijar de ColorMatrix
M00, M11, M22 a 0, 0, 0, respectivamente, y luego poner un nuevo valor en M40, M41, M42, pero que el nuevo valor se calcula a partir de una multiplicación valor y la adición de los componentes de ese píxel (((0.21 * (Clr.R) + (0.72 * (Clr.G)) + (0.07 * (Clr.B))
y el resultado de que - Luminance
-. se multiplica por el componente de color)
Es esto posible con ColorMatrix
?
Solución
No. Hacer cualquiera de los componentes de color se multiplica por sí mismo o cualquier otro componente no es posible con un ColorMatrix. Puede ony multiplican los componentes con constantes y luego añadir las piezas juntas.
Pero lo que puede hacer es escribir esto en C # y uso .LockBits en lugar de GetPixel / SetPixel. Eso sería aún más rápido que lo que lo que pueda lograr con un ColorMatrix.
Actualizar : un código de ejemplo:
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;
}
}
}
}