[英]How does Bitmap compress work in android?
我有一个一般性的问题。 我正在编写一个日志记录应用程序,用户可以在其中选择拍照并与其他信息一起保存。 所有信息都作为对象存储在arraylist中,但是我很难将图像作为对象的一部分保存到文件中。 我终于弄清楚了位图是不可序列化的,所以这就是一个问题所在。 现在,我要做的就是将位图保存在自己的arraylist中,以便可以使用与对象arraylist相同的位置调用特定的位图,并且可以在ImageViewer上设置位图。 在保存位图的所有发现中,我看到每个人都在对其进行压缩和解码。 我的问题是,为什么必须将位图压缩(或将其保存到文件中)?
以防万一这将使我的问题更有意义,这是我的代码:
package com.example.ticklist;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.StreamCorruptedException;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
public class DataProvider {
private static final String ROUTES = "routes";
private static final String PICS = "pictures";
static Bitmap photo;
static ArrayList<Bitmap> bList;
public static boolean writeRoute(Route r, Bitmap img){
ArrayList<Route> list = getRoutes();
ArrayList<Bitmap> bmlist = getPictures();
list.add(r);
bmlist.add(img);
FileOutputStream fos;
FileOutputStream fosp;
try {
fos = TicklistMain.getContext().openFileOutput(ROUTES, Context.MODE_PRIVATE);
ObjectOutputStream oos = new ObjectOutputStream(fos);
fosp = TicklistMain.getContext().openFileOutput(PICS, Context.MODE_PRIVATE);
ObjectOutputStream oosp = new ObjectOutputStream(fosp);
oos.writeObject(list);
oosp.writeObject(bmlist);
oos.close();
oosp.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return true;
}
public static ArrayList<Route> getRoutes(){
FileInputStream fis;
ArrayList<Route> list = null;
try {
fis = TicklistMain.getContext().openFileInput(ROUTES);
ObjectInputStream ois = new ObjectInputStream(fis);
list = (ArrayList<Route>) ois.readObject();
ois.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
list = new ArrayList<Route>();
} catch (StreamCorruptedException e) {
list = new ArrayList<Route>();
e.printStackTrace();
} catch (IOException e) {
list = new ArrayList<Route>();
e.printStackTrace();
} catch (ClassNotFoundException e) {
list = new ArrayList<Route>();
e.printStackTrace();
}
return list;
}
public static ArrayList<Bitmap> getPictures(){
FileInputStream fis;
ArrayList<Bitmap> bmlist = null;
try {
fis = TicklistMain.getContext().openFileInput(PICS);
ObjectInputStream ois = new ObjectInputStream(fis);
bmlist = (ArrayList<Bitmap>) ois.readObject();
ois.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
bmlist = new ArrayList<Bitmap>();
} catch (StreamCorruptedException e) {
bmlist = new ArrayList<Bitmap>();
e.printStackTrace();
} catch (IOException e) {
bmlist = new ArrayList<Bitmap>();
e.printStackTrace();
} catch (ClassNotFoundException e) {
bmlist = new ArrayList<Bitmap>();
e.printStackTrace();
}
return bmlist;
}
public static Bitmap getPicture(int position){
ArrayList<Bitmap> bList = getPictures();
photo = bList.get(position);
return photo;
}
}
以及我所说的位置:
package com.example.ticklist;
import java.util.ArrayList;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.app.ListFragment;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
public class SendList extends ListFragment {
AddRope ar = new AddRope();
Bitmap bm;
private static final String TAG = TicklistMain.class.getName();
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return super.onCreateView( inflater, container, savedInstanceState);
//View rootView = inflater.inflate( R.layout.mylistfrag_layout, container, false);
//return rootView;
}
@Override
public void onActivityCreated(Bundle b) {
super.onActivityCreated(b);
ArrayList<Route> list = DataProvider.getRoutes();
ArrayAdapter<Route> adapter = new ArrayAdapter<Route>(getActivity(),
android.R.layout.simple_list_item_1, list);
setListAdapter(adapter);
} //onActivity
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
ArrayList<Route> list = DataProvider.getRoutes();
ArrayList<Bitmap> pList = DataProvider.getPictures();
Log.d(TAG, "position " + position);
bm = pList.get(position - 1);
Route routeDetail = list.get(position);
RouteDetail fragment = new RouteDetail();
fragment.loadData(routeDetail);
fragment.loadPicture(bm);
final FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.ticklist_container, fragment);
ft.addToBackStack(null);
ft.commit();
}
}
和详细视图:
package com.example.ticklist;
import com.example.ticklist.R;
import android.app.Fragment;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
public class RouteDetail extends Fragment{
TextView routeName, routeGrade, routeDate, routeComments;
ImageView img;
private Route r;
private Bitmap bmp;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.route_detail,
container, false);
routeName = (TextView) view.findViewById(R.id.routeName);
routeGrade = (TextView) view.findViewById(R.id.routeGrade);
routeDate = (TextView) view.findViewById(R.id.routeDate);
routeComments = (TextView) view.findViewById(R.id.routeComments);
img = (ImageView) view.findViewById(R.id.routeImage);
routeName.setText(r.getName());
routeGrade.setText(r.getGrade());
routeDate.setText(r.getDate());
routeComments.setText(r.getComments());
img.setImageBitmap(bmp);
return view;
}
public void loadData(Route routeDetail) {
// TODO Auto-generated method stub
this.r = routeDetail;
}
public void loadPicture(Bitmap img){
this.bmp = img;
}
}
位图不必进行压缩,但是压缩它们可以实现两个目标:序列化它们并使它变小。
位图只是..位图...就这么简单,考虑一下:
如果您具有1000 x 1000的图像,并且每个像素都使用short表示一种颜色。 (这只是一个例子,所以和我一起滚动)。 现在,假设该图片中的每个像素都是白色。
如果在不压缩的情况下序列化了该文件,则文件将存储以下内容:height:1000,width:1000,content:WHITE,WHITE,WHITE,WHITE,WHITE,WHITE,WHITE,WHITE,.........
序列化取决于所使用的算法,但是假设您使用LZW的一种变体,并使用一个int表示集合中有多少像素和颜色。 在这种情况下,您只需要保存到压缩文件中即可:height:1000,width:1000,content:1000000xWHITE。 可以很容易地保存在几个字节中。
位图是可序列化的(实际上位图是序列化的)。 只需将其转换为Base64。
因此,基本上您可以压缩它,将其写入文件或序列化。
不必压缩它,但是将它们保存为未压缩是非常非常糟糕的做法,除非您有特定的理由不这样做。
位图的一个优点(以及Android应用程序使用它们的原因)是,它们完全未被压缩,实质上只是一堆描述图像的位。 现在,这意味着该格式非常简单且可以快速解码,这使得它们非常适合任何面向UI的应用程序,包括Android应用程序。 如果您要绘制的是PNG或JPEG而不是位图,则您的应用程序会慢很多 。
但是,这种简单性和完全没有压缩也使其成为迄今为止使用的存储空间最大的图像格式。 只需将位图甚至通过侵入性最小的JPEG或PNG压缩器,就可以将大小减小多个数量级,而代价是基本上没有质量(JPEG)或绝对没有质量损失(PNG)。 这使得很容易理解为什么每个人都这样做,即使他们不必这样做。 :)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.