2011-08-19 10:35:37 yfxuchao 阅读数 73
  • 6.小项目.图片解码播放器

    本课程是《朱有鹏老师嵌入式linux核心课程》第6部分,是一个课程后的小项目。用开发板本身自带的硬件完成一个基于linux API开发的图片解码播放器,实现了对BMP、JPG、PNG等格式图片进行解码播放的功能。

    7515 人正在学习 去看看 朱有鹏

android中可以使用NinePatch处理PNG图片的失真问题。效果超级棒。哈哈。

2016-04-27 11:26:32 wxx614817 阅读数 6867
  • 6.小项目.图片解码播放器

    本课程是《朱有鹏老师嵌入式linux核心课程》第6部分,是一个课程后的小项目。用开发板本身自带的硬件完成一个基于linux API开发的图片解码播放器,实现了对BMP、JPG、PNG等格式图片进行解码播放的功能。

    7515 人正在学习 去看看 朱有鹏

        最近项目中遇到一个问题:就是从网络获取应用PNG图标后,显示到GridView中,发现图标透明的地方都变成了黑色?为什么呢?

        个人习惯有问题先梳理一遍代码:


一、从网络异步下载图标并显示代码

  

	class IconAsyncTask extends AsyncTask<String, Void, Bitmap> {

		private AdsInfo tAdsInfo;
		private ImageView tAppIcon;

		public IconAsyncTask(ImageView appIcon, AdsInfo adsInfo) {
			// TODO Auto-generated constructor stub
			tAppIcon = appIcon;
			tAdsInfo = adsInfo;
		}

		@Override
		protected Bitmap doInBackground(String... params) {
			// TODO Auto-generated method stub
			Bitmap icon = getBitmapFromURL(params[0]);
			try {
				FileUtil.writeImgFile(icon, getIconPath(tAdsInfo.id));
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			return icon;
		}

		@Override
		protected void onPostExecute(Bitmap result) {
			// TODO Auto-generated method stub
			if (tAppIcon.getTag().equals(tAdsInfo.url)) {
				tAppIcon.setImageBitmap(result);
			}
		}

	}

       其中,getBitmapFromURL()为从网络获取bitmap, writeImgFile()为保存图片到本地,具体代码看后面~



二、从网络获取Bitmap具体代码

	private Bitmap getBitmapFromURL(String urlString) {
		Bitmap bitmap = null;
		InputStream is = null;
		HttpURLConnection connection = null;
		for (int i = 0; i < Constants.NETWORK_RETRY_NUM; i++) {
			try {
				URL url = new URL(urlString);
				connection = (HttpURLConnection) url.openConnection();
				connection.setRequestMethod("GET");
				connection.setConnectTimeout(5000);
				connection.setReadTimeout(5000);
				connection.setDoInput(true);
				connection.setDoOutput(false);

				if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
					is = new BufferedInputStream(connection.getInputStream());
					bitmap = BitmapFactory.decodeStream(is);
					break;
				}
			} catch (MalformedURLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} finally {
				try {
					if (connection != null) {
						connection.disconnect();
					}
					if (is != null) {
						is.close();
					}
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}

		return bitmap;
	}


三、将Bitmap以PNG格式保存到本地

	public static void writeImgFile(Bitmap bitmap, String fileName)
			throws IOException {
		writeImgFile(bitmap, Bitmap.CompressFormat.PNG, new File(fileName));
	}

	public static void writeImgFile(Bitmap bitmap, CompressFormat format,
			File file) throws IOException {
		File parentDir = file.getParentFile();
		if ((parentDir != null) && !parentDir.exists()) {
			parentDir.mkdirs();
		}
		BufferedOutputStream bos = new BufferedOutputStream(
				new FileOutputStream(file));
		bitmap.compress(format, 100, bos);
		bos.flush();
		bos.close();
	}



四、保存路径代码

	private String getIconPath(int id) {
		String iconPath = StringUtil.stringAppend(
				SettingUtil.getDownloadPath(mContext), File.separator,
				Constants.BannerInfo.bannericon.info, File.separator,
				String.valueOf(id));
		return iconPath;
	}



五、分析解决问题
        代码走了一遍,没发现有问题,再用Android工具Hierarchy Viewer查看,发现图片的背景本身就是黑色的,说明什么呢?只有两种原因:一保存的图片为非PNG格式,二读取图片出错。

        再看代码,上面保存图片语句:writeImgFile(bitmap, Bitmap.CompressFormat.PNG, new File(fileName));确定保存为PNG格式。

        那读取显示图片呢?只是读取bitmap图片并显示,并不知道具体显示的是什么格式图片。难道真是这个问题? 于是把保存路径后面加上后缀名“.png”, 代码如下

	private String getIconPath(int id) {
		String iconPath = StringUtil.stringAppend(
				SettingUtil.getDownloadPath(mContext), File.separator,
				Constants.BannerInfo.bannericon.info, File.separator,
				String.valueOf(id), ".png");
		return iconPath;
	}
          再运行,果然,PNG完美显示。看来保存PNG格式图片时要注意加上后缀,否则在读取时有可能变成JPG格式了~~


2018-10-18 11:07:02 u011715726 阅读数 544
  • 6.小项目.图片解码播放器

    本课程是《朱有鹏老师嵌入式linux核心课程》第6部分,是一个课程后的小项目。用开发板本身自带的硬件完成一个基于linux API开发的图片解码播放器,实现了对BMP、JPG、PNG等格式图片进行解码播放的功能。

    7515 人正在学习 去看看 朱有鹏

Android 设置PNG图片的打印分辨率dpi(pHYs)

1.了解png的原文件数据,头文件IHDR,控制物理密度的pHYs,

  • 关于png的头文件IHDR:

https://blog.csdn.net/satanzw/article/details/38757121

png图片都是以固定标识89 50 4E 47 0D 0A 1A 0A开始,然后接着IHDR
例如一张png从头开始为:
89 50 4E 47 0D 0A 1A 0A00 00 00 0D49 48 44 52
00 00 00 06 00 00 00 06 08 02 00 00 00 F9 7D AA
93

对于上面,89 50 4E 47 0D 0A 1A 0A 是PNG头部署名域,表示这是一个PNG图片
00 00 00 0D 描述IHDR头部的大小 ,13个字节

49 48 44 52 是Chunk Type Code, 这里对应为‘IHDR ’,49对应为十进制的73,即为大写字母I的ASCII编码,同理后三字节分别对应H,D,R

00 00 00 06 00 00 00 06 08 02 00 00 00 是Chunk Data,前四字节是图片宽度,随后四字节是图片高度,00 00 00 06表示此图片宽高都是6, 6x6像素

F9 7D AA 93 是IHDR的CRC校验,至此头部结束

  • 关于PNG数据块(Chunk)

数据块有统一的格式,四字节数据块长度,四字节数据块名字,对应长度的数据值,四字节CRC校验
https://www.cnblogs.com/lidabo/p/3701197.html
https://www.w3.org/TR/PNG-Chunks.html

  • 关于pHYs数据块

对于pHYs,同理,四个长度,四个名字,9个数据,四个校验,共21字节
其中,9字节数据部分为关键,前4字节是横向密度,随后4字节是纵向密度,最后一个是密度单位,0未知,1是米。

通常dpi是指dots per inch,png中单位是dots per meter, 一英寸=0.0254米
也就是说,想要设置150dpi的话,这里要设置成150/0.0254=5906,但是注意5906是十进制!

The pHYs chunk specifies the intended pixel size or aspect ratio for display of the image. It contains:
Pixels per unit, X axis: 4 bytes (unsigned integer)
Pixels per unit, Y axis: 4 bytes (unsigned integer)
Unit specifier: 1 byte
The following values are legal for the unit specifier:
0: unit is unknown
1: unit is the meter
When the unit specifier is 0, the pHYs chunk defines pixel aspect ratio only; the actual size of the pixels remains unspecified.
Conversion note: one inch is equal to exactly 0.0254 meters.

  • 例如对于pHYs数据块如下:

00 00 00 09 70 48 59 73 00 00 17 12 00 00 17
12 01 67 9f d2 52

表示数据部分有9字节(00 00 00 09),名字是pHYs(70 48 59 73),打印分辨率是5906dpm,即150dpi(00 00 17 12),单位是米(01),CRC校验结尾(67 9f d2 52)

四字节crc校验具体算法我没研究,但是发现随便写上去也不影响图片的一般使用,所以这四字节我就随便取了四个值

以下是一张2x2像素的150dpi的png图片文件数据截图
在这里插入图片描述

2.设置图片打印分辨率dpi(物理分辨率), 即为png文件数据流中的pHYs数据块

在这里是文件结构中没有pHYs数据块的方法,在头文件IHDR之后添加pHYs数据块

**

  • 步骤:获取bitmap的数据流,向其字节数组中添加pHys数据,保存,bingo!

**
关键代码:

public static void save(Bitmap bitmap, File file, int dpi) {
        try {
            ByteArrayOutputStream imageByteArray = new ByteArrayOutputStream();
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, imageByteArray);
            byte[] imageData = imageByteArray.toByteArray();
            imageByteArray.close();

            FileOutputStream fileOutputStream = new FileOutputStream(file);
            fileOutputStream.write(setDpi(imageData, dpi));
            fileOutputStream.close();
            imageData = null;
            Log.e("aaa", "saved");
        } catch (Exception e) {
            Log.e("aaa", "Wrong in Class 'BitmapToPng'");
            Log.e("aaa", e.getMessage());
        }
    }

    private static byte[] setDpi(byte[] imageData, int dpi) {
        byte[] imageDataCopy = new byte[imageData.length + 21];
        System.arraycopy(imageData, 0, imageDataCopy, 0, 33);
        System.arraycopy(imageData, 33, imageDataCopy, 33 + 21, imageData.length - 33);

        int[] pHYs = new int[]{0, 0, 0, 9, 112, 72, 89, 115, 0, 0, 23, 18, 0, 0, 23, 18, 1, 103, 159, 210, 82};

        for (int i = 0; i < 21; i++) {
            imageDataCopy[i + 33] = (byte) (pHYs[i] & 0xff);
        }

        dpi = (int) (dpi / 0.0254);
        imageDataCopy[41] = (byte) (dpi >> 24);
        imageDataCopy[42] = (byte) (dpi >> 16);
        imageDataCopy[43] = (byte) (dpi >> 8);
        imageDataCopy[44] = (byte) (dpi & 0xff);

        imageDataCopy[45] = (byte) (dpi >> 24);
        imageDataCopy[46] = (byte) (dpi >> 16);
        imageDataCopy[47] = (byte) (dpi >> 8);
        imageDataCopy[48] = (byte) (dpi & 0xff);

//        for (int i = 0; i < 30; i++) {
//            String line = "";
//            for (int j = 0; j < 16; j++) {
//                int temp = imageDataCopy[16 * i + j] & 0xFF;
//                line += Integer.toHexString(temp) + " ";
//            }
//            Log.e(i + "", line);
//        }
        return imageDataCopy;
    }
2019-03-15 14:32:57 sinat_38184748 阅读数 156
  • 6.小项目.图片解码播放器

    本课程是《朱有鹏老师嵌入式linux核心课程》第6部分,是一个课程后的小项目。用开发板本身自带的硬件完成一个基于linux API开发的图片解码播放器,实现了对BMP、JPG、PNG等格式图片进行解码播放的功能。

    7515 人正在学习 去看看 朱有鹏

Android 制作.9.png图片之利用Android studio

前言

相关:Android 制作.9.png图片之利用Android 9-patch shadow generator

有时候UI给了切图,但是并不能直接使用,要转换成.9.png图才能使用。
举例:一个右上角弹窗
右上角弹窗
UI提供了设计切图:
设计切图
但是,这图普通的图,在我们的列表选项数量以及每项宽高不确定的时候直接使用这个当背景图会拉伸
所以需要制作.9.png图来满足需要。

制作

打开Android studio,打开你的项目
把你的普通png图放进 res 文件夹的 drawable 文件夹里
右键文件名
在这里插入图片描述
点击 Create 9-Parch file
就会在 res 文件夹的 drawable 文件夹里生成同名的后缀为.9.png的文件
删除普通png后缀的文件
双击后缀为.9.png的文件
打开编辑页面
在这里插入图片描述
这时候能看到图片四边有四条黑边。

  • 左侧黑边-----控制可拉伸变形的高度范围
  • 顶部黑边-----控制可拉伸变形的宽度范围
  • 右边黑边-----控制内容可填充的高度范围
  • 底部黑边-----控制内容可填充的宽度范围

设置好以后,就能直接当作普通图片使用了。完事

2018-03-13 14:30:17 u013365445 阅读数 94
  • 6.小项目.图片解码播放器

    本课程是《朱有鹏老师嵌入式linux核心课程》第6部分,是一个课程后的小项目。用开发板本身自带的硬件完成一个基于linux API开发的图片解码播放器,实现了对BMP、JPG、PNG等格式图片进行解码播放的功能。

    7515 人正在学习 去看看 朱有鹏

Android studio开发中,.9.png图片文件问题。

  • 开发中,我们要使用.9.png图片,如果直接改png图片的名字,然后拷贝到drawable文件夹里,Android studio就会报错


Error:java.util.concurrent.ExecutionException: com.android.builder.internal.aapt.AaptException:
Error:Execution failed for task ':app:mergeDebugResources'.
> Error: java.util.concurrent.ExecutionException: com.android.builder.internal.aapt.AaptException: 
  • 网上解决方法,不大靠谱,他们在gradle里面的buildToolsVersion 下面加
    aaptOptions.cruncherEnabled = false
    aaptOptions.useNewCruncher = false

这个法子说关闭png检测,这个法子不行。


  • 最直接的方法,就是直接拷贝png图片到drawable目录下,然后右键png图片,倒数第二个选项create 9-patch file...然后就好了
最后自己设置内容区域咯,完美

TIM截图20171214094036.jpg
没有更多推荐了,返回首页