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

int blender(const char* blendMode, int c1, int c2, int amount){

    int sob, sog, sor, soa, dsr, dsg, dsb, dsa = 0;

    dsr = Argb_GetRed(c1);
    dsg = Argb_GetGreen(c1);
    dsb = Argb_GetBlue(c1);
    dsa = Argb_GetAlpha(c1);

    sor = Argb_GetRed(c2);
    sog = Argb_GetGreen(c2);
    sob = Argb_GetBlue(c2);
    soa = Argb_GetAlpha(c2);


    int src_alpha, mix_alpha, dst_alpha;

    src_alpha = soa * ((255 * amount) / 100) >> 8;

    if (!strcmp(blendMode, "normal")) {
            PSD_BLEND_NORMAL(dsr, sor, mix_alpha);
            PSD_BLEND_NORMAL(dsg, sog, mix_alpha);
            PSD_BLEND_NORMAL(dsb, sob, mix_alpha);
    }
    else if (!strcmp(blendMode, "exclusion")) {

            mix_alpha = soa / 255;
            //.... it's not always just the 3 macros

            PSD_BLEND_EXCLUSION(dsr, sor, mix_alpha);
            PSD_BLEND_EXCLUSION(dsg, sog, mix_alpha);
            PSD_BLEND_EXCLUSION(dsb, sob, mix_alpha);
    }

    ~~~~~~~~~ X 20 or so blend modes ~~~~~~~~~~~~
}

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

Кроме того, он должен принимать исходную команду в виде строки (из json и передавать через java)

Я могу придумать пару способов сделать его более эффективным, но все они включают в себя написание двух гигантских операторов switch. Я бы предпочел использовать 1 оператор переключения или поиск, если это возможно

Спасибо!

0
Lerchmo 26 Мар 2011 в 00:20
Вы всегда можете вместо передачи строки передать целочисленный код функции, таким образом, вы можете сделать актуальный переключатель (который, вероятно, будет скомпилирован во что-то очень быстрое)
 – 
Dre
26 Мар 2011 в 09:39

1 ответ

Довольно неприятная проблема, но у меня есть "хакерская" идея.

Если имена 'blendMode' выбраны правильно, вы можете сравнить только первые две (или три) буквы строк. Если есть несколько строк с одинаковыми первыми буквами, вы можете сделать особый случай и сравнить первую и третью букву и так далее.

Этот прием сделает код намного быстрее, чем постоянный вызов strcmp(). Также может помочь встраивание функции сравнения.

Вот код:

/* compares first two letters of the string */
inline int fast_cmp(const char *mode, const char *cmp) {
    return (mode[0] == cmp[0] && mode[1] == cmp[1]) ? 1 : 0;
}

if( fast_cmp(blendMode, "no") ); /* for "normal"    */
if( fast_cmp(blendMode, "ex") ); /* for "exclusion" */

В действии: http://ideone.com/OiXS0.

Конечно, сравнения могут быть записаны непосредственно в операторах if/else, но это может привести к путанице. Это можно исправить с помощью небольшого и изящного макроса:

#define FAST_CMP(x, y) x[0] == y[0] && x[1] == y[1]

А вот макрос в действии: http://ideone.com/NQFwW

Эта версия макроса, пожалуй, самый быстрый способ сделать сравнение.

1
Athabaska Dick 26 Мар 2011 в 11:22