当前位置:网站首页>Custom view: graphics and image processing (I): using simple pictures
Custom view: graphics and image processing (I): using simple pictures
2022-06-10 22:54:00 【A thrill for Android】
Android The system provides ImageView Show normal still pictures , Also provided AnimationDrawable To develop frame by frame animation , Can also be through Animation Use gap animation for normal pictures . graphics 、 Image processing is not only for Android The application interface of the system is very important , and Android Puzzle games on the system 、2D Games need a lot of graphics 、 The image processing .
The so-called game , The essence is to provide more realistic 、 A user interface that simulates an environment , And respond to user actions according to certain rules . To provide a more realistic user interface , With the help of graphics 、 The image processing .
In a broad sense ,Android The pictures in the application are not only Include *.png、*.jpg、 *.gif And so on , Also include Use XML The resource file defines various Drawable object .
1. Use Drawable object
by Android Applications add Drawable After resources ,Android SDK For this resource in R Inventory file Create a Index entry :R.drawable.file_name.
Access method :
- stay XML In the resource file @drawablelfile_name Access to Drawable object ,
- stay Java Passed in code R.drawable.file_name Access to Drawable object .
It's important to point out that ,R.drawable.file_name It's a int Constant of type , It only represents Drawable Object's ID, If Java The program needs to get the actual Drawable object , Can be called Resources Of getDrawable (int id) Method to implement .
2.Bitmap and BitmapFactory
Bitmap Representing one Bitmap ,BitmapDrawable in encapsulation The picture is One Bitmap object .
The conversion between the two :
// Put one Bitmap Object packed as BitmapDrawable object BitmapDrawable drawable = new BitmapDrawable (bitmap) ;If you need to get BitmapDrawable It's packaged Bitmap object , Can be called BitmapDrawable Of getBitmap () Method , This is shown in the following code :
// obtain BitmapDrawable It's packaged Bitmap object Bitmap bitmap = drawable.getBitmap();
newly build Bitmap Some methods of object :
- createBitmap (Bitmap source,int x, int y,int width,int height): From source bitmap source The specified coordinate point of ( Given x、y) Start , from “ Dig up " wide width、 high height A piece of , Create a new Bitmap object .
- createScaledBitmap (Bitmap src, int dstWidth,int dstHeight,boolean filter) : For source bitmap src Zoom , Zoom to width dstWidth、 high dstHeight New bitmap for . filter It's the filter .
- createBitmap (int width,int height,Bitmap.Config config): Create a wide width、 high height New bitmap for .
- createBitmap (Bitmap source,int x, int y, int width,int height,Matrixm, boolean filter): From source bitmap source The specified coordinate point of ( Given x、y) Start , from “ Dig up " wide width、 high height A piece of , Create a new Bitmap object , And press Matrix The specified rules .
Bitmap.Config class , stay Bitmap In class createBitmap(int width, int height, Bitmap.Config config) It's used in the method , Open this class and have a look : Enumerate variables
public static final Bitmap.Config ALPHA_8
public static final Bitmap.Config ARGB_4444
public static final Bitmap.Config ARGB_8888
public static final Bitmap.Config RGB_565
BitmapFactory Is a utility class , It provides a number of methods , These methods can be used to parse from different data sources 、 establish Bitmap object .BitmapFactory The following methods are included .
- decodeByteArray (byte[]data,int offset,int length)︰ From the specified byte array offset Position start , The length will be length The byte data of is parsed into Bitmap object .
- decodeFile (String pathName) : from pathName Resolve in the specified file 、 establish Bitmap object .
- decodeFileDescriptor (FileDescriptor fd): For from FileDescriptor Parse in the corresponding file 、 establish Bitmap object .
- decodeResource (Resources res,int id) : Used according to a given resource ID Resolve from the specified resource 、 establish Bitmap object .
- decodeStream (InputStream is): Used to parse from the specified input stream 、 establish Bitmap object .
For creation , The corresponding is recycling . If the system keeps parsing 、 establish Bitmap object , Probably due to the creation of Bitmap The memory used has not been recycled yet , And lead to OOM.
- boolean isRecycled (): Return to the Bitmap Whether the object has been recycled .
- void recycle () : Force one Bitmap Object immediately reclaims itself .
If Android Applications need to be Access other storage paths ( such as SD card ) The picture in , Then we all need the help of BitmapFactory Parsing 、 establish Bitmap object .
2.1 Example

Let's develop a view /assets/ Picture viewer for pictures in the directory , When the user clicks this button, the program will automatically search /assets/ Under the directory — A picture . The interface layout code will not be given here , The code of the program is as follows .
public class Test4Activity extends Activity {
String[] images = null;
AssetManager assets = null;
int currentImg = 0;
private ImageView image;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test4_acitvity);
image = findViewById(R.id.test4_iv);
Button next = findViewById(R.id.test4_bt_next);
try {
assets = getAssets();
// obtain assets All files in the directory
images =assets.list("");
} catch (IOException e) {
e.printStackTrace();
}
// Button event
next.setOnClickListener(view -> {
// If the array is out of bounds
if(currentImg >= images.length){
currentImg = 0;
}
// Find the next picture file
while (!images[currentImg].endsWith(".png")&&!images[currentImg].endsWith(".jpg")
&&!images[currentImg].endsWith(".gif")){
currentImg++;
// If an array out of bounds has occurred
if(currentImg >= images.length){
currentImg = 0;
}
}
InputStream assetFile = null;
try {
// Open the input stream corresponding to the specified resource
assetFile = assets.open(images[currentImg++]);
} catch (IOException e) {
e.printStackTrace();
}
BitmapDrawable bitmapDrawable = (BitmapDrawable) image.getDrawable();
// If the picture hasn't been recycled yet , Force the image to be recycled first
if(bitmapDrawable != null&&!bitmapDrawable.getBitmap().isRecycled()){
bitmapDrawable.getBitmap().recycle();
}
// change ImageView display picture
// Called BitmapFactory Parses and creates... From the specified input stream Bitmap
image.setImageBitmap(BitmapFactory.decodeStream(assetFile));
});
}
}2.2 Extra knowledge (assets)
The system provides... For each newly designed program /assets Folder , This The files saved in the folder can be packaged in the program .
/res and /assets The difference is ,android Not for /assets File generation under ID. Suppose you use /assets The files under the , You need to specify the path and name of the file . How to access /assets Below ?
for example , Suppose that assets There is a name in the directory called filename The file of , Then you can access it using the following code :
AssetManager assset= getAssets();
InputStream is = assset.open("filename");2.3 Excellent thought learning , Make the code more rigorous
1. I found that the code is not yellow at all , The proof is rigorous .
Pay attention to why button Put it inside , and imageView Put it outside .
take button Put it outside there will be Field can be converted to a local variable Warning of , This means that this variable can be replaced with a local variable , It is recommended to delete and write it as a local variable . It is not used anywhere else , There is no need to declare as a member variable .
2. Design to array access , Be sure to prevent its array from going out of bounds . There are also two .
assetFile = assets.open(images[currentImg++]);At this point, enter open Must be the image resources name, After use currentImg Self adding , Explore the next picture . The first judgment to prevent the array from crossing the bounds is to prevent the array from crossing the bounds ; The second is corresponding to the judgment that it is not a picture resource ++. But there is still a problem with this code : If there are resources , But they are not picture resources . Then it will go into a dead circle
3. Before displaying the picture , Be sure to release the previous Bitmap, lest OOM
The condition for the judgment of release is to use Bitmap The wrapper class .
3.Android 9 Newly added ImageDecoder
Android 9 Introduced ImageDecoder、OnHanderDecodedListener etc. API, Provides more powerful picture decoding support , Can decode png、jpeg And so on gif、webp And so on . in addition . Also added support HEIF Format :
HEIF Format : This compression format With super high compression ratio , comparison JPEG, Can be compressed to half its size , And it can Ensure the approximate picture quality .
When using ImageDecoder decode gif、webp When waiting for animated pictures , Will return a AnimatedImageDrawable object , call AnimatedImageDrawable Object's start() Method to start the animation .
ImageDecoder How to decode pictures :
- call ImageDecoder Heavy load of createSource Method to create Source object . According to different picture sources , createSource Methods have different overload modes .
- call ImageDecoder Of decodeDrawabIe(Source) or decodeBitmap(Source) Method to read the Drawable or Bitmap object .
In the second step , It can be transmitted into a OnHanderDecodedListener Parameters , This parameter represents the listener , The listener should implement a onHanderDecoded(ImageDecoder,ImageInfo,Source) Method , It can be done to ImageDecoder Make additional settings , It can also be done through ImageInfo Get the information of the decoded picture .
3.1 Example
public class Test5Activity extends AppCompatActivity {
// To put it bluntly, there is only api 28 The later ones came in
@RequiresApi(api = Build.VERSION_CODES.P)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test5);
// Get objects
TextView textView = findViewById(R.id.test5_tv);
ImageView imageView = findViewById(R.id.test5_iv);
// establish imageDecoder.Source object
// First step :
ImageDecoder.Source source = ImageDecoder.createSource(getResources(),R.drawable.viewgif);
try {
// The second step : perform decodeDrawable() Method to get Drawable object
@SuppressLint({"WrongThread", "SetTextI18n"})
Drawable drawable = ImageDecoder.decodeDrawable(source,(decoder, info, s) ->{
// adopt info Parameter to obtain the information of the decoded picture
textView.setText(" The original width of the picture :"+info.getSize().getWidth()+
"\n"+" The original width and height of the picture "+info.getSize().getHeight());
// Set the zoom size after picture decoding
decoder.setTargetSize(600,580);
});
imageView.setImageDrawable(drawable);
// If drawable yes AnimatedImageDrawable Example , Then execute the animation
if(drawable instanceof AnimatedImageDrawable){
((AnimatedImageDrawable) drawable).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}With the traditional BitmapFactory comparison ,ImageDecoder Can even Decode pictures that contain incomplete or incorrect information , If you want to display ImageDecoder Some pictures before decoding error , Can be passed as ImageDecoder Not set OnPartialImageListener Monitor to achieve . For example, the following code snippet :
// First use Lambda Expression as OnHeaderDecodeListener Monitor
Drawable drawable = ImageDecoder.decodeDrawable(source,(decoder, info, s) ->{
// by ImageDecoder Set up OnPartialImageListener Monitor (Lambda expression )
decoder.setOnPartialImageListener(e->{
....
//return true Indicates that even if the entire picture cannot be decoded completely, it returns Drawable or Bitmap
return true;
});
});边栏推荐
- 【小程序】Vant-Weapp Radio单选框组件无法触发bind:Change事件
- dc_labs--lab1的学习与总结
- 【TcaplusDB知识库】TcaplusDB事务管理介绍
- CCF CSP 202109-4 collect cards
- [tcapulusdb knowledge base] tcapulusdb daily inspection introduction
- [Axi] explain the principle of two-way handshake mechanism of Axi protocol
- 图像拼接摄像头拼接笔记
- How about opening an account with flush? Is it safe to open an account?
- How to run Plink software -- three methods
- 数字孪生:第三人称鼠标操作
猜你喜欢

Whale conference sharing: what should we do if the conference is difficult?

【TcaplusDB知识库】TcaplusDB TcapProxy扩缩容介绍

Digital twin: third person mouse operation

Web3技术栈权威指南【2022】

TcaplusDB君 · 行业新闻汇编(四)

Interpretation of dataset class of mmdetection

【Xpath】使用following-sibling获取后面的同级节点

数字孪生:第三人称鼠标操作

Tcapulusdb Jun · industry news collection (IV)
![[tcapulusdb knowledge base] Introduction to tcapulusdb push configuration](/img/98/0819d5c30a3f214d97b43f2a949fa2.png)
[tcapulusdb knowledge base] Introduction to tcapulusdb push configuration
随机推荐
鲸会务会议分享:大会难办怎么办?
[applet] vant sliding cell adds the function of clicking other positions to close automatically
[tcapulusdb knowledge base] tcapulusdb tcapdb capacity expansion and contraction introduction
Reflow and repaint
SQLServer数据库应用与开发:第九章上机
kubernetes 二进制安装(v1.20.15)(六)部署WorkNode节点
Open source project PM how to design official website
Basic knowledge learning of Web cluster (1)
Sealem Finance打造Web3去中心化金融平台基础设施
TypeScript - 声明文件和内置对象
QT custom delegation
Niuke.com: sum of two numbers
Use of cocoeval function
【TcaplusDB知识库】TcaplusDB机器初始化和上架介绍
LeetCode - 5. 最长回文子串
Implementation of simply untyped lambda calculus
[XPath] use following sibling to obtain the following peer nodes
中银证券开户安全吗?它和中国银行是什么关系呢?
Digital twin: third person mouse operation
UE4骨骼动画新手入门