Como usar os valores de cores calculados com Colormatrix?
-
26-09-2019 - |
Pergunta
Estou alterando os valores de cores de cada pixel em uma imagem com base em um cálculo. O problema é que isso leva mais de 5 segundos na minha máquina com uma imagem de 1000x1333 e estou procurando uma maneira de otimizá -la para ser muito mais rápida.
Eu penso ColorMatrix
Pode ser uma opção, mas estou tendo dificuldades para descobrir como obteria um conjunto de valores de Pixel RGB, use isso para calcular e definir o novo valor de pixel. Eu posso ver como isso pode ser feito se eu estivesse apenas modificando (multiplicando, subtraindo etc.) o valor original com o Colormatrix, mas agora como posso usar o valor retornado dos pixels para usá -lo para calcular e novo valor.
Por exemplo:
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
o Luminance
O valor é o calculado. Eu sei que posso definir ColorMatrix
M00, M11, M22 a 0, 0, 0, respectivamente, e depois coloque um novo valor em M40, M41, M42, mas esse novo valor é calculado com base em uma multiplicação de valor e adição dos componentes desse pixel (((0.21 * (Clr.R) + (0.72 * (Clr.G)) + (0.07 * (Clr.B))
e o resultado disso - Luminance
- é multiplicado pelo componente de cores).
Isso é possível com ColorMatrix
?
Solução
Não. Tornar qualquer um dos componentes de cores que estão sendo multiplicados consigo mesmo ou qualquer outro componente não é possível com uma Colormatrix. Você pode multiplicar os componentes com constantes e depois adicionar as peças.
Mas o que você posso Faça é escrever isso no C# e usar .lockbits em vez de getpixel/setPixel. Isso seria ainda mais rápido que o que você poderia alcançar com uma Colormatrix.
ATUALIZAR: Algum código de amostra:
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;
}
}
}
}