Собственная обработка растровых изображений и ALPHA_8 - PullRequest
6 голосов
/ 02 октября 2011

Я пытаюсь преобразовать изображение в оттенки серого с помощью встроенной функции, используя фрагмент кода, взятый из Android в действии (2-е изд .; вы также можете увидеть его здесь ). К сожалению, возвращенный растровый объект вместо градаций серого оказывается пустым.

Вот как я загружаю (.png) изображение:

Bitmap original = BitmapFactory.decodeResource(this.getResources(), R.drawable.sample, options);

Существует ряд условий безопасности, которые передает растровое изображение (проверьте ниже). Вот определение нативной функции в Java:

public native void convertToGray(Bitmap bitmapIn,Bitmap bitmapOut);

и звонок:

// Grayscale bitmap (initially empty)     
Bitmap gray = Bitmap.createBitmap(original.getWidth(),original.getHeight(),Config.ALPHA_8);
// Native function call
convertToGray(original,gray);

А вот и функция:

JNIEXPORT void JNICALL Java_com_example_Preprocessor_convertToGray(JNIEnv * env, jobject  obj, jobject bitmapcolor,jobject bitmapgray)
{
    AndroidBitmapInfo infocolor;
    AndroidBitmapInfo infogray; 
    void* pixelscolor;
    void* pixelsgray;
    int ret;
    int y;
    int x;    

    LOGI("convertToGray");
    if ((ret = AndroidBitmap_getInfo(env, bitmapcolor, &infocolor)) < 0) {
        LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
        return;
    }    

    if ((ret = AndroidBitmap_getInfo(env, bitmapgray, &infogray)) < 0) {
        LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
        return;
    }

    LOGI("color image :: width is %d; height is %d; stride is %d; format is %d;flags is %d",infocolor.width,infocolor.height,infocolor.stride,infocolor.format,infocolor.flags);
    if (infocolor.format != ANDROID_BITMAP_FORMAT_RGBA_8888) {
        LOGE("Bitmap format is not RGBA_8888 !");
        return;
    }  

    LOGI("gray image :: width is %d; height is %d; stride is %d; format is %d;flags is %d",infogray.width,infogray.height,infogray.stride,infogray.format,infogray.flags);
    if (infogray.format != ANDROID_BITMAP_FORMAT_A_8) {
        LOGE("Bitmap format is not A_8 !");
        return;
    }   

    if ((ret = AndroidBitmap_lockPixels(env, bitmapcolor, &pixelscolor)) < 0) {
        LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
    }

    if ((ret = AndroidBitmap_lockPixels(env, bitmapgray, &pixelsgray)) < 0) {
        LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
    }

    // modify pixels with image processing algorithm
    for (y=0;y<infocolor.height;y++) {
        argb * line = (argb *) pixelscolor;
        uint8_t * grayline = (uint8_t *) pixelsgray;
        for (x=0;x<infocolor.width;x++) {
            grayline[x] = 0.3 * line[x].red + 0.59 * line[x].green + 0.11*line[x].blue;
        }

        pixelscolor = (char *)pixelscolor + infocolor.stride;
        pixelsgray = (char *) pixelsgray + infogray.stride;
    }

    LOGI("Done! Unlocking pixels...");
    AndroidBitmap_unlockPixels(env, bitmapcolor);
    AndroidBitmap_unlockPixels(env, bitmapgray);
}

Цветное растровое изображение передается правильно, и обрабатывающая часть кода, кажется, работает нормально, но bitmapgray остается пустой. Я полагаю, что здесь что-то упущено.

Тестовая среда: эмулятор, v2.2. В этой версии функция работает, когда собственный код вызывается из основного потока . В эмуляторе 2.3 функция не работает независимо от потока , который вызывает код C, или способа загрузки растрового изображения. Android NDK: 4b и 6b.

ОБНОВЛЕНИЕ № 1: Вы найдете полный исходный код здесь .

ОБНОВЛЕНИЕ № 2: RGB_565 вместо ALPHA_8 дает некоторые результаты. Похоже, даже setPixels () в Java не работает для ALPHA_8, и я имею Проблемы с поиском информации по этому типу конфигурации. Любая помощь будет высоко ценится.

Ответы [ 3 ]

1 голос
/ 12 апреля 2012

У меня были такие же проблемы.Я не очень старался, чтобы ALPHA_8 работал, но использование ARGB_8888 устраняет проблему.

Кстати, в ответ на комментарий @ white_pawn (извините, я не могу отвечать на комментарии)

Структура argb в IBM пример в неправильном порядке.в моих эмуляторах или телефоне преобразование его в RGBA устраняет проблему (возможно, это причина того, что ваше изображение выглядит синим, потому что вы используете alpa для синего).Хотя я не уверен, зависит ли этот порядок от аппаратного.

typedef struct
{
    uint8_t red;
    uint8_t green;
    uint8_t blue;
    uint8_t alpha;
} argb;
1 голос
/ 31 октября 2011

У меня была похожая проблема.Прежде всего, я использовал формат Android RGBA_8888 для Infogray вместо A_8 (исходное растровое изображение было создано с использованием формата ARGB_8888).Затем, если вы используете структуру argb для серой линии вместо uint_8, вы можете заполнить пиксели следующим образом:

for (y = 0; y < infocolor.height; ++y) {
       argb* line = (argb*) pixelscolor;
       argb* grayline = (argb*) pixelsgray;
       for (x = 0; x < infocolor.width; ++x) {         
          grayline[x].red = grayline[x].green = grayline[x].blue = 0.3 * line[x].red + 0.59 * line[x].green + 0.11 * line[x].blue;
       }
       pixelscolor = (char*)pixelscolor + infocolor.stride;
       pixelsgray = (char*)pixelsgray + infogray.stride;
   }
0 голосов
/ 19 мая 2012

У меня была такая же проблема, и я нашел, что пошло не так!Когда вы используете APHA_8, вам нужно изменить фон на # ffffffff ,

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#ffffffff">
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...