Bitmap.cpp revision ec5039b3720ee9b92fb2a2c6dd9f468d2dcd7172
1#include "SkBitmap.h" 2#include "SkPixelRef.h" 3#include "SkImageEncoder.h" 4#include "SkColorPriv.h" 5#include "GraphicsJNI.h" 6#include "SkDither.h" 7#include "SkUnPreMultiply.h" 8 9#include <binder/Parcel.h> 10#include "android_util_Binder.h" 11#include "android_nio_utils.h" 12#include "CreateJavaOutputStreamAdaptor.h" 13 14#include <jni.h> 15 16#include <Caches.h> 17 18#if 0 19 #define TRACE_BITMAP(code) code 20#else 21 #define TRACE_BITMAP(code) 22#endif 23 24/////////////////////////////////////////////////////////////////////////////// 25// Conversions to/from SkColor, for get/setPixels, and the create method, which 26// is basically like setPixels 27 28typedef void (*FromColorProc)(void* dst, const SkColor src[], int width, 29 int x, int y); 30 31static void FromColor_D32(void* dst, const SkColor src[], int width, 32 int, int) { 33 SkPMColor* d = (SkPMColor*)dst; 34 35 for (int i = 0; i < width; i++) { 36 *d++ = SkPreMultiplyColor(*src++); 37 } 38} 39 40static void FromColor_D565(void* dst, const SkColor src[], int width, 41 int x, int y) { 42 uint16_t* d = (uint16_t*)dst; 43 44 DITHER_565_SCAN(y); 45 for (int stop = x + width; x < stop; x++) { 46 SkColor c = *src++; 47 *d++ = SkDitherRGBTo565(SkColorGetR(c), SkColorGetG(c), SkColorGetB(c), 48 DITHER_VALUE(x)); 49 } 50} 51 52static void FromColor_D4444(void* dst, const SkColor src[], int width, 53 int x, int y) { 54 SkPMColor16* d = (SkPMColor16*)dst; 55 56 DITHER_4444_SCAN(y); 57 for (int stop = x + width; x < stop; x++) { 58 SkPMColor c = SkPreMultiplyColor(*src++); 59 *d++ = SkDitherARGB32To4444(c, DITHER_VALUE(x)); 60// *d++ = SkPixel32ToPixel4444(c); 61 } 62} 63 64// can return NULL 65static FromColorProc ChooseFromColorProc(SkBitmap::Config config) { 66 switch (config) { 67 case SkBitmap::kARGB_8888_Config: 68 return FromColor_D32; 69 case SkBitmap::kARGB_4444_Config: 70 return FromColor_D4444; 71 case SkBitmap::kRGB_565_Config: 72 return FromColor_D565; 73 default: 74 break; 75 } 76 return NULL; 77} 78 79bool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors, 80 int srcOffset, int srcStride, 81 int x, int y, int width, int height, 82 const SkBitmap& dstBitmap) { 83 SkAutoLockPixels alp(dstBitmap); 84 void* dst = dstBitmap.getPixels(); 85 FromColorProc proc = ChooseFromColorProc(dstBitmap.config()); 86 87 if (NULL == dst || NULL == proc) { 88 return false; 89 } 90 91 const jint* array = env->GetIntArrayElements(srcColors, NULL); 92 const SkColor* src = (const SkColor*)array + srcOffset; 93 94 // reset to to actual choice from caller 95 dst = dstBitmap.getAddr(x, y); 96 // now copy/convert each scanline 97 for (int y = 0; y < height; y++) { 98 proc(dst, src, width, x, y); 99 src += srcStride; 100 dst = (char*)dst + dstBitmap.rowBytes(); 101 } 102 103 env->ReleaseIntArrayElements(srcColors, const_cast<jint*>(array), 104 JNI_ABORT); 105 return true; 106} 107 108//////////////////// ToColor procs 109 110typedef void (*ToColorProc)(SkColor dst[], const void* src, int width, 111 SkColorTable*); 112 113static void ToColor_S32_Alpha(SkColor dst[], const void* src, int width, 114 SkColorTable*) { 115 SkASSERT(width > 0); 116 const SkPMColor* s = (const SkPMColor*)src; 117 do { 118 *dst++ = SkUnPreMultiply::PMColorToColor(*s++); 119 } while (--width != 0); 120} 121 122static void ToColor_S32_Opaque(SkColor dst[], const void* src, int width, 123 SkColorTable*) { 124 SkASSERT(width > 0); 125 const SkPMColor* s = (const SkPMColor*)src; 126 do { 127 SkPMColor c = *s++; 128 *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c), 129 SkGetPackedB32(c)); 130 } while (--width != 0); 131} 132 133static void ToColor_S4444_Alpha(SkColor dst[], const void* src, int width, 134 SkColorTable*) { 135 SkASSERT(width > 0); 136 const SkPMColor16* s = (const SkPMColor16*)src; 137 do { 138 *dst++ = SkUnPreMultiply::PMColorToColor(SkPixel4444ToPixel32(*s++)); 139 } while (--width != 0); 140} 141 142static void ToColor_S4444_Opaque(SkColor dst[], const void* src, int width, 143 SkColorTable*) { 144 SkASSERT(width > 0); 145 const SkPMColor* s = (const SkPMColor*)src; 146 do { 147 SkPMColor c = SkPixel4444ToPixel32(*s++); 148 *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c), 149 SkGetPackedB32(c)); 150 } while (--width != 0); 151} 152 153static void ToColor_S565(SkColor dst[], const void* src, int width, 154 SkColorTable*) { 155 SkASSERT(width > 0); 156 const uint16_t* s = (const uint16_t*)src; 157 do { 158 uint16_t c = *s++; 159 *dst++ = SkColorSetRGB(SkPacked16ToR32(c), SkPacked16ToG32(c), 160 SkPacked16ToB32(c)); 161 } while (--width != 0); 162} 163 164static void ToColor_SI8_Alpha(SkColor dst[], const void* src, int width, 165 SkColorTable* ctable) { 166 SkASSERT(width > 0); 167 const uint8_t* s = (const uint8_t*)src; 168 const SkPMColor* colors = ctable->lockColors(); 169 do { 170 *dst++ = SkUnPreMultiply::PMColorToColor(colors[*s++]); 171 } while (--width != 0); 172 ctable->unlockColors(false); 173} 174 175static void ToColor_SI8_Opaque(SkColor dst[], const void* src, int width, 176 SkColorTable* ctable) { 177 SkASSERT(width > 0); 178 const uint8_t* s = (const uint8_t*)src; 179 const SkPMColor* colors = ctable->lockColors(); 180 do { 181 SkPMColor c = colors[*s++]; 182 *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c), 183 SkGetPackedB32(c)); 184 } while (--width != 0); 185 ctable->unlockColors(false); 186} 187 188// can return NULL 189static ToColorProc ChooseToColorProc(const SkBitmap& src) { 190 switch (src.config()) { 191 case SkBitmap::kARGB_8888_Config: 192 return src.isOpaque() ? ToColor_S32_Opaque : ToColor_S32_Alpha; 193 case SkBitmap::kARGB_4444_Config: 194 return src.isOpaque() ? ToColor_S4444_Opaque : ToColor_S4444_Alpha; 195 case SkBitmap::kRGB_565_Config: 196 return ToColor_S565; 197 case SkBitmap::kIndex8_Config: 198 if (src.getColorTable() == NULL) { 199 return NULL; 200 } 201 return src.isOpaque() ? ToColor_SI8_Opaque : ToColor_SI8_Alpha; 202 default: 203 break; 204 } 205 return NULL; 206} 207 208/////////////////////////////////////////////////////////////////////////////// 209/////////////////////////////////////////////////////////////////////////////// 210 211static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors, 212 int offset, int stride, int width, int height, 213 SkBitmap::Config config, jboolean isMutable) { 214 if (NULL != jColors) { 215 size_t n = env->GetArrayLength(jColors); 216 if (n < SkAbs32(stride) * (size_t)height) { 217 doThrowAIOOBE(env); 218 return NULL; 219 } 220 } 221 222 SkBitmap bitmap; 223 224 bitmap.setConfig(config, width, height); 225 226 jbyteArray buff = GraphicsJNI::allocateJavaPixelRef(env, &bitmap, NULL); 227 if (NULL == buff) { 228 return NULL; 229 } 230 231 if (jColors != NULL) { 232 GraphicsJNI::SetPixels(env, jColors, offset, stride, 233 0, 0, width, height, bitmap); 234 } 235 236 return GraphicsJNI::createBitmap(env, new SkBitmap(bitmap), buff, isMutable, NULL); 237} 238 239static jobject Bitmap_copy(JNIEnv* env, jobject, const SkBitmap* src, 240 SkBitmap::Config dstConfig, jboolean isMutable) { 241 SkBitmap result; 242 JavaPixelAllocator allocator(env); 243 244 if (!src->copyTo(&result, dstConfig, &allocator)) { 245 return NULL; 246 } 247 248 return GraphicsJNI::createBitmap(env, new SkBitmap(result), allocator.getStorageObj(), isMutable, NULL); 249} 250 251static void Bitmap_destructor(JNIEnv* env, jobject, SkBitmap* bitmap) { 252#ifdef USE_OPENGL_RENDERER 253 if (android::uirenderer::Caches::hasInstance()) { 254 android::uirenderer::Caches::getInstance().resourceCache.destructor(bitmap); 255 return; 256 } 257#endif // USE_OPENGL_RENDERER 258 delete bitmap; 259} 260 261static void Bitmap_recycle(JNIEnv* env, jobject, SkBitmap* bitmap) { 262#ifdef USE_OPENGL_RENDERER 263 if (android::uirenderer::Caches::hasInstance()) { 264 android::uirenderer::Caches::getInstance().resourceCache.recycle(bitmap); 265 return; 266 } 267#endif // USE_OPENGL_RENDERER 268 bitmap->setPixels(NULL, NULL); 269} 270 271// These must match the int values in Bitmap.java 272enum JavaEncodeFormat { 273 kJPEG_JavaEncodeFormat = 0, 274 kPNG_JavaEncodeFormat = 1, 275 kWEBP_JavaEncodeFormat = 2 276}; 277 278static bool Bitmap_compress(JNIEnv* env, jobject clazz, SkBitmap* bitmap, 279 int format, int quality, 280 jobject jstream, jbyteArray jstorage) { 281 SkImageEncoder::Type fm; 282 283 switch (format) { 284 case kJPEG_JavaEncodeFormat: 285 fm = SkImageEncoder::kJPEG_Type; 286 break; 287 case kPNG_JavaEncodeFormat: 288 fm = SkImageEncoder::kPNG_Type; 289 break; 290 case kWEBP_JavaEncodeFormat: 291 fm = SkImageEncoder::kWEBP_Type; 292 break; 293 default: 294 return false; 295 } 296 297 bool success = false; 298 SkWStream* strm = CreateJavaOutputStreamAdaptor(env, jstream, jstorage); 299 if (NULL != strm) { 300 SkImageEncoder* encoder = SkImageEncoder::Create(fm); 301 if (NULL != encoder) { 302 success = encoder->encodeStream(strm, *bitmap, quality); 303 delete encoder; 304 } 305 delete strm; 306 } 307 return success; 308} 309 310static void Bitmap_erase(JNIEnv* env, jobject, SkBitmap* bitmap, jint color) { 311 bitmap->eraseColor(color); 312} 313 314static int Bitmap_width(JNIEnv* env, jobject, SkBitmap* bitmap) { 315 return bitmap->width(); 316} 317 318static int Bitmap_height(JNIEnv* env, jobject, SkBitmap* bitmap) { 319 return bitmap->height(); 320} 321 322static int Bitmap_rowBytes(JNIEnv* env, jobject, SkBitmap* bitmap) { 323 return bitmap->rowBytes(); 324} 325 326static int Bitmap_config(JNIEnv* env, jobject, SkBitmap* bitmap) { 327 return bitmap->config(); 328} 329 330static int Bitmap_getGenerationId(JNIEnv* env, jobject, SkBitmap* bitmap) { 331 return bitmap->getGenerationID(); 332} 333 334static jboolean Bitmap_hasAlpha(JNIEnv* env, jobject, SkBitmap* bitmap) { 335 return !bitmap->isOpaque(); 336} 337 338static void Bitmap_setHasAlpha(JNIEnv* env, jobject, SkBitmap* bitmap, 339 jboolean hasAlpha) { 340 bitmap->setIsOpaque(!hasAlpha); 341} 342 343/////////////////////////////////////////////////////////////////////////////// 344 345static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) { 346 if (parcel == NULL) { 347 SkDebugf("-------- unparcel parcel is NULL\n"); 348 return NULL; 349 } 350 351 android::Parcel* p = android::parcelForJavaObject(env, parcel); 352 353 const bool isMutable = p->readInt32() != 0; 354 const SkBitmap::Config config = (SkBitmap::Config)p->readInt32(); 355 const int width = p->readInt32(); 356 const int height = p->readInt32(); 357 const int rowBytes = p->readInt32(); 358 const int density = p->readInt32(); 359 360 if (SkBitmap::kARGB_8888_Config != config && 361 SkBitmap::kRGB_565_Config != config && 362 SkBitmap::kARGB_4444_Config != config && 363 SkBitmap::kIndex8_Config != config && 364 SkBitmap::kA8_Config != config) { 365 SkDebugf("Bitmap_createFromParcel unknown config: %d\n", config); 366 return NULL; 367 } 368 369 SkBitmap* bitmap = new SkBitmap; 370 371 bitmap->setConfig(config, width, height, rowBytes); 372 373 SkColorTable* ctable = NULL; 374 if (config == SkBitmap::kIndex8_Config) { 375 int count = p->readInt32(); 376 if (count > 0) { 377 size_t size = count * sizeof(SkPMColor); 378 const SkPMColor* src = (const SkPMColor*)p->readInplace(size); 379 ctable = new SkColorTable(src, count); 380 } 381 } 382 383 jbyteArray buffer = GraphicsJNI::allocateJavaPixelRef(env, bitmap, ctable); 384 if (NULL == buffer) { 385 SkSafeUnref(ctable); 386 delete bitmap; 387 return NULL; 388 } 389 390 SkSafeUnref(ctable); 391 392 size_t size = bitmap->getSize(); 393 bitmap->lockPixels(); 394 memcpy(bitmap->getPixels(), p->readInplace(size), size); 395 bitmap->unlockPixels(); 396 397 return GraphicsJNI::createBitmap(env, bitmap, buffer, isMutable, NULL, density); 398} 399 400static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject, 401 const SkBitmap* bitmap, 402 jboolean isMutable, jint density, 403 jobject parcel) { 404 if (parcel == NULL) { 405 SkDebugf("------- writeToParcel null parcel\n"); 406 return false; 407 } 408 409 android::Parcel* p = android::parcelForJavaObject(env, parcel); 410 411 p->writeInt32(isMutable); 412 p->writeInt32(bitmap->config()); 413 p->writeInt32(bitmap->width()); 414 p->writeInt32(bitmap->height()); 415 p->writeInt32(bitmap->rowBytes()); 416 p->writeInt32(density); 417 418 if (bitmap->getConfig() == SkBitmap::kIndex8_Config) { 419 SkColorTable* ctable = bitmap->getColorTable(); 420 if (ctable != NULL) { 421 int count = ctable->count(); 422 p->writeInt32(count); 423 memcpy(p->writeInplace(count * sizeof(SkPMColor)), 424 ctable->lockColors(), count * sizeof(SkPMColor)); 425 ctable->unlockColors(false); 426 } else { 427 p->writeInt32(0); // indicate no ctable 428 } 429 } 430 431 size_t size = bitmap->getSize(); 432 bitmap->lockPixels(); 433 void* pDst = p->writeInplace(size); 434 435 const void* pSrc = bitmap->getPixels(); 436 437 if (pSrc == NULL) { 438 memset(pDst, 0, size); 439 } else { 440 memcpy(pDst, pSrc, size); 441 } 442 bitmap->unlockPixels(); 443 return true; 444} 445 446static jobject Bitmap_extractAlpha(JNIEnv* env, jobject clazz, 447 const SkBitmap* src, const SkPaint* paint, 448 jintArray offsetXY) { 449 SkIPoint offset; 450 SkBitmap* dst = new SkBitmap; 451 JavaPixelAllocator allocator(env); 452 453 src->extractAlpha(dst, paint, &allocator, &offset); 454 // If Skia can't allocate pixels for destination bitmap, it resets 455 // it, that is set its pixels buffer to NULL, and zero width and height. 456 if (dst->getPixels() == NULL && src->getPixels() != NULL) { 457 delete dst; 458 doThrowOOME(env, "failed to allocate pixels for alpha"); 459 return NULL; 460 } 461 if (offsetXY != 0 && env->GetArrayLength(offsetXY) >= 2) { 462 int* array = env->GetIntArrayElements(offsetXY, NULL); 463 array[0] = offset.fX; 464 array[1] = offset.fY; 465 env->ReleaseIntArrayElements(offsetXY, array, 0); 466 } 467 468 return GraphicsJNI::createBitmap(env, dst, allocator.getStorageObj(), true, NULL); 469} 470 471/////////////////////////////////////////////////////////////////////////////// 472 473static int Bitmap_getPixel(JNIEnv* env, jobject, const SkBitmap* bitmap, 474 int x, int y) { 475 SkAutoLockPixels alp(*bitmap); 476 477 ToColorProc proc = ChooseToColorProc(*bitmap); 478 if (NULL == proc) { 479 return 0; 480 } 481 const void* src = bitmap->getAddr(x, y); 482 if (NULL == src) { 483 return 0; 484 } 485 486 SkColor dst[1]; 487 proc(dst, src, 1, bitmap->getColorTable()); 488 return dst[0]; 489} 490 491static void Bitmap_getPixels(JNIEnv* env, jobject, const SkBitmap* bitmap, 492 jintArray pixelArray, int offset, int stride, 493 int x, int y, int width, int height) { 494 SkAutoLockPixels alp(*bitmap); 495 496 ToColorProc proc = ChooseToColorProc(*bitmap); 497 if (NULL == proc) { 498 return; 499 } 500 const void* src = bitmap->getAddr(x, y); 501 if (NULL == src) { 502 return; 503 } 504 505 SkColorTable* ctable = bitmap->getColorTable(); 506 jint* dst = env->GetIntArrayElements(pixelArray, NULL); 507 SkColor* d = (SkColor*)dst + offset; 508 while (--height >= 0) { 509 proc(d, src, width, ctable); 510 d += stride; 511 src = (void*)((const char*)src + bitmap->rowBytes()); 512 } 513 env->ReleaseIntArrayElements(pixelArray, dst, 0); 514} 515 516/////////////////////////////////////////////////////////////////////////////// 517 518static void Bitmap_setPixel(JNIEnv* env, jobject, const SkBitmap* bitmap, 519 int x, int y, SkColor color) { 520 SkAutoLockPixels alp(*bitmap); 521 if (NULL == bitmap->getPixels()) { 522 return; 523 } 524 525 FromColorProc proc = ChooseFromColorProc(bitmap->config()); 526 if (NULL == proc) { 527 return; 528 } 529 530 proc(bitmap->getAddr(x, y), &color, 1, x, y); 531} 532 533static void Bitmap_setPixels(JNIEnv* env, jobject, const SkBitmap* bitmap, 534 jintArray pixelArray, int offset, int stride, 535 int x, int y, int width, int height) { 536 GraphicsJNI::SetPixels(env, pixelArray, offset, stride, 537 x, y, width, height, *bitmap); 538} 539 540static void Bitmap_copyPixelsToBuffer(JNIEnv* env, jobject, 541 const SkBitmap* bitmap, jobject jbuffer) { 542 SkAutoLockPixels alp(*bitmap); 543 const void* src = bitmap->getPixels(); 544 545 if (NULL != src) { 546 android::AutoBufferPointer abp(env, jbuffer, JNI_TRUE); 547 548 // the java side has already checked that buffer is large enough 549 memcpy(abp.pointer(), src, bitmap->getSize()); 550 } 551} 552 553static void Bitmap_copyPixelsFromBuffer(JNIEnv* env, jobject, 554 const SkBitmap* bitmap, jobject jbuffer) { 555 SkAutoLockPixels alp(*bitmap); 556 void* dst = bitmap->getPixels(); 557 558 if (NULL != dst) { 559 android::AutoBufferPointer abp(env, jbuffer, JNI_FALSE); 560 // the java side has already checked that buffer is large enough 561 memcpy(dst, abp.pointer(), bitmap->getSize()); 562 } 563} 564 565static bool Bitmap_sameAs(JNIEnv* env, jobject, const SkBitmap* bm0, 566 const SkBitmap* bm1) { 567 if (bm0->width() != bm1->width() || 568 bm0->height() != bm1->height() || 569 bm0->config() != bm1->config()) { 570 return false; 571 } 572 573 SkAutoLockPixels alp0(*bm0); 574 SkAutoLockPixels alp1(*bm1); 575 576 // if we can't load the pixels, return false 577 if (NULL == bm0->getPixels() || NULL == bm1->getPixels()) { 578 return false; 579 } 580 581 if (bm0->config() == SkBitmap::kIndex8_Config) { 582 SkColorTable* ct0 = bm0->getColorTable(); 583 SkColorTable* ct1 = bm1->getColorTable(); 584 if (NULL == ct0 || NULL == ct1) { 585 return false; 586 } 587 if (ct0->count() != ct1->count()) { 588 return false; 589 } 590 591 SkAutoLockColors alc0(ct0); 592 SkAutoLockColors alc1(ct1); 593 const size_t size = ct0->count() * sizeof(SkPMColor); 594 if (memcmp(alc0.colors(), alc1.colors(), size) != 0) { 595 return false; 596 } 597 } 598 599 // now compare each scanline. We can't do the entire buffer at once, 600 // since we don't care about the pixel values that might extend beyond 601 // the width (since the scanline might be larger than the logical width) 602 const int h = bm0->height(); 603 const size_t size = bm0->width() * bm0->bytesPerPixel(); 604 for (int y = 0; y < h; y++) { 605 if (memcmp(bm0->getAddr(0, y), bm1->getAddr(0, y), size) != 0) { 606 return false; 607 } 608 } 609 return true; 610} 611 612static void Bitmap_prepareToDraw(JNIEnv* env, jobject, SkBitmap* bitmap) { 613 bitmap->lockPixels(); 614 bitmap->unlockPixels(); 615} 616 617/////////////////////////////////////////////////////////////////////////////// 618 619#include <android_runtime/AndroidRuntime.h> 620 621static JNINativeMethod gBitmapMethods[] = { 622 { "nativeCreate", "([IIIIIIZ)Landroid/graphics/Bitmap;", 623 (void*)Bitmap_creator }, 624 { "nativeCopy", "(IIZ)Landroid/graphics/Bitmap;", 625 (void*)Bitmap_copy }, 626 { "nativeDestructor", "(I)V", (void*)Bitmap_destructor }, 627 { "nativeRecycle", "(I)V", (void*)Bitmap_recycle }, 628 { "nativeCompress", "(IIILjava/io/OutputStream;[B)Z", 629 (void*)Bitmap_compress }, 630 { "nativeErase", "(II)V", (void*)Bitmap_erase }, 631 { "nativeWidth", "(I)I", (void*)Bitmap_width }, 632 { "nativeHeight", "(I)I", (void*)Bitmap_height }, 633 { "nativeRowBytes", "(I)I", (void*)Bitmap_rowBytes }, 634 { "nativeConfig", "(I)I", (void*)Bitmap_config }, 635 { "nativeHasAlpha", "(I)Z", (void*)Bitmap_hasAlpha }, 636 { "nativeSetHasAlpha", "(IZ)V", (void*)Bitmap_setHasAlpha }, 637 { "nativeCreateFromParcel", 638 "(Landroid/os/Parcel;)Landroid/graphics/Bitmap;", 639 (void*)Bitmap_createFromParcel }, 640 { "nativeWriteToParcel", "(IZILandroid/os/Parcel;)Z", 641 (void*)Bitmap_writeToParcel }, 642 { "nativeExtractAlpha", "(II[I)Landroid/graphics/Bitmap;", 643 (void*)Bitmap_extractAlpha }, 644 { "nativeGenerationId", "(I)I", (void*)Bitmap_getGenerationId }, 645 { "nativeGetPixel", "(III)I", (void*)Bitmap_getPixel }, 646 { "nativeGetPixels", "(I[IIIIIII)V", (void*)Bitmap_getPixels }, 647 { "nativeSetPixel", "(IIII)V", (void*)Bitmap_setPixel }, 648 { "nativeSetPixels", "(I[IIIIIII)V", (void*)Bitmap_setPixels }, 649 { "nativeCopyPixelsToBuffer", "(ILjava/nio/Buffer;)V", 650 (void*)Bitmap_copyPixelsToBuffer }, 651 { "nativeCopyPixelsFromBuffer", "(ILjava/nio/Buffer;)V", 652 (void*)Bitmap_copyPixelsFromBuffer }, 653 { "nativeSameAs", "(II)Z", (void*)Bitmap_sameAs }, 654 { "nativePrepareToDraw", "(I)V", (void*)Bitmap_prepareToDraw }, 655}; 656 657#define kClassPathName "android/graphics/Bitmap" 658 659int register_android_graphics_Bitmap(JNIEnv* env); 660int register_android_graphics_Bitmap(JNIEnv* env) 661{ 662 return android::AndroidRuntime::registerNativeMethods(env, kClassPathName, 663 gBitmapMethods, SK_ARRAY_COUNT(gBitmapMethods)); 664} 665