Заполнение данных в растровом Android как можно быстрее из C - PullRequest
14 голосов
/ 15 октября 2011

Мне удалось создать android.graphics.Bitmap, и я успешно заполняю его с помощью команды SetPixels.

Проблема в том, что я начинаю с данных RGBA.Затем я создаю jintArray.Затем я вызываю SetIntArray (эффективно запоминаю данные в буфере).Затем, наконец, я вызываю setPixels для фактической установки пикселей (что, по-видимому, вызывает другую копию).

Одна большая проблема, связанная с этим, заключается в том, что независимо от того, использовал ли я R8G8B8A8, или R5G6B5, или A8, мне все еще нужно преобразовать свои данные пикселейк данным R8G8B8A8.

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

Есть ли какой-либо способ непосредственно попасть в буферданные, содержащиеся в растровом изображении?Я вижу, что в JNI есть функция GetDirectBufferAddress, но в документации, которую я могу найти, предлагается ограничить ее java.nio.buffer.Могу ли я напрямую получить данные пикселей с помощью этой функции?Возможно, получая внутренний буфер, используемый классом Bitmap?

Является ли мой единственный способ использовать это для создания Global Ref'd Java.nio.buffer, тогда каждый раз, когда я хочу обновить, скопировать в него данные моего пикселя и затем использовать copyPixelsFromBuffer?Это все еще включает 2 копии, но может, по крайней мере, устранить изменение формата пикселя.Это будет более эффективным, чем метод, который я уже использую?

Есть ли еще лучший способ сделать это?

Кстати, я AM осознаю тот факт, что я могу использовать функции в , ноМне бы очень хотелось не потерять поддержку Android 2.1 и Android 2.2 ...

Заранее спасибо!

Ответы [ 2 ]

4 голосов
/ 25 октября 2011

Вот вам грязное, но работающее решение, работающее от Android 1.5 до 4.0. Код на C ++.

                              //decls of some partial classes from Skia library
class SkRefCnt{
public:
   virtual ~SkRefCnt(){}
private:
   mutable int fRefCnt;
};

//----------------------------

class SkPixelRef: public SkRefCnt{
public:
   virtual class Factory getFactory() const;
   virtual void flatten(class SkFlattenableWriteBuffer&) const;
protected:
   virtual void* onLockPixels(class SkColorTable**) = 0;
   virtual void onUnlockPixels() = 0;
public:
   void *GetPixels(){
      SkColorTable *ct;
      return onLockPixels(&ct);
   }
};

jobject java_bitmap;  //your Bitmap object
jclass java_bitmap_class = env.GetObjectClass(java_bitmap);
class SkBitmap;
SkBitmap *sk_bitmap = (SkBitmap*)env.CallIntMethod(java_bitmap, env.GetMethodID(java_bitmap_class, "ni", "()I"));
SkPixelRef *sk_pix_ref;
sk_pix_ref = (SkPixelRef*)((int*)sk_bitmap)[1];
// get pointer to Bitmap's pixel memory, and lenght of single line in bytes
int buffer_pitch = env.CallIntMethod(java_bitmap, env.GetMethodID(java_bitmap_class, "getRowBytes", "()I"));
void *buffer = sk_pix_ref->GetPixels();
0 голосов
/ 21 октября 2011

AFAIK, статический метод:

public static Bitmap createBitmap (int[] colors, int offset, int stride, int width, int height, Bitmap.Config config)

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

http://javaocr.svn.sourceforge.net/viewvc/javaocr/trunk/demos/recognizer/src/net/sf/javaocr/demos/android/recognizer/Recognizer.java?revision=239&view=markup

(строка 520)

...