2013-03-21 1 views
5

Я начал кодировать программу обработки изображений из разных алгоритмов обработки изображений, в основном из работы Рене Шульте, и когда я сравнивал результаты тестов, я заметил, что из всех эффектов, которые я мог найти из разных источников, код для применения эффекта «Мягкий свет» был самым медленным. Я не умею оптимизировать уравнение, но я считаю, что фильтр основан на формуле, которая, возможно, повторяет переменные без причины.Является ли эта формула повторяющейся или оптимальной?

Не могли бы это быть обобщены на что-то более короткое или быстрое?

// Basically, b is from Image A, and t from Image B 
int csoftLight(float b, float t) 
     { 
      b /= 255; 
      t /= 255; 

      return (int)((t < 0.5) ? 255 * ((1 - 2 * t) * b * b + 2 * t * b) : 255 * ((1 - (2 * t - 1)) * b + (2 * t - 1) * (Math.Pow(b, 0.5)))); 
     } 

[Edit - результаты, используя уравнение Мохаммед Хоссейн найдено около SoftLight в PS]

// Input: 137 and 113 

// Byte version: 
int other = ((byte)((B < 128) ? (2 * ((A >> 1) + 64)) * ((float)B/255) : (255 - (2 * (255 - ((A >> 1) + 64)) * (float)(255 - B)/255)))); 
// Returns 116  


// float version: 
int res = (int)((t < 0.5) ? 255 * ((1 - 2 * t) * b * b + 2 * t * b) : 255 * ((1 - (2 * t - 1)) * b + (2 * t - 1) * (Math.Pow(b, 0.5)))); 
// Returns 129 

[Редактировать]

Вот самый быстрый алгоритм, основанный на Мохаммед Хоссейн ответ:

int csoftLight(byte A, byte B) 
{ 
    return (int)((A < 128) ? (2 * ((B >> 1) + 64)) * ((float)A/255) : (255 - (2 * (255 - ((B >> 1) + 64)) * (float)(255 - A)/255)));   
} 
+0

Я надеюсь, что компиляторы бы общее исключение подвыражения, но когда с плавающим point принимает участие ... – nneonneo

+0

И googling имя парня, который добавил этот код к исходному источнику, ничего не возвращает. Я в конечном итоге вызову кодер! –

+0

Арифметические операции с float более дороги, чем на целые числа. изменить типы параметров на int, тогда я могу предоставить решение. –

ответ

4

Этот ответ должен помочь вам и немного прояснить некоторые вещи: How does photoshop blend two images together?

Одним из уравнений является алгоритм мягкого света.

#define ChannelBlend_SoftLight(A,B) ((uint8)((B < 128)?(2*((A>>1)+64))*((float)B/255):(255-(2*(255-((A>>1)+64))*(float)(255-B)/255)))) //not very accurate 

Это важно избежать дорогостоящей операции квадратного корня и менее важно использует операторы битового сдвига вместо деления на 2 (который должен быть оптимизирован прочь смарт-составителей, в любом случае). Он также использует больше целых операций, чем плавающие операции, что происходит быстрее.

Вот другая формула (любезно владельцы this, который переключает операции с переменными, и это, казалось бы, работает ...

#define ChannelBlend_SoftLight(A,B) (uint8)(((A < 128) ? (2 * ((B >> 1) + 64)) * ((float) A/255) : (255 - (2 * (255 - ((B >> 1) + 64)) * (float) (255 - A)/255)))); 
+0

Ничего себе, вы получили именно контекст уравнения. Megaupvote! –

+0

Не знаю, что я делаю неправильно, но оно не возвращает правильное изображение: 'int csoftLight (byte A, byte B) { return ((byte) ((B <128)? (2 * ((A >> 1) + 64)) * ((float) B/255): (255 - (2 * (255 - ((A >> 1) + 64)) * (float) (255 - B)/255)))); } ' –

+1

Вы должны вызывать это для каждого канала пикселя; если вы делаете это в RGB, вы должны называть его три раза (R, G, B). Конечным продуктом являются три значения (R, G, B), которые являются тремя каналами выходного пикселя. Вы сейчас это делаете? –