【移動應(yīng)用開發(fā)技術(shù)】Android中Bitmap有什么用_第1頁
【移動應(yīng)用開發(fā)技術(shù)】Android中Bitmap有什么用_第2頁
【移動應(yīng)用開發(fā)技術(shù)】Android中Bitmap有什么用_第3頁
【移動應(yīng)用開發(fā)技術(shù)】Android中Bitmap有什么用_第4頁
【移動應(yīng)用開發(fā)技術(shù)】Android中Bitmap有什么用_第5頁
已閱讀5頁,還剩9頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

【移動應(yīng)用開發(fā)技術(shù)】Android中Bitmap有什么用

Bitmap(android.graphics.Bitmap)基于android-6.0.1_r80源代碼分析Bitmap對象創(chuàng)建//

/home/yuxiang/repo_aosp/android-6.0.1_r79/frameworks/base/core/jni/android/graphics/Bitmap.cpp

static

jobject

Bitmap_creator(JNIEnv*

env,

jobject,

jintArray

jColors,

jint

offset,

jint

stride,

jint

width,

jint

height,

jint

configHandle,

jboolean

isMutable)

{

SkColorType

colorType

=

GraphicsJNI::legacyBitmapConfigToColorType(configHandle);

if

(NULL

!=

jColors)

{

size_t

n

=

env->GetArrayLength(jColors);

if

(n

<

SkAbs32(stride)

*

(size_t)height)

{

doThrowAIOOBE(env);

return

NULL;

}

}

//

ARGB_4444

is

a

deprecated

format,

convert

automatically

to

8888

if

(colorType

==

kARGB_4444_SkColorType)

{

colorType

=

kN32_SkColorType;

}

SkBitmap

bitmap;

bitmap.setInfo(SkImageInfo::Make(width,

height,

colorType,

kPremul_SkAlphaType));

Bitmap*

nativeBitmap

=

GraphicsJNI::allocateJavaPixelRef(env,

&bitmap,

NULL);

if

(!nativeBitmap)

{

return

NULL;

}

if

(jColors

!=

NULL)

{

GraphicsJNI::SetPixels(env,

jColors,

offset,

stride,

0,

0,

width,

height,

bitmap);

}

return

GraphicsJNI::createBitmap(env,

nativeBitmap,

getPremulBitmapCreateFlags(isMutable));

}//

/home/yuxiang/repo_aosp/android-6.0.1_r79/external/skia/include/core/SkImageInfo.h

enum

SkColorType

{

kUnknown_SkColorType,

kAlpha_8_SkColorType,

kRGB_565_SkColorType,

kARGB_4444_SkColorType,

kRGBA_8888_SkColorType,

kBGRA_8888_SkColorType,

kIndex_8_SkColorType,

kGray_8_SkColorType,

kLastEnum_SkColorType

=

kGray_8_SkColorType,

#if

SK_PMCOLOR_BYTE_ORDER(B,G,R,A)

kN32_SkColorType

=

kBGRA_8888_SkColorType,

#elif

SK_PMCOLOR_BYTE_ORDER(R,G,B,A)

kN32_SkColorType

=

kRGBA_8888_SkColorType,

#else

#error

"SK_*32_SHFIT

values

must

correspond

to

BGRA

or

RGBA

byte

order"

#endif

};public:

SkImageInfo()

:

fWidth(0)

,

fHeight(0)

,

fColorType(kUnknown_SkColorType)

,

fAlphaType(kUnknown_SkAlphaType)

,

fProfileType(kLinear_SkColorProfileType)

{}

static

SkImageInfo

Make(int

width,

int

height,

SkColorType

ct,

SkAlphaType

at,

SkColorProfileType

pt

=

kLinear_SkColorProfileType)

{

return

SkImageInfo(width,

height,

ct,

at,

pt);

}int

register_android_graphics_Graphics(JNIEnv*

env)

{

jmethodID

m;

jclass

c;

...

gVMRuntime

=

env->NewGlobalRef(env->CallStaticObjectMethod(gVMRuntime_class,

m));

gVMRuntime_newNonMovableArray

=

env->GetMethodID(gVMRuntime_class,

"newNonMovableArray",

"(Ljava/lang/Class;I)Ljava/lang/Object;");

...

}

env->CallObjectMethod(gVMRuntime,

gVMRuntime_newNonMovableArray,

gByte_class,

size)

拿到虛擬機(jī)分配Heap對象,

env->CallLongMethod(gVMRuntime,

gVMRuntime_addressOf,

arrayObj)

拿到分配對象的地址,調(diào)用

native

層構(gòu)造函數(shù)

new

android::Bitmap(env,

arrayObj,

(void*)

addr,

info,

rowBytes,

ctable)

//

/home/yuxiang/repo_aosp/android-6.0.1_r79/frameworks/base/core/jni/android/graphics/Bitmap.cpp

Bitmap::Bitmap(JNIEnv*

env,

jbyteArray

storageObj,

void*

address,

const

SkImageInfo&

info,

size_t

rowBytes,

SkColorTable*

ctable)

:

mPixelStorageType(PixelStorageType::Java)

{

env->GetJavaVM(&mPixelStorage.java.jvm);

mPixelStorage.java.jweakRef

=

env->NewWeakGlobalRef(storageObj);

mPixelStorage.java.jstrongRef

=

nullptr;

mPixelRef.reset(new

WrappedPixelRef(this,

address,

info,

rowBytes,

ctable));

//

Note:

this

will

trigger

a

call

to

onStrongRefDestroyed(),

but

//

we

want

the

pixel

ref

to

have

a

ref

count

of

0

at

this

point

mPixelRef->unref();

}

void

Bitmap::getSkBitmap(SkBitmap*

outBitmap)

{

assertValid();

android::AutoMutex

_lock(mLock);

//

Safe

because

mPixelRef

is

a

WrappedPixelRef

type,

otherwise

rowBytes()

//

would

require

locking

the

pixels

first.

outBitmap->setInfo(mPixelRef->info(),

mPixelRef->rowBytes());

outBitmap->setPixelRef(refPixelRefLocked())->unref();

outBitmap->setHasHardwareMipMap(hasHardwareMipMap());

}

void

Bitmap::pinPixelsLocked()

{

switch

(mPixelStorageType)

{

case

PixelStorageType::Invalid:

LOG_ALWAYS_FATAL("Cannot

pin

invalid

pixels!");

break;

case

PixelStorageType::External:

case

PixelStorageType::Ashmem:

//

Nothing

to

do

break;

case

PixelStorageType::Java:

{

JNIEnv*

env

=

jniEnv();

if

(!mPixelStorage.java.jstrongRef)

{

mPixelStorage.java.jstrongRef

=

reinterpret_cast<jbyteArray>(

env->NewGlobalRef(mPixelStorage.java.jweakRef));

if

(!mPixelStorage.java.jstrongRef)

{

LOG_ALWAYS_FATAL("Failed

to

acquire

strong

reference

to

pixels");

}

}

break;

}

}

}

//

/home/yuxiang/repo_aosp/android-6.0.1_r79/frameworks/base/core/jni/android/graphics/Bitmap.h

std::unique_ptr<WrappedPixelRef>

mPixelRef;

PixelStorageType

mPixelStorageType;

union

{

struct

{

void*

address;

void*

context;

FreeFunc

freeFunc;

}

external;

struct

{

void*

address;

int

fd;

size_t

size;

}

ashmem;

struct

{

JavaVM*

jvm;

jweak

jweakRef;

jbyteArray

jstrongRef;

}

java;

}

mPixelStorage;//

/home/yuxiang/repo_aosp/android-6.0.1_r79/frameworks/base/core/jni/android/graphics/Bitmap.cpp

jobject

GraphicsJNI::createBitmap(JNIEnv*

env,

android::Bitmap*

bitmap,

int

bitmapCreateFlags,

jbyteArray

ninePatchChunk,

jobject

ninePatchInsets,

int

density)

{

bool

isMutable

=

bitmapCreateFlags

&

kBitmapCreateFlag_Mutable;

bool

isPremultiplied

=

bitmapCreateFlags

&

kBitmapCreateFlag_Premultiplied;

//

The

caller

needs

to

have

already

set

the

alpha

type

properly,

so

the

//

native

SkBitmap

stays

in

sync

with

the

Java

Bitmap.

assert_premultiplied(bitmap->info(),

isPremultiplied);

jobject

obj

=

env->NewObject(gBitmap_class,

gBitmap_constructorMethodID,

reinterpret_cast<jlong>(bitmap),

bitmap->javaByteArray(),

bitmap->width(),

bitmap->height(),

density,

isMutable,

isPremultiplied,

ninePatchChunk,

ninePatchInsets);

hasException(env);

//

For

the

side

effect

of

logging.

return

obj;

}JNI編程中明顯的內(nèi)存泄漏NativeCode本身的內(nèi)存泄漏Bitmap對象釋放//

/home/yuxiang/repo_aosp/android-6.0.1_r79/frameworks/base/core/jni/android/graphics/Bitmap.cpp

void

Bitmap::freePixels()

{

AutoMutex

_lock(mLock);

if

(mPinnedRefCount

==

0)

{

doFreePixels();

mPixelStorageType

=

PixelStorageType::Invalid;

}

}

void

Bitmap::doFreePixels()

{

switch

(mPixelStorageType)

{

case

PixelStorageType::Invalid:

//

already

free'd,

nothing

to

do

break;

case

PixelStorageType::External:

mPixelStorage.external.freeFunc(mPixelStorage.external.address,

mPixelStorage.external.context);

break;

case

PixelStorageType::Ashmem:

munmap(mPixelStorage.ashmem.address,

mPixelStorage.ashmem.size);

close(mPixelStorage.ashmem.fd);

break;

case

PixelStorageType::Java:

JNIEnv*

env

=

jniEnv();

LOG_ALWAYS_FATAL_IF(mPixelStorage.java.jstrongRef,

"Deleting

a

bitmap

wrapper

while

there

are

outstanding

strong

"

"references!

mPinnedRefCount

=

%d",

mPinnedRefCount);

env->DeleteWeakGlobalRef(mPixelStorage.java.jweakRef);

break;

}

if

(android::uirenderer::Caches::hasInstance())

{

android::uirenderer::Caches::getInstance().textureCache.releaseTexture(

mPixelRef->getStableID());

}

}//

/home/yuxiang/repo_aosp/android-6.0.1_r79/art/runtime/jni_internal.cc

static

void

DeleteWeakGlobalRef(JNIEnv*

env,

jweak

obj)

{

JavaVMExt*

vm

=

down_cast<JNIEnvExt*>(env)->vm;

Thread*

self

=

down_cast<JNIEnvExt*>(env)->self;

vm->DeleteWeakGlobalRef(self,

obj);

}

//

/home/yuxiang/repo_aosp/android-6.0.1_r79/art/runtime/java_vm_ext.cc

void

JavaVMExt::DeleteWeakGlobalRef(Thread*

self,

jweak

obj)

{

if

(obj

==

nullptr)

{

return;

}

MutexLock

mu(self,

weak_globals_lock_);

if

(!weak_globals_.Remove(IRT_FIRST_SEGMENT,

obj))

{

LOG(WARNING)

<<

"JNI

WARNING:

DeleteWeakGlobalRef("

<<

obj

<<

")

"

<<

"failed

to

find

entry";

}

}通過BitmapFactory創(chuàng)建Bitmap//

BitmapFactory.java

private

static

native

Bitmap

nativeDecodeStream(InputStream

is,

byte[]

storage,

Rect

padding,

Options

opts);

private

static

native

Bitmap

nativeDecodeFileDescriptor(FileDescriptor

fd,

Rect

padding,

Options

opts);

private

static

native

Bitmap

nativeDecodeAsset(long

nativeAsset,

Rect

padding,

Options

opts);

private

static

native

Bitmap

nativeDecodeByteArray(byte[]

data,

int

offset,

int

length,

Options

opts);

private

static

native

boolean

nativeIsSeekable(FileDescriptor

fd);//

BitmapFactory.cpp

static

jobject

nativeDecodeStream(JNIEnv*

env,

jobject

clazz,

jobject

is,

jbyteArray

storage,

jobject

padding,

jobject

options)

{

jobject

bitmap

=

NULL;

SkAutoTDelete<SkStream>

stream(CreateJavaInputStreamAdaptor(env,

is,

storage));

if

(stream.get())

{

SkAutoTDelete<SkStreamRewindable>

bufferedStream(

SkFrontBufferedStream::Create(stream.detach(),

BYTES_TO_BUFFER));

SkASSERT(bufferedStream.get()

!=

NULL);

bitmap

=

doDecode(env,

bufferedStream,

padding,

options);

}

return

bitmap;

}//

BitmapFactory.cpp

static

jobject

doDecode(JNIEnv*

env,

SkStreamRewindable*

stream,

jobject

padding,

jobject

options)

{

int

sampleSize

=

1;

SkImageDecoder::Mode

decodeMode

=

SkImageDecoder::kDecodePixels_Mode;

SkColorType

prefColorType

=

kN32_SkColorType;

bool

doDither

=

true;

bool

isMutable

=

false;

float

scale

=

1.0f;

bool

preferQualityOverSpeed

=

false;

bool

requireUnpremultiplied

=

false;

jobject

javaBitmap

=

NULL;

if

(options

!=

NULL)

{

sampleSize

=

env->GetIntField(options,

gOptions_sampleSizeFieldID);

if

(optionsJustBounds(env,

options))

{

decodeMode

=

SkImageDecoder::kDecodeBounds_Mode;

}

//

initialize

these,

in

case

we

fail

later

on

env->SetIntField(options,

gOptions_widthFieldID,

-1);

env->SetIntField(options,

gOptions_heightFieldID,

-1);

env->SetObjectField(options,

gOptions_mimeFieldID,

0);

jobject

jconfig

=

env->GetObjectField(options,

gOptions_configFieldID);

prefColorType

=

GraphicsJNI::getNativeBitmapColorType(env,

jconfig);

isMutable

=

env->GetBooleanField(options,

gOptions_mutableFieldID);

doDither

=

env->GetBooleanField(options,

gOptions_ditherFieldID);

preferQualityOverSpeed

=

env->GetBooleanField(options,

gOptions_preferQualityOverSpeedFieldID);

requireUnpremultiplied

=

!env->GetBooleanField(options,

gOptions_premultipliedFieldID);

javaBitmap

=

env->GetObjectField(options,

gOptions_bitmapFieldID);

if

(env->GetBooleanField(options,

gOptions_scaledFieldID))

{

const

int

density

=

env->GetIntField(options,

gOptions_densityFieldID);

const

int

targetDensity

=

env->GetIntField(options,

gOptions_targetDensityFieldID);

const

int

screenDensity

=

env->GetIntField(options,

gOptions_screenDensityFieldID);

if

(density

!=

0

&&

targetDensity

!=

0

&&

density

!=

screenDensity)

{

scale

=

(float)

targetDensity

/

density;

}

}

...

}//

BitmapFactory.cpp

static

jobject

doDecode(JNIEnv*

env,

SkStreamRewindable*

stream,

jobject

padding,

jobject

options)

{

...

SkImageDecoder*

decoder

=

SkImageDecoder::Factory(stream);

if

(decoder

==

NULL)

{

return

nullObjectReturn("SkImageDecoder::Factory

returned

null");

}

decoder->setSampleSize(sampleSize);

decoder->setDitherImage(doDither);

decoder->setPreferQualityOverSpeed(preferQualityOverSpeed);

decoder->setRequireUnpremultipliedColors(requireUnpremultiplied)

...

}

//

SkImageDecoder_FactoryDefault.cpp

SkImageDecoder*

SkImageDecoder::Factory(SkStreamRewindable*

stream)

{

return

image_decoder_from_stream(stream);

}

//

SkImageDecoder_FactoryRegistrar.cpp

SkImageDecoder*

image_decoder_from_stream(SkStreamRewindable*

stream)

{

SkImageDecoder*

codec

=

NULL;

const

SkImageDecoder_DecodeReg*

curr

=

SkImageDecoder_DecodeReg::Head();

while

(curr)

{

codec

=

curr->factory()(stream);

//

we

rewind

here,

because

we

promise

later

when

we

call

"decode",

that

//

the

stream

will

be

at

its

beginning.

bool

rewindSuceeded

=

stream->rewind();

//

our

image

decoder's

require

that

rewind

is

supported

so

we

fail

early

//

if

we

are

given

a

stream

that

does

not

support

rewinding.

if

(!rewindSuceeded)

{

SkDEBUGF(("Unable

to

rewind

the

image

stream."));

SkDELETE(codec);

return

NULL;

}

if

(codec)

{

return

codec;

}

curr

=

curr->next();

}

return

NULL;

}

//

SkImageDecoder.cpp

const

char*

SkImageDecoder::GetFormatName(Format

format)

{

switch

(format)

{

case

kUnknown_Format:

return

"Unknown

Format";

case

kBMP_Format:

return

"BMP";

case

kGIF_Format:

return

"GIF";

case

kICO_Format:

return

"ICO";

case

kPKM_Format:

return

"PKM";

case

kKTX_Format:

return

"KTX";

case

kASTC_Format:

return

"ASTC";

case

kJPEG_Format:

return

"JPEG";

case

kPNG_Format:

return

"PNG";

case

kWBMP_Format:

return

"WBMP";

case

kWEBP_Format:

return

"WEBP";

default:

SkDEBUGFAIL("Invalid

format

type!");

}

return

"Unknown

Format";

}//

BitmapFactory.cpp

static

jobject

doDecode(JNIEnv*

env,

SkStreamRewindable*

stream,

jobject

padding,

jobject

options)

{

...

SkBitmap

outputBitmap;

if

(willScale)

{

//

This

is

weird

so

let

me

explain:

we

could

use

the

scale

parameter

//

directly,

but

for

historical

reasons

this

is

how

the

corresponding

//

Dalvik

code

has

always

behaved.

We

simply

recreate

the

behavior

here.

//

The

result

is

slightly

dif

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論