在 Android 中解码 jpeg
Posted
技术标签:
【中文标题】在 Android 中解码 jpeg【英文标题】:Decoding a jpeg in Android 【发布时间】:2015-10-11 11:54:41 【问题描述】:我有从 URL 查看的 JSON 数据。 JSON 数组中有很多 JSON 对象,其中一个是 jpeg 图像。
我想将该图像发送到 android 应用中的列表视图。
现在我将图像 JSON 对象链接到我的 Java 文件中的私有静态最终字符串 TAG。但是,我意识到我必须对图像进行解码,否则我将收到以下错误:无法解码流:java.io.FileNotFoundException and resolveUri failed on bad bitmap uri。
我一直在进行长期的搜索,以了解如何解码 JSON jpeg 图像,大部分此类研究都是通过查看本网站上的帖子进行的,因此请不要标记为重复问题。
public class JSONBuilderActivity extends ListActivity
private ProgressDialog pDialog;
//URL to get JSON
private static String url = "";
//JSON Node names
private static final String TAG_CARS = "cars"; //root
private static final String TAG_CARID = "CarID";
private static final String TAG_CARVIN = "CarVIN";
private static final String TAG_IMG= "CarMainImage";
JSONArray carid = null; //Initializes JSON array
static String response = null;
//Hashmap for ListView
ArrayList<HashMap<String, Object>>caridList;
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
ListView lv = getListView();
//Listview on item click listener
lv.setOnItemClickListener(new OnItemClickListener()
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
//Gets values from selected ListItem
String cars = ((TextView) view.findViewById(R.id.cars)).getText().toString();
String car_id = ((TextView) view.findViewById(R.id.car_id)).getText().toString();
String car_vin = ((TextView) view.findViewById(R.id.car_vin)).getText().toString();
String model_img = ((ImageView) view.findViewById(R.id.model_img)).getTag().toString();
Intent in = new Intent(JSONBuilderActivity.this, MainActivity.class);
//Sends data to MainActivity
in.putExtra("TAG_CARS", cars);
in.putExtra("TAG_CARID", car_id);
in.putExtra("TAG_CarVin", car_vin);
in.putExtra("TAG_IMG", model_img);
startActivity(in);
);
//Calls async task to get json
new GetCars().execute();
public class ServiceHandler
public final static int GET = 1;
public final static int POST = 2;
public ServiceHandler()
/**
* Makes service call
* @url - url to make request
* @method - http request method
* */
public String makeServiceCall(String url, int method)
return this.makeServiceCall(url, method, null);
/**
* Makes service call
* @url - url to make request
* @method - http request method
* @params - http request params
* */
public String makeServiceCall(String url, int method,ArrayList<NameValuePair> params)
try
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpEntity httpEntity = null;
HttpResponse httpResponse = null;
//Checks http request method type
if (method == POST)
HttpPost httpPost = new HttpPost(url);
//Adds post params
if (params != null)
httpPost.setEntity(new UrlEncodedFormEntity(params));
httpResponse = httpClient.execute(httpPost);
else if (method == GET)
//Appends params to url
if (params != null)
String paramString = URLEncodedUtils.format(params, "utf-8");
url += "?" + paramString;
HttpGet httpGet = new HttpGet(url);
httpResponse = httpClient.execute(httpGet);
httpEntity = httpResponse.getEntity();
response = EntityUtils.toString(httpEntity);
catch (UnsupportedEncodingException e)
e.printStackTrace();
catch (ClientProtocolException e)
e.printStackTrace();
catch (IOException e)
e.printStackTrace();
return response;
/*
* Async task class to get json by making HTTP call
*/
private class GetCars extends AsyncTask<Void, Void, Void>
@Override
protected void onPreExecute()
super.onPreExecute();
caridList = new ArrayList<HashMap<String, Object>>();
//Shows progress dialog
pDialog = new ProgressDialog(JSONBuilderActivity.this);
pDialog.setMessage("Please wait...");
pDialog.setCancelable(false);
pDialog.show();
@Override
protected Void doInBackground(Void... arg0)
//Creates service handler class instance
ServiceHandler sh = new ServiceHandler();
//Makes a request to url and getting response
String jsonStr = sh.makeServiceCall(url, ServiceHandler.GET);
//Prints the json response in the log
Log.d("GetCars response: ", "> " + jsonStr);
if (jsonStr != null)
try
Log.d("try", "in the try");
JSONObject jsonObj = new JSONObject(jsonStr);
Log.d("jsonObject", "new json Object");
//Gets JSON Array node
carid = jsonObj.getJSONArray(TAG_CARS);
Log.d("json array", "user point array");
int len = carid.length();
Log.d("len", "get array length");
for (int i = 0; i < carid.length(); i++)
JSONObject c = carid.getJSONObject(i);
String car_id = c.getString(TAG_CARID);
Log.d("car_id", car_id);
String car_vin = c.getString(TAG_CARVIN);
Log.d("car_vin", car_vin);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), R.id.model_img, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
String imageType = options.outMimeType;
// byte[] byteArray = Base64.decode(jsonObj.getString(TAG_IMG), Base64.DEFAULT) ;
//Bitmap bmp1 = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length);
//String model_img = c.getString(TAG_IMG);
//Log.d("model_img", model_img);
//Hashmap for single match
HashMap<String, Object> matchGetCars = new HashMap<String, Object>();
//Adds each child node to HashMap key => value
matchGetCars.put(TAG_CARID, car_id);
matchGetCars.put(TAG_CARVIN, car_vin);
matchGetCars.put(TAG_IMG, ); //idk
caridList.add(matchGetCars);
catch (JSONException e)
e.printStackTrace();
else
Log.e("ServiceHandler", "Couldn't get any data from the url");
return null;
@Override
protected void onPostExecute(Void result)
super.onPostExecute(result);
//Dismisses the progress dialog
if (pDialog.isShowing())
pDialog.dismiss();
/**
* Updates parsed JSON data into ListView
* */
ListAdapter adapter = new SimpleAdapter(JSONBuilderActivity.this, caridList, R.layout.list_item,
new String[]TAG_CARID, TAG_CARVIN, TAG_IMG, new int[]R.id.car_id, R.id.car_vin, R.id.model_img);
setListAdapter(adapter);
Log.v("List parsed", caridList.toString());
因此,我们将不胜感激任何有关如何解码 JSON jpeg 图像的建议。谢谢你。
更新:
public Uri getImageUri(Context inContext, Bitmap inImage)
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
inImage.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
String path = MediaStore.Images.Media.insertImage(inContext.getContentResolver(), inImage, "CarMainImage", null);
return Uri.parse(path);
public void saveBmpToFile(File filename, Bitmap bmp)
FileOutputStream out = null;
try
out = new FileOutputStream(filename);
bmp.compress(Bitmap.CompressFormat.PNG, 100, out); // bmp is your Bitmap instance
// PNG is a lossless format, the compression factor (100) is ignored
catch (Exception e)
e.printStackTrace();
finally
try
if (out != null)
out.close();
catch (IOException e)
e.printStackTrace();
//------------------------
public boolean renameFileExtension(String source, String newExtension)
String target;
String currentExtension = getFileExtension(source);
if (currentExtension.equals(""))
target = source + "." + newExtension;
else
target = source.replaceFirst(Pattern.quote("." +
currentExtension) + "$", Matcher.quoteReplacement("." + newExtension));
return new File(source).renameTo(new File(target));
//---------------------------------------------------
public String getFileExtension(String f)
String ext = "";
int i = f.lastIndexOf('.');
if (i > 0 && i < f.length() - 1)
ext = f.substring(i + 1);
return ext;
/*
* Async task class to get json by making HTTP call
*/
private class GetCars extends AsyncTask<Void, Void, Void>
@Override
protected void onPreExecute()
super.onPreExecute();
caridList = new ArrayList<HashMap<String, Object>>();
//Shows progress dialog
pDialog = new ProgressDialog(JSONBuilderActivity.this);
pDialog.setMessage("Please wait...");
pDialog.setCancelable(false);
pDialog.show();
@Override
protected Void doInBackground(Void... arg0)
//Creates service handler class instance
ServiceHandler sh = new ServiceHandler();
//Makes a request to url and getting response
String jsonStr = sh.makeServiceCall(url, ServiceHandler.GET);
//Prints the json response in the log
Log.d("GetCars response: ", "> " + jsonStr);
if (jsonStr != null)
try
Log.d("try", "in the try");
JSONObject jsonObj = new JSONObject(jsonStr);
Log.d("jsonObject", "new json Object");
//Gets JSON Array node
carid = jsonObj.getJSONArray(TAG_CARS);
Log.d("json array", "user point array");
int len = carid.length();
Log.d("len", "get array length");
for (int i = 0; i < carid.length(); i++)
JSONObject c = carid.getJSONObject(i);
String car_id = c.getString(TAG_CARID);
Log.d("car_id", car_id);
String car_vin = c.getString(TAG_CARVIN);
Log.d("car_vin", car_vin);
String model_img=c.getString(TAG_IMG);
// byte[] byteArray = Base64.decode(jsonObj.getString(TAG_IMG), Base64.DEFAULT) ;
//Bitmap bmp1 = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length);
// String model_img = c.getString(TAG_IMG);
//Log.d("model_img", model_img);
//Hashmap for single match
HashMap<String, Object> matchGetCars = new HashMap<String, Object>();
//Adds each child node to HashMap key => value
matchGetCars.put(TAG_CARID, car_id);
matchGetCars.put(TAG_CARVIN, car_vin);
matchGetCars.put(TAG_IMG, model_img);
caridList.add(matchGetCars);
catch (JSONException e)
e.printStackTrace();
else
Log.e("ServiceHandler", "Couldn't get any data from the url");
return null;
@Override
protected void onPostExecute(Void result)
super.onPostExecute(result);
//Dismisses the progress dialog
if (pDialog.isShowing())
pDialog.dismiss();
/**
* Updates parsed JSON data into ListView
* */
ListAdapter adapter = new SimpleAdapter(JSONBuilderActivity.this, caridList, R.layout.list_item,
new String[]TAG_CARID, TAG_CARVIN, TAG_IMG, new int[]R.id.car_id, R.id.car_vin, R.id.model_img);
setListAdapter(adapter);
Log.v("List parsed", caridList.toString());
Logcat:
V/List parsed﹕ [CarMainImage=/images/image.php?w=200&i
Unable to decode stream: java.io.FileNotFoundException: /images/image.php?w=200....
unable to resolveUri failed on bad bitmap uri: /images/image.php?w=200....
我不明白为什么解析的列表被正确记录,然后那些错误弹出。但是,URL 中的 JSON jpeg 不像 log cat 中的 jpeg 那样完全格式化,因为 JSON 中的 jpeg 看起来像:/images/image.php?w=200... 而 logcat 中的 jpeg 看起来像:/images /image.php?200.. 所以区别在于..任何人都可以详细说明为什么会显示错误消息和/或提供修复错误的建议吗? 我非常愿意研究并来回了解您的建议。谢谢。
【问题讨论】:
vogella.com/tutorials/AndroidListView/… 看看,学习他的“视图持有者”模式,以帮助处理 img 标签和列表上下文中的位图 @RobertRowntree 我会彻底调查这个。谢谢! 【参考方案1】:without thinking I will post you some conversion code:
**this is a place holder.**
required understanding:
Bitmap
Uri Provides an object representation of a "uniform resource identifier"
URL (Universal resourse loacator) reference (an address) to a resource on the Internet.
file extensions. *.png *.jpg
this will be up-dated when my brain is not without sleep ;O)
more to come as I think , my brain hurts:
//------------------------
public Uri getImageUri(Context inContext, Bitmap inImage)
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
inImage.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
String path = Images.Media.insertImage(inContext.getContentResolver(), inImage, "Title", null);
return Uri.parse(path);
public void saveBmpToFile(File filename, Bitmap bmp)
FileOutputStream out = null;
try
out = new FileOutputStream(filename);
bmp.compress(Bitmap.CompressFormat.PNG, 100, out); // bmp is your Bitmap instance
// PNG is a lossless format, the compression factor (100) is ignored
catch (Exception e)
e.printStackTrace();
finally
try
if (out != null)
out.close();
catch (IOException e)
e.printStackTrace();
//------------------------
public static boolean renameFileExtension(String source, String newExtension)
String target;
String currentExtension = getFileExtension(source);
if (currentExtension.equals(""))
target = source + "." + newExtension;
else
target = source.replaceFirst(Pattern.quote("." +
currentExtension) + "$", Matcher.quoteReplacement("." + newExtension));
return new File(source).renameTo(new File(target));
//---------------------------------------------------
public static String getFileExtension(String f)
String ext = "";
int i = f.lastIndexOf('.');
if (i > 0 && i < f.length() - 1)
ext = f.substring(i + 1);
return ext;
//-----------------------
【讨论】:
你好。是的,我从我的另一篇文章中记得你。谢谢你回复这个。我想从存储在 URL 中的 JSON 数据中获取 jpeg 并解码该图像以在 ListView 中查看,而不是在我的 Android 应用程序中的 ImageView 中查看。最近,我一直在研究 Picasso 的 getView 方法,但到目前为止没有成功。和以前一样,我仍然非常愿意来回讨论解决方案。 谢谢!我稍微编辑了您的代码以解决出现的一些问题。我现在正在研究 URL 和 URI 之间的区别,.jpg 和位图解码的使用。我现在还尝试获取图像 uri 并将 uri 信息包含在 doInBackground 中,以将 uri 应用于与该图像相对应的 TAG_IMG。此外,我正在尝试获取该图像并在 ListView 而不是 ImageView 中查看它。我期待收到您的来信。 请耐心等待,我很忙,但我完全支持这个网站的精神——回馈一些东西。随着时间的推移,建立一个你喜欢和理解的代码库。编码是一项巨大的承诺和回报。这些点只是为了好玩(上瘾的性质不会被忽视!)。你的礼貌和热情,一个程序员的良好开端。继续努力吧。我希望很多人帮助你建立你的技能和代码库。继续破解! 有时候旅程比目的地更重要 ;O) 感谢您的提示(以及赞美)!根据您的个人资料信息和答案,听到一个受过良好教育和成功的人的消息是鼓舞人心的。我一定会记住你所说的一切。我非常同意旅程有时(通常对我而言)比目的地更重要。既然你对我帮助最大,我会毫无疑问地接受你的回答。非常感谢您的帮助。我已经在您的代码上构建了,并期待在很长一段时间内继续这样做。谢谢你,乔恩。【参考方案2】:任何BitmapFactory
方法适合您?有一对可以接受一个字节数组并给你一个Bitmap
。然后你可以很容易地将你的Bitmap
放入ImageView
。
【讨论】:
谢谢!我将继续研究 BitmapFactory 方法。但是,您可以解释一下如何将 Bitmap 放入 ListView 而不是 ImageView? 也许你可以编辑你的问题来画出你期望它的样子。如果您希望图像出现在视图中的每个列表项中,最好在列表项布局文件中放置一个 ImageView 并将其填充到列表适配器中。如果你想要它作为背景,那应该是一个相当简单的调用来设置视图的背景。 嗨,我编辑了我的问题以更彻底地解释我想做的事情。请看一下。谢谢!【参考方案3】:我建议使用Picasso
因为您只需要在适配器的 getView() 函数中提供图像 url 和 imageView。从 url 下载图像到位图转换并设置为图像视图的所有工作都将由 Picasso 处理。
例如:Picasso.with(context).load(url).into(view/*Your image view*/);
【讨论】:
您好,感谢您的回复。我正在通过 URL 访问 JSON 数据,所以我是否将该特定 URL 放在 load() 区域中?我现在正在研究 Picasso 以及它如何应用于 Android 适配器和视图。您能否详细说明您提供的毕加索示例?谢谢。 不,您只需要传递您在 JSON 数据中获取的图像 url。从您的 Json 数据中使用 for-each 循环获取所有图像 url 并将它们保存到一个列表中,然后将此列表传递给您的适配器。遵循此适配器代码。 github.com/square/picasso/blob/master/picasso-sample/src/main/…希望对你有帮助!!以上是关于在 Android 中解码 jpeg的主要内容,如果未能解决你的问题,请参考以下文章
Swift 中的 Base64 编码不会在 Android 中解码