Java 位图压缩在android中是如何工作的?
我有一个一般性的问题。 我正在编写一个日志应用程序,用户可以选择拍照并将其与其他信息一起保存。所有信息都作为对象存储在arraylist中,但我很难将图像作为对象的一部分保存到文件中。我最终发现位图是不可序列化的,所以这就是问题所在。现在,我只想将位图保存在它自己的arraylist中,这样我就可以使用与对象arraylist相同的位置调用特定位图,并且可以在ImageViewer上设置位图。 在我所有关于保存位图的发现中,我发现每个人都在压缩和解码位图。我的问题是,为什么位图必须被压缩(或是被压缩)才能保存到文件中 为了使我的问题更有意义,以下是我的代码:Java 位图压缩在android中是如何工作的?,java,android,bitmap,save,Java,Android,Bitmap,Save,我有一个一般性的问题。 我正在编写一个日志应用程序,用户可以选择拍照并将其与其他信息一起保存。所有信息都作为对象存储在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;
}
}
位图不需要压缩,但压缩位图可以实现两个目标:序列化位图和缩小位图 位图只是。。。。比特地图。。。尽管它是微不足道的,但请考虑如下: 如果你有一个1000 x 1000的图像,每个像素都用一个短字符表示一种颜色。(这只是一个例子,跟我来)。现在想象一下,这张图片中的每个像素都是白色的 如果在不压缩的情况下序列化此文件,则该文件将存储以下内容: 高度:1000,宽度:1000,内容:白色,白色,白色,白色,白色,白色,白色,白色,白色 序列化取决于使用的算法,但假设您使用LZW的一个变体,并使用一个int来指示集合和颜色中有多少像素。在这种情况下,您需要保存到压缩文件的所有内容是高度:1000,宽度:1000,内容:1000000xWHITE。它可以很容易地保存在几个字节内。位图是可序列化的(实际上,位图是序列化的)。只需将其转换为Base64即可
所以基本上你可以压缩它,把它写进一个文件或者序列化它。它不需要压缩,但是如果你没有特别的理由不压缩,保存它们是非常非常糟糕的做法 位图的一个优点——也是Android应用程序使用位图的原因——是位图完全未压缩,本质上只是一堆描述图像的位。现在,这意味着这种格式非常简单,解码速度也非常快,这使得它们适合任何面向用户界面的应用,包括Android应用。如果你画的是PNG或JPEG而不是位图,你的应用程序会慢很多
然而,这种简单性和完全缺乏压缩也使得它成为迄今为止所用存储空间最大的图像格式。只需将位图通过干扰最小的JPEG或PNG压缩器即可将大小减小多个数量级,代价是基本无质量(JPEG)或绝对无质量损失(PNG)。这使得人们很容易理解为什么每个人都这么做,即使他们不必这么做。:) 谢谢你,亚历山大。你回答了我的问题。你能解释一下为什么我上面的代码不起作用吗?我知道这不是保存和加载图像的最有效方法,但为什么当我单击“SendList”中的项目时不能将图像加载到RoutedDetail片段上呢?我在ipad上,但你可以在这里看到位图的序列化:谢谢你,FeleMed。要清楚一点,您是说位图是可序列化的,还是说压缩后可以序列化?文档说(据我所知)它只实现了parcelable,我想他是说它是“可序列化的”,因为你可以通过将它转换为Base64来序列化它,但不,它实际上没有实现可序列化。
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;
}
}