2014-11-13 1 views
2

Я пытаюсь создать алгоритм в C/C++, который применяет равномерный прозрачный градиент слева направо к буферу пикселей. Как видно на следующем изображении:Применение прозрачного градиента слева направо в C/C++

enter image description here

Следующая до сих пор моя реализация. Но получившийся образ даже не близок к тому, что мне нужно достичь. Кто-нибудь может понять, что я делаю неправильно? Благодаря

void alphaGradient(uint32_t* pixelsBuffer, const int width, const int height) 
{ 
    const short OPAQUE = 255; 
    int pixelOffsetY, pixelIndex; 
    short A, R, G, B; 

    for (int y = 0; y < height; y++) 
    { 
     A = OPAQUE; 

     pixelOffsetY = y * height; 

     for (int x = 0; x < width; x++) 
     { 
      pixelIndex = pixelOffsetY + x; 

      A = (int)(OPAQUE - ((OPAQUE * x)/width)); 
      R = (pixelsBuffer[pixelIndex] & 0x00FF0000) >> 16; 
      G = (pixelsBuffer[pixelIndex] & 0x0000FF00) >> 8; 
      B = (pixelsBuffer[pixelIndex] & 0x000000FF); 

      pixelsBuffer[pixelIndex] = (A << 24) + (R << 16) + (G << 8) + B; 
     } 
    } 
} 
+0

Как результат отличается от ожидаемого? Код выглядит отлично с первого взгляда. –

+2

Вы сильно смешиваете типы. В 'A' у вас есть приведение к подписанным значениям и' (A << 24) 'здесь вы меняете' short' на 24 байта. Разве это не неопределенное поведение? Возможно, все в порядке, но в некоторых случаях конверсии довольно сложны. – luk32

+4

Вы сделали простую ошибку: 'pixelOffsetY = y * height;' должно быть 'pixelOffsetY = y * width;' –

ответ

1

Я не пробовал этот код из но что-то, как это должно работать:

void alphaGradient(uint32_t* pixelBuffer, const int width, const int height) 
{ 
for (int i = 0; i < width; i++) 
{ 
    for (int j = 0; j < height; j++) 
    { 
     const DWORD src = pixelBuffer[i + j * width]; 
     const DWORD dst = MYBACKGROUNDCOLOR; 

     const unsigned char src_A = (width - i) * 255/width; 
     const unsigned char src_R = (src & 0x00FF0000) >> 16; 
     const unsigned char src_G = (src & 0x0000FF00) >> 8; 
     const unsigned char src_B = (src & 0x000000FF); 

     //const unsigned char dst_Alpha = (src & 0xFF000000) >> 24; 
     const unsigned char dst_R = (dst & 0x00FF0000) >> 16; 
     const unsigned char dst_G = (dst & 0x0000FF00) >> 8; 
     const unsigned char dst_B = (dst & 0x000000FF); 

     const unsigned char rlt_R = (src_R * src_A + dst_R * (255 - src_A))/255; 
     const unsigned char rlt_G = (src_G * src_A + dst_G * (255 - src_A))/255; 
     const unsigned char rlt_B = (src_B * src_A + dst_B * (255 - src_A))/255; 
     //pixelBuffer[i + j*width] = (DWORD)(((255) << 24) | (((rlt_R)& 0xff) << 16) | (((rlt_G)& 0xff) << 8) | ((rlt_B)& 0xff)); 
     // or if you want to save the transparancy then 
     //pixelBuffer[i + j*width] = (DWORD)(((src_A) << 24) | (((src_R)& 0xff) << 16) | (((src_G)& 0xff) << 8) | ((src_B)& 0xff)); 
    } 

} 
} 

Но лично я хотел бы попробовать использовать DirectX или OpenGL для этого и написать хорошую PixelShader. Это сделает это быстрее.

+0

Хороший комментарий, спасибо помощнику :). –

+0

Просто отлично. Работает так, как ожидалось. – PerracoLabs

+0

Вы премноделите цвета в этом случае. Возможно, это не то, что пользователь ищет ... это очень многое зависит от того, что сделано с изображением позже, но я думаю, что в вопросе ничего не говорилось об изменении цветов. –

0

В качестве предложения, поскольку вы хотите изменить альфа-канал, вам не нужно ничего делать с цветами. Таким образом, следующее будет работать:

char *b((char *) pixelBuffer); 
for(int j = 0; j < height; ++j) 
{ 
    for(int i = 0; i < width; ++i, b += 4) 
    { 
     *b = (width - i) * 255/width; 
    } 
} 

Всё. Можно также исключить вычисление для каждой строки, дублируя данные первой строки в следующих строках:

// WARNING: code expects height > 0! 
char *b((char *) pixelBuffer); 
for(int i = 0; i < width; ++i, b += 4) 
{ 
    *b = (width - i) * 255/width; 
} 
int offset = width * -4; 
for(int j = 1; j < height; ++j) 
{ 
    for(int i = 0; i < width; ++i, b += 4) 
    { 
     *b = b[offset]; 
    } 
} 

Я оставлю как упражнение для вас, чтобы изменить этот двойной for() цикл в одном for() цикле, который сделает его еще немного быстрее (потому что у вас будет один счетчик (переменная b) вместо трех).


Обратите внимание, что я не понимаю, как ответ Микаэла был бы работать, как он использует * 255 в неправильном месте в его вычислении альфа-канале. С целочисленной арифметикой это очень важно. Таким образом, это должно возвращать 0 или 255:

(width - i)/width * 255 

, потому что если value < width затем value/width == 0. И (width - i) либо width, либо значение меньше width ...

 Смежные вопросы

  • Нет связанных вопросов^_^