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

}

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.

  • @see #inDensity

  • @see #inTargetDensity

  • @see #inScaled

  • @see android.util.DisplayMetrics#densityDpi

*/

public int inScreenDensity;

inScaled

设置为true时进行图片压缩,从inDensity到inTargetDensity

/**

  • When this flag is set, if {@link #inDensity} and

  • {@link #inTargetDensity} are not 0, the

  • bitmap will be scaled to match {@link #inTargetDensity} when loaded,

  • rather than relying on the graphics system scaling it each time it

  • is drawn to a Canvas.

  • BitmapRegionDecoder ignores this flag, and will not scale output

  • based on density. (though {@link #inSampleSize} is supported)

  • This flag is turned on by default and should be turned off if you need

  • a non-scaled version of the bitmap. Nine-patch bitmaps ignore this

  • flag and are always scaled.

  • If {@link #inPremultiplied} is set to false, and the image has alpha,

  • setting this flag to true may result in incorrect colors.

*/

public boolean inScaled;

inPurgeable

当存储Pixel的内存空间在系统内存不足时是否可以被回收

/**

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

  • ignored.

  • In {@link android.os.Build.VERSION_CODES#KITKAT} and below, if this

  • is set to true, then the resulting bitmap will allocate its

  • pixels such that they can be purged if the system needs to reclaim

  • memory. In that instance, when the pixels need to be accessed again

  • (e.g. the bitmap is drawn, getPixels() is called), they will be

  • automatically re-decoded.

  • For the re-decode to happen, the bitmap must have access to the

  • encoded data, either by sharing a reference to the input

  • or by making a copy of it. This distinction is controlled by

  • inInputShareable. If this is true, then the bitmap may keep a shallow

  • reference to the input. If this is false, then the bitmap will

  • explicitly make a copy of the input data, and keep that. Even if

  • sharing is allowed, the implementation may still decide to make a

  • deep copy of the input data.

  • While inPurgeable can help avoid big Dalvik heap allocations (from

  • API level 11 onward), it sacrifices performance predictability since any

  • image that the view system tries to draw may incur a decode delay which

  • can lead to dropped frames. Therefore, most apps should avoid using

  • inPurgeable to allow for a fast and fluid UI. To minimize Dalvik heap

  • allocations use the {@link #inBitmap} flag instead.

  • Note: This flag is ignored when used

  • with {@link #decodeResource(Resources, int,

  • android.graphics.BitmapFactory.Options)} or {@link #decodeFile(String,

  • android.graphics.BitmapFactory.Options)}.

*/

@Deprecated

public boolean inPurgeable;

inInputShareable

inPurgeable为true情况下才生效,是否可以共享一个InputStream

/**

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

  • ignored.

  • In {@link android.os.Build.VERSION_CODES#KITKAT} and below, this

  • field works in conjuction with inPurgeable. If inPurgeable is false,

  • then this field is ignored. If inPurgeable is true, then this field

  • determines whether the bitmap can share a reference to the input

  • data (inputstream, array, etc.) or if it must make a deep copy.

*/

@Deprecated

public boolean inInputShareable;

inPreferQualityOverSpeed

为true则优先保证Bitmap质量其次是解码速度。

/**

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

  • ignored. The output will always be high quality.

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

  • inPreferQualityOverSpeed is set to true, the decoder will try to

  • decode the reconstructed image to a higher quality even at the

  • expense of the decoding speed. Currently the field only affects JPEG

  • decode, in the case of which a more accurate, but slightly slower,

  • IDCT method will be used instead.

*/

public boolean inPreferQualityOverSpeed;

decodeFile(String pathName, Options opts)

从文件读取图片

/**

  • Decode a file path into a bitmap. If the specified file name is null,

  • or cannot be decoded into a bitmap, the function returns null.

  • @param pathName complete path name for the file to be decoded.

  • @param opts null-ok; Options that control downsampling and whether the

  •         image should be completely decoded, or just is size returned.
    
  • @return The decoded bitmap, or null if the image data could not be

  •     decoded, or, if opts is non-null, if opts requested only the
    
  •     size be returned (in opts.outWidth and opts.outHeight)
    

*/

public static Bitmap decodeFile(String pathName, Options opts) {

Bitmap bm = null;

InputStream stream = null;

try {

stream = new FileInputStream(pathName);

bm = decodeStream(stream, null, opts);

} catch (Exception e) {

/* do nothing.

If the exception happened on open, bm will be null.

*/

Log.e(“BitmapFactory”, "Unable to decode stream: " + e);

} finally {

if (stream != null) {

try {

stream.close();

} catch (IOException e) {

// do nothing here

}

}

}

return bm;

}

decodeResource

从res资源文件读取图片。

加载的图片可能会经过缩放,该缩放目前是放在 java 层做的,效率比较低,而且需要消耗 java 层的内存。因此,如果大量使用该接口加载图片,容易导致OOM错误

/**

  • Synonym for opening the given resource and calling

  • {@link #decodeResourceStream}.

  • @param res The resources object containing the image data

  • @param id The resource id of the image data

  • @param opts null-ok; Options that control downsampling and whether the

  •         image should be completely decoded, or just is size returned.
    
  • @return The decoded bitmap, or null if the image data could not be

  •     decoded, or, if opts is non-null, if opts requested only the
    
  •     size be returned (in opts.outWidth and opts.outHeight)
    

*/

public static Bitmap decodeResource(Resources res, int id, Options opts) {

Bitmap bm = null;

InputStream is = null;

try {

final TypedValue value = new TypedValue();

is = res.openRawResource(id, value);

bm = decodeResourceStream(res, value, is, null, opts);

} catch (Exception e) {

/* do nothing.

If the exception happened on open, bm will be null.

If it happened on close, bm is still valid.

*/

} finally {

try {

if (is != null) is.close();

} catch (IOException e) {

// Ignore

}

}

if (bm == null && opts != null && opts.inBitmap != null) {

throw new IllegalArgumentException(“Problem decoding into existing bitmap”);

}

return bm;

}

decodeByteArray

从数组读取图片

/**

  • Decode an immutable bitmap from the specified byte array.

  • @param data byte array of compressed image data

  • @param offset offset into imageData for where the decoder should begin

  •           parsing.
    
  • @param length the number of bytes, beginning at offset, to parse

  • @param opts null-ok; Options that control downsampling and whether the

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

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

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

img

img

img

img

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

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

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

文末

不管怎么样,不论是什么样的大小面试,要想不被面试官虐的不要不要的,只有刷爆面试题题做好全面的准备,当然除了这个还需要在平时把自己的基础打扎实,这样不论面试官怎么样一个知识点里往死里凿,你也能应付如流啊

小编将自己6年以来的面试经验和学习笔记都整理成了一个**937页的PDF,**以及我学习进阶过程中看过的一些优质视频教程。

其实看到身边很多朋友抱怨自己的工资很低,包括笔者也是一样的,其原因是在面试过程中没有给面试官一个很好的答案。所以笔者会持续更新面试过程中遇到的问题,也希望大家和笔者一起进步,一起学习。

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

ength the number of bytes, beginning at offset, to parse

  • @param opts null-ok; Options that control downsampling and whether the

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

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

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

[外链图片转存中…(img-FYdOVKJ6-1713731809949)]

[外链图片转存中…(img-gDN9EKu2-1713731809952)]

[外链图片转存中…(img-qf7cbkgD-1713731809953)]

[外链图片转存中…(img-INhEMcc7-1713731809954)]

[外链图片转存中…(img-feCtVWTt-1713731809955)]

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

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

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

[外链图片转存中…(img-aRaUHiqn-1713731809957)]

文末

不管怎么样,不论是什么样的大小面试,要想不被面试官虐的不要不要的,只有刷爆面试题题做好全面的准备,当然除了这个还需要在平时把自己的基础打扎实,这样不论面试官怎么样一个知识点里往死里凿,你也能应付如流啊

小编将自己6年以来的面试经验和学习笔记都整理成了一个**937页的PDF,**以及我学习进阶过程中看过的一些优质视频教程。

[外链图片转存中…(img-nLEtlF94-1713731809958)]

其实看到身边很多朋友抱怨自己的工资很低,包括笔者也是一样的,其原因是在面试过程中没有给面试官一个很好的答案。所以笔者会持续更新面试过程中遇到的问题,也希望大家和笔者一起进步,一起学习。

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值