Android 从源码分析Bitmap和BitmapFactory常用API

getAllocationByteCount()

获取用来存储bitmap所分配的内存大小。在bitmap的生命周期内此值不会改变。

/**

  • Returns the size of the allocated memory used to store this bitmap’s pixels.

  • This can be larger than the result of {@link #getByteCount()} if a bitmap is reused to

  • decode other bitmaps of smaller size, or by manual reconfiguration. See {@link

  • #reconfigure(int, int, Config)}, {@link #setWidth(int)}, {@link #setHeight(int)}, {@link

  • #setConfig(Bitmap.Config)}, and {@link BitmapFactory.Options#inBitmap

  • BitmapFactory.Options.inBitmap}. If a bitmap is not modified in this way, this value will be

  • the same as that returned by {@link #getByteCount()}.

  • This value will not change over the lifetime of a Bitmap.

  • @see #reconfigure(int, int, Config)

*/

public final int getAllocationByteCount() {

if (mBuffer == null) {

// native backed bitmaps don’t support reconfiguration,

// so alloc size is always content size

return getByteCount();

}

return mBuffer.length;

}

getConfig()

获取Config枚举:

  • ALPHA_8, 代表8位Alpha位图,每个像素占用1byte内存

  • RGB_565,代表8位RGB位图,每个像素占用2byte内存

  • ARGB_4444 (@deprecated),代表16位ARGB位图,每个像素占用2byte内存

  • ARGB_8888,代表32位ARGB位图,每个像素占用4byte内存

/**

  • If the bitmap’s internal config is in one of the public formats, return

  • that config, otherwise return null.

*/

public final Config getConfig() {

if (mRecycled) {

Log.w(TAG, “Called getConfig() on a recycle()'d bitmap! This is undefined behavior!”);

}

return Config.nativeToConfig(nativeConfig(mNativePtr));

}

hasAlpha()

检测bitmap是否支持像素级别透明。

/** Returns true if the bitmap’s config supports per-pixel alpha, and

  • if the pixels may contain non-opaque alpha values. For some configs,

  • this is always false (e.g. RGB_565), since they do not support per-pixel

  • alpha. However, for configs that do, the bitmap may be flagged to be

  • known that all of its pixels are opaque. In this case hasAlpha() will

  • also return false. If a config such as ARGB_8888 is not so flagged,

  • it will return true by default.

*/

public final boolean hasAlpha() {

if (mRecycled) {

Log.w(TAG, “Called hasAlpha() on a recycle()'d bitmap! This is undefined behavior!”);

}

return nativeHasAlpha(mNativePtr);

}

setHasAlpha(boolean hasAlpha)

设置bitmap是否支持像素级别透明

/**

  • Tell the bitmap if all of the pixels are known to be opaque (false)

  • or if some of the pixels may contain non-opaque alpha values (true).

  • Note, for some configs (e.g. RGB_565) this call is ignored, since it

  • does not support per-pixel alpha values.

  • This is meant as a drawing hint, as in some cases a bitmap that is known

  • to be opaque can take a faster drawing case than one that may have

  • non-opaque per-pixel alpha values.

*/

public void setHasAlpha(boolean hasAlpha) {

checkRecycled(“setHasAlpha called on a recycled bitmap”);

nativeSetHasAlpha(mNativePtr, hasAlpha, mRequestPremultiplied);

}

eraseColor(@ColorInt int c)

用颜色值填充bitmap的像素。

/**

  • Fills the bitmap’s pixels with the specified {@link Color}.

  • @throws IllegalStateException if the bitmap is not mutable.

*/

public void eraseColor(@ColorInt int c) {

checkRecycled(“Can’t erase a recycled bitmap”);

if (!isMutable()) {

throw new IllegalStateException(“cannot erase immutable bitmaps”);

}

nativeErase(mNativePtr, c);

}

getPixel(int x, int y)

获取指定位置像素的颜色值。

/**

  • Returns the {@link Color} at the specified location. Throws an exception

  • if x or y are out of bounds (negative or >= to the width or height

  • respectively). The returned color is a non-premultiplied ARGB value.

  • @param x The x coordinate (0…width-1) of the pixel to return

  • @param y The y coordinate (0…height-1) of the pixel to return

  • @return The argb {@link Color} at the specified coordinate

  • @throws IllegalArgumentException if x, y exceed the bitmap’s bounds

*/

@ColorInt

public int getPixel(int x, int y) {

checkRecycled(“Can’t call getPixel() on a recycled bitmap”);

checkPixelAccess(x, y);

return nativeGetPixel(mNativePtr, x, y);

}

setPixel(int x, int y, @ColorInt int color)

设置指定位置像素的颜色值。

/**

  • Write the specified {@link Color} into the bitmap (assuming it is

  • mutable) at the x,y coordinate. The color must be a

  • non-premultiplied ARGB value.

  • @param x The x coordinate of the pixel to replace (0…width-1)

  • @param y The y coordinate of the pixel to replace (0…height-1)

  • @param color The ARGB color to write into the bitmap

  • @throws IllegalStateException if the bitmap is not mutable

  • @throws IllegalArgumentException if x, y are outside of the bitmap’s

  •     bounds.
    

*/

public void setPixel(int x, int y, @ColorInt int color) {

checkRecycled(“Can’t call setPixel() on a recycled bitmap”);

if (!isMutable()) {

throw new IllegalStateException();

}

checkPixelAccess(x, y);

nativeSetPixel(mNativePtr, x, y, color);

}

writeToParcel(Parcel p, int flags)

打包bitmap

/**

  • Write the bitmap and its pixels to the parcel. The bitmap can be

  • rebuilt from the parcel by calling CREATOR.createFromParcel().

  • @param p Parcel object to write the bitmap data into

*/

public void writeToParcel(Parcel p, int flags) {

checkRecycled(“Can’t parcel a recycled bitmap”);

if (!nativeWriteToParcel(mNativePtr, mIsMutable, mDensity, p)) {

throw new RuntimeException(“native writeToParcel failed”);

}

}

extractAlpha()

获取原bitmap的alpha通道数据最为新的bitmap。

/**

  • Returns a new bitmap that captures the alpha values of the original.

  • This may be drawn with Canvas.drawBitmap(), where the color(s) will be

  • taken from the paint that is passed to the draw call.

  • @return new bitmap containing the alpha channel of the original bitmap.

*/

@CheckResult

public Bitmap extractAlpha() {

return extractAlpha(null, null);

}

和另外一个bitmap比较二者是否相同。

/**

  • Given another bitmap, return true if it has the same dimensions, config,

  • and pixel data as this bitmap. If any of those differ, return false.

  • If other is null, return false.

*/

public boolean sameAs(Bitmap other) {

checkRecycled(“Can’t call sameAs on a recycled bitmap!”);

if (this == other) return true;

if (other == null) return false;

if (other.isRecycled()) {

throw new IllegalArgumentException(“Can’t compare to a recycled bitmap!”);

}

return nativeSameAs(mNativePtr, other.mNativePtr);

}

prepareToDraw()

绘制准备:重建该bitmap相关联的缓存来绘制。在可清除的bitmap中,此方法会尝试确保像素已经被解码。

/**

  • Rebuilds any caches associated with the bitmap that are used for

  • drawing it. In the case of purgeable bitmaps, this call will attempt to

  • ensure that the pixels have been decoded.

  • If this is called on more than one bitmap in sequence, the priority is

  • given in LRU order (i.e. the last bitmap called will be given highest

  • priority).

  • For bitmaps with no associated caches, this call is effectively a no-op,

  • and therefore is harmless.

*/

public void prepareToDraw() {

checkRecycled(“Can’t prepareToDraw on a recycled bitmap!”);

// Kick off an update/upload of the bitmap outside of the normal

// draw path.

nativePrepareToDraw(mNativePtr);

}

CompressFormat

bitmap压缩格式:JPEG,PNG,WEBP(谷歌推出的图片格式,小体积高质量,豆瓣电影的海报使用的此格式)

/**

  • Specifies the known formats a bitmap can be compressed into

*/

public enum CompressFormat {

JPEG (0),

PNG (1),

WEBP (2);

CompressFormat(int nativeInt) {

this.nativeInt = nativeInt;

}

final int nativeInt;

}

compress(CompressFormat format, int quality, OutputStream stream)

压缩bitmap。

/**

  • Write a compressed version of the bitmap to the specified outputstream.

  • If this returns true, the bitmap can be reconstructed by passing a

  • corresponding inputstream to BitmapFactory.decodeStream(). Note: not

  • all Formats support all bitmap configs directly, so it is possible that

  • the returned bitmap from BitmapFactory could be in a different bitdepth,

  • and/or may have lost per-pixel alpha (e.g. JPEG only supports opaque

  • pixels).

  • @param format The format of the compressed image

  • @param quality Hint to the compressor, 0-100. 0 meaning compress for

  •             small size, 100 meaning compress for max quality. Some
    
  •             formats, like PNG which is lossless, will ignore the
    
  •             quality setting
    
  • @param stream The outputstream to write the compressed data.

  • @return true if successfully compressed to the specified stream.

*/

public boolean compress(CompressFormat format, int quality, OutputStream stream) {

checkRecycled(“Can’t compress a recycled bitmap”);

// do explicit check before calling the native method

if (stream == null) {

throw new NullPointerException();

}

if (quality < 0 || quality > 100) {

throw new IllegalArgumentException(“quality must be 0…100”);

}

Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, “Bitmap.compress”);

boolean result = nativeCompress(mNativePtr, format.nativeInt,

quality, stream, new byte[WORKING_COMPRESS_STORAGE]);

Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);

return result;

}


BitmapFactory


inMutable

配置bitmap是否可修改

/**

  • If set, decode methods will always return a mutable Bitmap instead of

  • an immutable one. This can be used for instance to programmatically apply

  • effects to a Bitmap loaded through BitmapFactory.

*/

@SuppressWarnings({“UnusedDeclaration”}) // used in native code

public boolean inMutable;

inJustDecodeBounds

如果设置为true,不获取图片,不分配内存,但会返回图片的高度宽度信息。

/**

  • If set to true, the decoder will return null (no bitmap), but

  • the out… fields will still be set, allowing the caller to query

  • the bitmap without having to allocate the memory for its pixels.

*/

public boolean inJustDecodeBounds;

inSampleSize

图片缩放倍数

/**

  • If set to a value > 1, requests the decoder to subsample the original

  • image, returning a smaller image to save memory. The sample size is

  • the number of pixels in either dimension that correspond to a single

  • pixel in the decoded bitmap. For example, inSampleSize == 4 returns

  • an image that is 1/4 the width/height of the original, and 1/16 the

  • number of pixels. Any value <= 1 is treated the same as 1. Note: the

  • decoder uses a final value based on powers of 2, any other value will

  • be rounded down to the nearest power of 2.

*/

public int inSampleSize;

inDither, @deprecated

抖动解码

/**

  • @deprecated As of {@link android.os.Build.VERSION_CODES#N}, this is

  • ignored.

  • In {@link android.os.Build.VERSION_CODES#M} and below, if dither is

  • true, the decoder will attempt to dither the decoded image.

*/

public boolean inDither;

inDensity

用于位图的像素压缩比。

/**

  • The pixel density to use for the bitmap. This will always result

  • in the returned bitmap having a density set for it (see

  • {@link Bitmap#setDensity(int) Bitmap.setDensity(int)}). In addition,

  • if {@link #inScaled} is set (which it is by default} and this

  • density does not match {@link #inTargetDensity}, then the bitmap

  • will be scaled to the target density before being returned.

  • If this is 0,

  • {@link BitmapFactory#decodeResource(Resources, int)},

  • {@link BitmapFactory#decodeResource(Resources, int, android.graphics.BitmapFactory.Options)},

  • and {@link BitmapFactory#decodeResourceStream}

  • will fill in the density associated with the resource. The other

  • functions will leave it as-is and no density will be applied.

  • @see #inTargetDensity

  • @see #inScreenDensity

  • @see #inScaled

  • @see Bitmap#setDensity(int)

  • @see android.util.DisplayMetrics#densityDpi

*/

public int inDensity;

inTargetDensity

用于目标位图的像素压缩比(要生成的位图)

/**

  • The pixel density of the destination this bitmap will be drawn to.

  • This is used in conjunction with {@link #inDensity} and

  • {@link #inScaled} to determine if and how to scale the bitmap before

  • returning it.

  • If this is 0,

  • {@link BitmapFactory#decodeResource(Resources, int)},

  • {@link BitmapFactory#decodeResource(Resources, int, android.graphics.BitmapFactory.Options)},

  • and {@link BitmapFactory#decodeResourceStream}

  • will fill in the density associated the Resources object’s

  • DisplayMetrics. The other

  • functions will leave it as-is and no scaling for density will be

  • performed.

  • @see #inDensity

  • @see #inScreenDensity

  • @see #inScaled

  • @see android.util.DisplayMetrics#densityDpi

*/

public int inTargetDensity;

inScreenDensity

当前屏幕的像素密度

/**

  • The pixel density of the actual screen that is being used. This is

  • purely for applications running in density compatibility code, where

  • {@link #inTargetDensity} is actually the density the application

  • sees rather than the real screen density.

  • By setting this, you

  • allow the loading code to avoid scaling a bitmap that is currently

  • in the screen density up/down to the compatibility density. Instead,

  • if {@link #inDensity} is the same as {@link #inScreenDensity}, the

  • bitmap will be left as-is. Anything using the resulting bitmap

  • must also used {@link Bitmap#getScaledWidth(int)

  • Bitmap.getScaledWidth} and {@link Bitmap#getScaledHeight

  • Bitmap.getScaledHeight} to account for any different between the

  • bitmap’s density and the target’s density.

  • This is never set automatically for the caller by

  • {@link BitmapFactory} itself. It must be explicitly set, since the

  • caller must deal with the resulting bitmap in a density-aware way.

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
img

写在最后

在技术领域内,没有任何一门课程可以让你学完后一劳永逸,再好的课程也只能是“师傅领进门,修行靠个人”。“学无止境”这句话,在任何技术领域,都不只是良好的习惯,更是程序员和工程师们不被时代淘汰、获得更好机会和发展的必要前提。

如果你觉得自己学习效率低,缺乏正确的指导,可以一起学习交流!

加入我们吧!群内有许多来自一线的技术大牛,也有在小厂或外包公司奋斗的码农,我们致力打造一个平等,高质量的Android交流圈子,不一定能短期就让每个人的技术突飞猛进,但从长远来说,眼光,格局,长远发展的方向才是最重要的。

35岁中年危机大多是因为被短期的利益牵着走,过早压榨掉了价值,如果能一开始就树立一个正确的长远的职业规划。35岁后的你只会比周围的人更值钱。

本文已被CODING开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》收录

一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算

的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!**

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
[外链图片转存中…(img-VIdKZDzY-1712099457074)]

写在最后

在技术领域内,没有任何一门课程可以让你学完后一劳永逸,再好的课程也只能是“师傅领进门,修行靠个人”。“学无止境”这句话,在任何技术领域,都不只是良好的习惯,更是程序员和工程师们不被时代淘汰、获得更好机会和发展的必要前提。

如果你觉得自己学习效率低,缺乏正确的指导,可以一起学习交流!

加入我们吧!群内有许多来自一线的技术大牛,也有在小厂或外包公司奋斗的码农,我们致力打造一个平等,高质量的Android交流圈子,不一定能短期就让每个人的技术突飞猛进,但从长远来说,眼光,格局,长远发展的方向才是最重要的。

35岁中年危机大多是因为被短期的利益牵着走,过早压榨掉了价值,如果能一开始就树立一个正确的长远的职业规划。35岁后的你只会比周围的人更值钱。

本文已被CODING开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》收录

一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值