




版權(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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 公益活動安全管理措施的總結(jié)計劃
- 財務(wù)管理中的預(yù)測與規(guī)劃計劃
- 土地確權(quán)協(xié)議書(2025年版)
- 校園環(huán)保與可持續(xù)發(fā)展活動計劃
- 三年級下冊數(shù)學(xué)教案-七 分?jǐn)?shù)的初步認(rèn)識(二)-蘇教版
- 2025年保健抗菌凈化劑合作協(xié)議書
- 不參與競標(biāo)回復(fù)函
- 房租催促通知函
- 群眾來信回復(fù)函范文
- 代理報檢委托書的委托人
- 人教版三年級下冊品社不一樣的你我他公開課獲獎?wù)n件百校聯(lián)賽一等獎?wù)n件
- 2024-2025學(xué)年北京市東城區(qū)五下數(shù)學(xué)期末檢測試題含答案
- 結(jié)構(gòu)化思維培訓(xùn)
- 2025年湖南安全技術(shù)職業(yè)學(xué)院單招職業(yè)技能測試題庫必考題
- 社會福利 課件全套 高和榮 第1-11章 緒論-社會福利的挑戰(zhàn)
- 食品采購員工工作計劃
- EPC工程項目建設(shè)管理機(jī)構(gòu)及權(quán)力職責(zé)
- 2024年林芝地區(qū)人民醫(yī)院高層次衛(wèi)技人才招聘筆試歷年參考題庫頻考點附帶答案
- 2025年全國國家版圖知識測試競賽題庫(附答案)
- 2025深圳勞動合同下載
- 《同濟(jì)堂會計信息披露違規(guī)案例研究》
評論
0/150
提交評論