我已經編寫了下一個算法(用於Android/NDK)將位數應用於位圖。問題是,真的非常慢,在像SGSIII這樣的快速設備上,對於800萬像素的圖像可能需要4秒鐘的時間。在配備ARMv6的設備上需要很長時間(超過10秒)。有什麼辦法可以優化它嗎?優化C++位圖處理算法
void applyLevels(unsigned int *rgb, const unsigned int width, const unsigned int height, const float exposure, const float brightness, const float contrast, const float saturation)
{
float R, G, B;
unsigned int pixelIndex = 0;
float exposureFactor = powf(2.0f, exposure);
float brightnessFactor = brightness/10.0f;
float contrastFactor = contrast > 0.0f ? contrast : 0.0f;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
const int pixelValue = buffer[pixelIndex];
R = ((pixelValue & 0xff0000) >> 16)/255.0f;
G = ((pixelValue & 0xff00) >> 8)/255.0f;
B = (pixelValue & 0xff)/255.0f;
// Clamp values
R = R > 1.0f ? 1.0f : R < 0.0f ? 0.0f : R;
G = G > 1.0f ? 1.0f : G < 0.0f ? 0.0f : G;
B = B > 1.0f ? 1.0f : B < 0.0f ? 0.0f : B;
// Exposure
R *= exposureFactor;
G *= exposureFactor;
B *= exposureFactor;
// Contrast
R = (((R - 0.5f) * contrastFactor) + 0.5f);
G = (((G - 0.5f) * contrastFactor) + 0.5f);
B = (((B - 0.5f) * contrastFactor) + 0.5f);
// Saturation
float gray = (R * 0.3f) + (G * 0.59f) + (B * 0.11f);
R = gray * (1.0f - saturation) + R * saturation;
G = gray * (1.0f - saturation) + G * saturation;
B = gray * (1.0f - saturation) + B * saturation;
// Brightness
R += brightnessFactor;
G += brightnessFactor;
B += brightnessFactor;
// Clamp values
R = R > 1.0f ? 1.0f : R < 0.0f ? 0.0f : R;
G = G > 1.0f ? 1.0f : G < 0.0f ? 0.0f : G;
B = B > 1.0f ? 1.0f : B < 0.0f ? 0.0f : B;
// Store new pixel value
R *= 255.0f;
G *= 255.0f;
B *= 255.0f;
buffer[pixelIndex] = ((int)R << 16) | ((int)G << 8) | (int)B;
pixelIndex++;
}
}
}
對於每個R/G/B值,您應該除去'/ 255.0'和'* 255.0',並使用255.0而不是1.0作爲最大值。這將消除昂貴的分工操作。你可能也想看看使用NEON,因爲這是SIMD的明顯候選者。 –
這個問題似乎是脫離主題,因爲它是關於codereview。你可以在http://codereview.stackexchange.com/上發帖。 – TemplateRex
試着不用浮動,看看普通整數數學是否足夠精確。畢竟,無論如何,你都以8位整數開始和結束。 –