1.基本的な考え方
-
画像のデコード
画像復号化は、異なるアーカイブフォーマットのピクチャ(例えば、復号化のある
JPEG
、PNG
アプリケーションまたはシステムに対応する処理を容易にするために、非圧縮のビットマップフォーマットになど)。 -
PixelMap
PixelMap
これは、画像のデコード後の非圧縮ビットマップ形式であり、画像の表示またはその後の処理に使用されます。 -
プログレッシブデコード
プログレッシブデコードとは、一度に完全な画像ファイルデータを提供できないモードです。画像ファイルデータが徐々に増えると、複数のインクリメンタルデコードによって画像デコードが徐々に完了します。
-
事前乗算
事前に乗算すると
RGB
、各チャネルの値は元の値にアルファチャネルの不透明な比率(0~1
)を掛けたものに置き換えられます。これは、後の段階での直接合成と重ね合わせに便利です。事前に乗算されていないということRGB
は、各チャネルの値が画像の元の値、およびAlpha
チャネルの値は無関係です。 -
画像コーディング
符号化画像は、アーカイブ形式の画像(に圧縮されていないビットマップ形式を符号化することである
JPEG
、PNG
等)異なるフォーマットでアプリケーションまたはシステムに対応する処理を容易にします。
制約と制限
- ローカルリソースを時間内に解放するために、画像デコード
ImageSource
オブジェクト、ビットマップ画像PixelMap
オブジェクト、または画像エンコードImagePacker
オブジェクトを使用した後、release()
メソッドをアクティブに呼び出すことをお勧めします。
2、画像のデコード
画像のデコードとは、サポートされている形式でアーカイブされた
PixelMap
画像を統合画像にデコードして、後続の画像表示や、回転、スケーリング、トリミングなどの他の処理を行うことです。現在サポートされているフォーマットにはJPEG
、PNG
、GIF
、HEIF
、WebP
、BMP
画像のデコードが主に使用され
ImageSource
、その一般的なインターフェイスは次のとおりです
インターフェイス名 | 説明 |
---|---|
create(String pathName、SourceOptions opts) | 画像ファイルパスから画像データソースを作成します。 |
create(InputStream is、SourceOptions opts) | 入力ストリームから画像データソースを作成します。 |
create(byte [] data、SourceOptions opts) | バイト配列から画像ソースを作成します。 |
create(byte [] data、int offset、int length、SourceOptions opts) | バイト配列の指定された範囲から画像ソースを作成します。 |
create(ファイルファイル、SourceOptions opts) | ファイルオブジェクトから画像データソースを作成します。 |
create(FileDescriptor fd、SourceOptions opts) | ファイル記述子から画像データソースを作成します。 |
createIncrementalSource(SourceOptions opts) | プログレッシブ画像データソースを作成します。 |
createIncrementalSource(IncrementalSourceOptions opts) | プログレッシブ画像データソースを作成し、プログレッシブデータ更新モードの設定をサポートします。 |
createPixelmap(DecodingOptions opts) | 画像データソースからPixelMap画像をデコードして作成します。 |
createPixelmap(int index、DecodingOptions opts) | 画像データソースからPixelMap画像をデコードして作成します。画像データソースが複数の画像をサポートしている場合、指定された画像インデックスがサポートされます。 |
updateData(byte [] data、boolean isFinal) | プログレッシブ画像ソースデータを更新します。 |
updateData(byte [] data、int offset、int length、boolean isFinal) | プログレッシブ画像ソースデータを更新し、入力データの有効なデータ範囲の設定をサポートします。 |
getImageInfo() | 基本的な画像情報を取得します。 |
getImageInfo(int index) | 特定のインデックスに従って基本的な画像情報を取得します。 |
getSourceInfo() | 画像ソース情報を取得します。 |
release() | オブジェクトに関連付けられているローカルリソースを解放します。 |
通常の開発
開発プロセスは次のとおりです
/**
* @description 普通模式解码
* @author PengHuAnZhi
* @date 2021/1/17 13:23
*/
private void testNormalImgDecode() {
/**
*1、
* 创建图像数据源ImageSource对象,可以通过SourceOptions指定数据源的格式信息,此格式信息仅为给解码器的提示,正确提供能帮助提高
* 解码效率,如果不设置或设置不正确,会自动检测正确的图像格式。不使用该选项时,可以将create接口传入的SourceOptions设置为null。
*/
ImageSource.SourceOptions srcOpts = new ImageSource.SourceOptions();
srcOpts.formatHint = "image/png";
String pathName = "/path/to/image.png";
ImageSource imageSource = ImageSource.create(pathName, srcOpts);
//也可以设置为空
ImageSource imageSourceNoOptions = ImageSource.create(pathName, null);
/**
* 2、
* 设置解码参数,解码获取PixelMap图像对象,解码过程中同时支持图像处理操作。设置desiredRegion支持按矩形区域裁剪,如果设置为全0,则不
* 进行裁剪。设置desiredSize支持按尺寸缩放,如果设置为全0,则不进行缩放。设置rotateDegrees支持旋转角度,以图像中心点顺时针旋转。如果只
* 需要解码原始图像,不使用该选项时,可将给createPixelMap传入的DecodingOptions 设置为null。
*/
// 普通解码叠加旋转、缩放、裁剪
ImageSource.DecodingOptions decodingOpts = new ImageSource.DecodingOptions();
decodingOpts.desiredSize = new Size(100, 2000);
decodingOpts.desiredRegion = new Rect(0, 0, 100, 100);
decodingOpts.rotateDegrees = 90;
PixelMap pixelMap = imageSource.createPixelmap(decodingOpts);
//3、普通解码
PixelMap pixelMapNoOptions = imageSource.createPixelmap(null);
//4、解码完成获取到PixelMap对象后,可以进行后续处理,比如渲染显示等。
//这里直接让一个image控件显示
mTestImg.setPixelMap(pixelMapNoOptions);
}
プログレッシブデコード
/**
* @description 渐进模式解码
* @author PengHuAnZhi
* @date 2021/1/17 13:34
*/
private void testGradualImgDecode() {
/**
* 1、
* 创建渐进式图像数据源ImageSource对象,可以通过SourceOptions指定数据源的格式信息,此格式信息仅为提示,如
* 果填写不正确,会自动检测正确的图像格式,使用IncrementalSourceOptions指定图像数据的更新方式为渐进式更新。
*/
ImageSource.SourceOptions srcOpts = new ImageSource.SourceOptions();
srcOpts.formatHint = "image/jpeg";
ImageSource.IncrementalSourceOptions incOpts = new ImageSource.IncrementalSourceOptions();
incOpts.opts = srcOpts;
incOpts.mode = ImageSource.UpdateMode.INCREMENTAL_DATA;
ImageSource imageSource = ImageSource.createIncrementalSource(incOpts);
//2、渐进式更新数据,在未获取到全部图像时,支持先更新部分数据来尝试解码,更新数据时设置isFinal为false,当获取到全部数据后,最后一次更新数据时设置isFinal为true,表示数据更新完毕。设置解码参数同普通解码。
// 获取到一定的数据时尝试解码,这里的第一个参数数据字节数组只是为了显示而模拟的,真实情况不是这样
imageSource.updateData(new byte[2048], 0, 20, false);
ImageSource.DecodingOptions decodingOpts = new ImageSource.DecodingOptions();
PixelMap pixelMap = imageSource.createPixelmap(decodingOpts);
mTestImg.setPixelMap(pixelMap);
// 更新数据再次解码,重复调用直到数据全部更新完成
imageSource.updateData(new byte[2048], 0, 20, false);
PixelMap pixelMapNext = imageSource.createPixelmap(decodingOpts);
mTestImg.setPixelMap(pixelMapNext);
// 3、数据全部更新完成时需要传入isFinal为true
imageSource.updateData(new byte[2048], 0, 20, true);
PixelMap pixelMapFinal = imageSource.createPixelmap(decodingOpts);
//4、解码完成获取到PixelMap对象后,可以进行后续处理,比如渲染显示等。
mTestImg.setPixelMap(pixelMapFinal);
}
3、画像コーディング
画像のエンコードとは
PixelMap
、保存や送信などの後続の他の処理のために、画像をさまざまなアーカイブ形式の画像にエンコードすることです。現在サポートされてJPEG
いるのはフォーマットのみです。
画像コーディングが主に使用され
ImagePacker
、その主なインターフェイスは次のとおりです
インターフェイス名 | 説明 |
---|---|
create() | イメージパッカーのインスタンスを作成します。 |
initializePacking(byte [] data、PackingOptions opts) | パッキングタスクを初期化し、パッキング後の出力先としてバイト配列を設定します。 |
initializePacking(byte [] data、int offset、PackingOptions opts) | パッキングタスクを初期化し、パッキング後の出力先としてオフセットを使用してバイト配列を設定します。 |
initializePacking(OutputStream outputStream、PackingOptions opts) | パッケージングタスクを初期化し、パッケージ化後の出力先として出力ストリームを設定します。 |
addImage(PixelMap pixelmap) | PixelMapオブジェクトをイメージパッカーに追加します。 |
addImage(ImageSourceソース) | 画像データソースImageSourceの画像を画像パッカーに追加します。 |
addImage(ImageSource source、int index) | 画像データソースImageSource内の指定された画像を画像パッカーに追加します。 |
finalizePacking() | 画像のパッケージ化タスクを完了します。 |
release() | オブジェクトに関連付けられているローカルリソースを解放します。 |
開発プロセスは次のとおりです
/**
* @description 图像编码
* @author PengHuAnZhi
* @date 2021/1/17 13:45
*/
private void testImgEncode() {
//1、创建图像编码ImagePacker对象。
ImagePacker imagePacker = ImagePacker.create();
//2、设置编码输出流和编码参数。设置format为编码的图像格式,当前支持jpeg格式。设置quality为图像质量,范围从0-100,100为最佳质量。
FileOutputStream outputStream = null;
try {
outputStream = new FileOutputStream("/path/to/packed.file");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
ImagePacker.PackingOptions packingOptions = new ImagePacker.PackingOptions();
packingOptions.format = "image/jpeg";
packingOptions.quality = 90;
boolean result = imagePacker.initializePacking(outputStream, packingOptions);
//这里开始是纯为了构造一个pixel而写的,无实际意义
ImageSource.SourceOptions srcOpts = new ImageSource.SourceOptions();
srcOpts.formatHint = "image/png";
String pathName = "/path/to/image.png";
ImageSource imageSource = ImageSource.create(pathName, srcOpts);
ImageSource imageSourceNoOptions = ImageSource.create(pathName, null);
ImageSource.DecodingOptions decodingOpts = new ImageSource.DecodingOptions();
decodingOpts.desiredSize = new Size(100, 2000);
decodingOpts.desiredRegion = new Rect(0, 0, 100, 100);
decodingOpts.rotateDegrees = 90;
//结束,创建了一个pixelMap
PixelMap pixelMap = imageSource.createPixelmap(decodingOpts);
result = imagePacker.addImage(pixelMap);
long dataSize = imagePacker.finalizePacking();
//5、编码输出完成后,可以进行后续处理,比如保存、传输等。
}
4、ビットマップ
ビットマップ操作とは
PixelMap
、情報の作成、クエリ、ピクセルデータの読み取りと書き込みなど、画像に対する関連操作を指します。
ビットマップ操作の
PixelMap
主なインターフェイスは次のとおりです
インターフェイス名 | 説明 |
---|---|
create(InitializationOptions opts) | 画像サイズ、ピクセル形式、アルファタイプなどの初期化オプションに基づいてPixelMapを作成します。 |
create(int []色、InitializationOptions opts) | 根据图像大小、像素格式、alpha类型等初始化选项,以像素颜色数组为数据源创建PixelMap。 |
create(int[] colors, int offset, int stride, InitializationOptions opts) | 根据图像大小、像素格式、alpha类型等初始化选项,以像素颜色数组、起始偏移量、行像素大小描述的数据源创建PixelMap。 |
create(PixelMap source, InitializationOptions opts) | 根据图像大小、像素格式、alpha类型等初始化选项,以源PixelMap为数据源创建PixelMap。 |
create(PixelMap source, Rect srcRegion, InitializationOptions opts) | 根据图像大小、像素格式、alpha类型等初始化选项,以源PixelMap、源裁剪区域描述的数据源创建PixelMap。 |
getBytesNumberPerRow() | 获取每行像素数据占用的字节数。 |
getPixelBytesCapacity() | 获取存储Pixelmap像素数据的内存容量。 |
isEditable() | 判断PixelMap是否允许修改。 |
isSameImage(PixelMap other) | 判断两个图像是否相同,包括ImageInfo属性信息和像素数据。 |
readPixel(Position pos) | 读取指定位置像素的颜色值,返回的颜色格式为PixelFormat.ARGB_8888。 |
readPixels(int[] pixels, int offset, int stride, Rect region) | 读取指定区域像素的颜色值,输出到以起始偏移量、行像素大小描述的像素数组,返回的颜色格式为PixelFormat.ARGB_8888。 |
readPixels(Buffer dst) | 读取像素的颜色值到缓冲区,返回的数据是PixelMap中像素数据的原样拷贝,即返回的颜色数据格式与PixelMap中像素格式一致。 |
resetConfig(Size size, PixelFormat pixelFormat) | 重置PixelMap的大小和像素格式配置,但不会改变原有的像素数据也不会重新分配像素数据的内存,重置后图像数据的字节数不能超过PixelMap的内存容量。 |
setAlphaType(AlphaType alphaType) | 设置PixelMap的Alpha类型。 |
writePixel(Position pos, int color) | 向指定位置像素写入颜色值,写入颜色格式为PixelFormat.ARGB_8888。 |
writePixels(int[] pixels, int offset, int stride, Rect region) | 将像素颜色数组、起始偏移量、行像素的个数描述的源像素数据写入PixelMap的指定区域,写入颜色格式为PixelFormat.ARGB_8888。 |
writePixels(Buffer src) | 将缓冲区描述的源像素数据写入PixelMap,写入的数据将原样覆盖PixelMap中的像素数据,即写入数据的颜色格式应与PixelMap的配置兼容。 |
writePixels(int color) | 将所有像素都填充为指定的颜色值,写入颜色格式为 PixelFormat.ARGB_8888。 |
getPixelBytesNumber() | 获取全部像素数据包含的字节数。 |
setBaseDensity(int baseDensity) | 设置PixelMap的基础像素密度值。 |
getBaseDensity() | 获取PixelMap的基础像素密度值。 |
setUseMipmap(boolean useMipmap) | 设置PixelMap渲染是否使用mipmap。 |
useMipmap() | 获取PixelMap渲染是否使用mipmap。 |
getNinePatchChunk() | 获取图像的NinePatchChunk数据。 |
getFitDensitySize(int targetDensity) | 获取适应目标像素密度的图像缩放的尺寸。 |
getImageInfo() | 获取图像基本信息。 |
release() | 释放对象关联的本地资源。 |
开发流程如下
/**
* @description 位图
* @author PengHuAnZhi
* @date 2021/1/17 13:52
*/
private void testPixelMap() {
//创建位图对象PixelMap。
// 指定初始化选项创建
// 从像素颜色数组创建
int[] defaultColors = new int[]{
5, 5, 5, 5, 6, 6, 3, 3, 3, 0};
/**
* 可以指定的初始化选项有下面几个
* public AlphaType alphaType;//AlphaType是一个枚举类,其中定义了若干常量
* public boolean editable = false;//是否可编辑
* public PixelFormat pixelFormat;//描述图像像素格式,也是一个枚举类
* public boolean releaseSource = false;//字面意思是释放资源,我也不知道是什么
* public ScaleMode scaleMode;//又是一个枚举类,图像缩放效果
* public Size size;//大小吧
* public boolean useSourceIfMatch = false;//如果匹配使用资源?
*/
PixelMap.InitializationOptions initializationOptions = new PixelMap.InitializationOptions();
initializationOptions.size = new Size(3, 2);
initializationOptions.pixelFormat = PixelFormat.ARGB_8888;
PixelMap pixelMap1 = PixelMap.create(defaultColors, initializationOptions);
// 以另外一个PixelMap作为数据源创建
PixelMap pixelMap2 = PixelMap.create(pixelMap1, initializationOptions);
//从位图对象中获取信息。
long capacity = pixelMap1.getPixelBytesCapacity();
long bytesNumber = pixelMap1.getPixelBytesNumber();
int rowBytes = pixelMap1.getBytesNumberPerRow();
byte[] ninePatchData = pixelMap1.getNinePatchChunk();
//读写位图像素数据。
// 读取指定位置像素
int color = pixelMap1.readPixel(new Position(1, 1));
// 读取指定区域像素
int[] pixelArray = new int[50];
Rect region = new Rect(0, 0, 10, 5);
pixelMap1.readPixels(pixelArray, 0, 10, region);
// 读取像素到Buffer
IntBuffer pixelBuf = IntBuffer.allocate(50);
pixelMap1.readPixels(pixelBuf);
// 在指定位置写入像素
pixelMap1.writePixel(new Position(1, 1), 0xFF112233);
// 在指定区域写入像素
pixelMap1.writePixels(pixelArray, 0, 10, region);
// 写入Buffer中的像素
pixelMap1.writePixels(defaultColors[0]);
}
五、图像属性解码
图像属性解码就是获取图像中包含的属性信息,比如
EXIF
属性
功能主要由
ImageSource
和ExifUtils
提供。
- ImageSource
接口名 | 描述 |
---|---|
getThumbnailInfo() | 获取嵌入图像文件的缩略图的基本信息。 |
getImageThumbnailBytes() | 获取嵌入图像文件缩略图的原始数据。 |
getThumbnailFormat() | 获取嵌入图像文件缩略图的格式。 |
- ExifUtils
接口名 | 描述 |
---|---|
getLatLong(ImageSource imageSource) | 获取嵌入图像文件的经纬度信息。 |
getAltitude(ImageSource imageSource, double defaultValue) | 获取嵌入图像文件的海拔信息。 |
开发流程如下
/**
* @description 图像属性解码
* @author PengHuAnZhi
* @date 2021/1/17 14:02
*/
private void testImgValueDecode() {
//1、创建图像数据源ImageSource对象,可以通过SourceOptions指定数据源的格式信息,此格式信息仅为给
// 解码器的提示,正确提供能帮助提高解码效率,如果不设置或设置不正确,会自动检测正确的图像格式。
ImageSource.SourceOptions srcOpts = new ImageSource.SourceOptions();
srcOpts.formatHint = "image/jpeg";
String pathName = "/path/to/image.jpg";
ImageSource imageSource = ImageSource.create(pathName, srcOpts);
//2、获取缩略图信息。
int format = imageSource.getThumbnailFormat();
byte[] thumbnailBytes = imageSource.getImageThumbnailBytes();
//3、将缩略图解码为PixelMap对象
ImageSource.DecodingOptions decodingOpts = new ImageSource.DecodingOptions();
PixelMap thumbnailPixelmap = imageSource.createThumbnailPixelmap(decodingOpts, false);
}