需要图片集和源码请点赞关注收藏后评论区留言~~~

一、转换位图的像素色彩

给图片添加装饰物,只是在局部变换,如果想让图片一边保持轮廓一边改变色彩,就要深入图像的每个像素点,将这些像素点统统采取某种算法修改一番,在像素级别更改图像的话,要先把图片转换成位图对象再进一步加工位图对象,此时用到了位图工具Bitmap 主要方法如下

1:createBitmap 创建一个新位图

2:getPixels 获取位图对象所有点的像素数组

3:setPixels 设置位图对象所有点的像素数组

效果如下 可以将一张图片以多种色彩效果显示出来

代码如下

Java类

package com.example.picture;import androidx.appcompat.app.AppCompatActivity;import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.Spinner;import com.example.picture.util.BitmapUtil;public class BitmapPixelActivity extends AppCompatActivity {private ImageView iv_picture; // 声明一个图像视图对象private Bitmap mOriginBitmap; // 原始位图@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_bitmap_pixel);iv_picture = findViewById(R.id.iv_picture);mOriginBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.butterfly);initColorSpinner(); // 初始化色彩模式下拉框}// 初始化色彩模式下拉框private void initColorSpinner() {ArrayAdapter<String> colorAdapter = new ArrayAdapter<>(this,R.layout.item_select, colorNameArray);Spinner sp_color = findViewById(R.id.sp_color);sp_color.setPrompt("请选择色彩模式");sp_color.setAdapter(colorAdapter);sp_color.setOnItemSelectedListener(new ColorSelectedListener());sp_color.setSelection(0);}private String[] colorNameArray = {"原色", "黑白", "底片", "怀旧", "模糊"};class ColorSelectedListener implements AdapterView.OnItemSelectedListener {public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {if (arg2 == 0) { // 原色iv_picture.setImageBitmap(mOriginBitmap); // 设置图像视图的位图对象} else if (arg2 == 1) { // 黑白Bitmap bitmap = BitmapUtil.convertBlack(mOriginBitmap); // 转换为黑白效果iv_picture.setImageBitmap(bitmap); // 设置图像视图的位图对象} else if (arg2 == 2) { // 底片Bitmap bitmap = BitmapUtil.convertNegative(mOriginBitmap); // 转换为底片效果iv_picture.setImageBitmap(bitmap); // 设置图像视图的位图对象} else if (arg2 == 3) { // 怀旧Bitmap bitmap = BitmapUtil.convertOld(mOriginBitmap); // 转换为怀旧效果iv_picture.setImageBitmap(bitmap); // 设置图像视图的位图对象} else if (arg2 == 4) { // 模糊Bitmap bitmap = BitmapUtil.convertBlur(mOriginBitmap); // 转换为模糊效果iv_picture.setImageBitmap(bitmap); // 设置图像视图的位图对象}}public void onNothingSelected(AdapterView<?> arg0) {}}}

XML文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="40dp"><TextViewandroid:layout_width="wrap_content"android:layout_height="match_parent"android:paddingLeft="5dp"android:gravity="center"android:text="请选择色彩模式"android:textColor="@color/black"android:textSize="17sp" /><Spinnerandroid:id="@+id/sp_color"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:gravity="center"android:spinnerMode="dialog" /></LinearLayout><ImageViewandroid:id="@+id/iv_picture"android:layout_width="match_parent"android:layout_height="200dp"android:src="@drawable/butterfly" />
</LinearLayout>

二、裁剪位图内部区域

createBitmap方法不仅可以创建空白位图,甚至能从原位图上截取一部分下来,裁剪出来的新位图来自原始位图,为了清楚的标记它在原位图的位置,可在图像视图上方覆盖新的图层,然后新图层先画一遍半透明的阴影,再画裁剪的位图部分,观察新老图层就可以看出裁剪的部位 效果如下

可以在下拉框中红选择裁剪不同区域并且保留图片

代码如下

Java类

package com.example.picture;import android.graphics.Bitmap;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.Toast;import androidx.appcompat.app.AppCompatActivity;import com.example.picture.util.BitmapUtil;
import com.example.picture.util.DateUtil;
import com.example.picture.widget.CropImageView;public class BitmapCutActivity extends AppCompatActivity {private CropImageView civ_over; // 声明一个裁剪视图对象private ImageView iv_old; // 声明一个原始图片的图像视图对象private ImageView iv_new; // 声明一个最新图片的图像视图对象@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_bitmap_cut);civ_over = findViewById(R.id.civ_over);iv_old = findViewById(R.id.iv_old);iv_new = findViewById(R.id.iv_new);findViewById(R.id.btn_save_image).setOnClickListener(v -> {civ_over.setVisibility(View.GONE);Bitmap bitmap = civ_over.getCropBitmap(); // 获取裁剪视图处理后的位图iv_new.setImageBitmap(bitmap); // 设置图像视图的位图对象// 生成图片文件的保存路径String path = String.format("%s/%s.jpg",getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).toString(),DateUtil.getNowDateTime());BitmapUtil.saveImage(path, bitmap); // 把位图保存为图片文件BitmapUtil.notifyPhotoAlbum(this, path); // 通知相册来了张新图片Toast.makeText(this, "成功保存图片文件:" + path, Toast.LENGTH_SHORT).show();initZoneSpinner(); // 初始化裁剪区域下拉框});iv_old.setDrawingCacheEnabled(true); // 开启位图视图的绘图缓存iv_old.setImageResource(R.drawable.butterfly); // 设置图像视图的资源编号new Handler(Looper.myLooper()).postDelayed(() -> initZoneSpinner(), 200);}// 初始化裁剪区域下拉框private void initZoneSpinner() {ArrayAdapter<String> zoneAdapter = new ArrayAdapter<>(this,R.layout.item_select, zoneNameArray);Spinner sp_zone = findViewById(R.id.sp_zone);sp_zone.setPrompt("请选择裁剪区域");sp_zone.setAdapter(zoneAdapter);sp_zone.setOnItemSelectedListener(new ZoneSelectedListener());sp_zone.setSelection(0);}private String[] zoneNameArray = {"不裁剪", "中间", "左上角", "右上角", "左下角", "右下角"};class ZoneSelectedListener implements AdapterView.OnItemSelectedListener {public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {civ_over.setVisibility(arg2==0?View.GONE:View.VISIBLE);Bitmap bitmap = iv_old.getDrawingCache(); // 从绘图缓存获取位图对象int width = bitmap.getWidth(), height = bitmap.getHeight();civ_over.setOrigBitmap(bitmap); // 设置裁剪视图的原始位图// 以下依据裁剪区域分别设置裁剪视图的位图边界if (arg2 == 1) { // 中间civ_over.setBitmapRect(new Rect(width/4, height/4, width/2, height/2));} else if (arg2 == 2) { // 左上角civ_over.setBitmapRect(new Rect(0, 0, width/2, height/2));} else if (arg2 == 3) { // 右上角civ_over.setBitmapRect(new Rect(width/2, 0, width/2, height/2));} else if (arg2 == 4) { // 左下角civ_over.setBitmapRect(new Rect(0, height/2, width/2, height/2));} else if (arg2 == 5) { // 右下角civ_over.setBitmapRect(new Rect(width/2, height/2, width/2, height/2));}}public void onNothingSelected(AdapterView<?> arg0) {}}}

XML文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical" ><LinearLayoutandroid:layout_width="match_parent"android:layout_height="40dp"><TextViewandroid:layout_width="wrap_content"android:layout_height="match_parent"android:paddingLeft="5dp"android:gravity="center"android:text="请选择裁剪区域"android:textColor="@color/black"android:textSize="17sp" /><Spinnerandroid:id="@+id/sp_zone"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:gravity="center"android:spinnerMode="dialog" /></LinearLayout><FrameLayoutandroid:layout_width="match_parent"android:layout_height="200dp" ><ImageViewandroid:id="@+id/iv_old"android:layout_width="match_parent"android:layout_height="match_parent" /><com.example.picture.widget.CropImageViewandroid:id="@+id/civ_over"android:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@color/transparent"android:scaleType="fitXY"android:visibility="gone" /></FrameLayout><Buttonandroid:id="@+id/btn_save_image"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="保存图片"android:textColor="@color/black"android:textSize="17sp" /><ImageViewandroid:id="@+id/iv_new"android:layout_width="match_parent"android:layout_height="200dp"android:scaleType="centerInside" />
</LinearLayout>

三、利用矩阵变换位图

可以利用矩阵工具Matrix对图片完成缩放 旋转 平移等变换操作 常用方法如下

postScale 指定横纵坐标两个方向的缩放比率

postRotate  指定旋转角度

postTranslate 指定横纵坐标两个方向的偏移大小

postSkew 指定横纵坐标两个方向的倾斜比例

效果如下 可在下拉框中选择旋转角度以及缩放比例、是否左右反转图像等等 同样可以保存图片

代码如下

Java类

package com.example.picture;import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.Spinner;
import android.widget.Toast;import androidx.appcompat.app.AppCompatActivity;import com.example.picture.util.BitmapUtil;
import com.example.picture.util.DateUtil;
import com.example.picture.widget.BitmapView;public class BitmapChangeActivity extends AppCompatActivity {private BitmapView bv_image; // 声明一个位图视图对象@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_bitmap_change);CheckBox ck_flip = findViewById(R.id.ck_flip);bv_image = findViewById(R.id.bv_image);ck_flip.setOnCheckedChangeListener((buttonView, isChecked) -> {bv_image.flip(); // 左右翻转图像});findViewById(R.id.btn_save_image).setOnClickListener(v -> {Bitmap bitmap = bv_image.getDrawingCache(); // 从绘图缓存获取位图对象// 生成图片文件的保存路径String path = String.format("%s/%s.jpg",getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).toString(),DateUtil.getNowDateTime());BitmapUtil.saveImage(path, bitmap); // 把位图保存为图片文件BitmapUtil.notifyPhotoAlbum(this, path); // 通知相册来了张新图片Toast.makeText(this, "成功保存图片文件:" + path, Toast.LENGTH_LONG).show();});initScaleSpinner(); // 初始化缩放比率下拉框initRotateSpinner(); // 初始化旋转角度下拉框}@Overrideprotected void onStart() {super.onStart();bv_image.setDrawingCacheEnabled(true); // 开启位图视图的绘图缓存Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.butterfly);bv_image.setImageBitmap(bitmap); // 设置位图视图的位图对象}@Overrideprotected void onStop() {super.onStop();bv_image.setDrawingCacheEnabled(false); // 关闭位图视图的绘图缓存}// 初始化缩放比率下拉框private void initScaleSpinner() {ArrayAdapter<String> scaleAdapter = new ArrayAdapter<>(this,R.layout.item_select, scaleArray);Spinner sp_scale = findViewById(R.id.sp_scale);sp_scale.setPrompt("请选择缩放比率");sp_scale.setAdapter(scaleAdapter);sp_scale.setOnItemSelectedListener(new ScaleSelectedListener());sp_scale.setSelection(3);}private String[] scaleArray = {"0.25", "0.5", "0.75", "1.0", "1.5", "2.0", "4.0"};class ScaleSelectedListener implements OnItemSelectedListener {public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {// 设置缩放比例bv_image.setScaleRatio(Float.parseFloat(scaleArray[arg2]), true);}public void onNothingSelected(AdapterView<?> arg0) {}}// 初始化旋转角度下拉框private void initRotateSpinner() {ArrayAdapter<String> rotateAdapter = new ArrayAdapter<>(this,R.layout.item_select, rotateArray);Spinner sp_rotate = findViewById(R.id.sp_rotate);sp_rotate.setPrompt("请选择旋转角度");sp_rotate.setAdapter(rotateAdapter);sp_rotate.setOnItemSelectedListener(new RotateSelectedListener());sp_rotate.setSelection(0);}private String[] rotateArray = {"0", "45", "90", "135", "180", "225", "270", "315"};class RotateSelectedListener implements OnItemSelectedListener {public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {// 设置旋转角度bv_image.setRotateDegree(Integer.parseInt(rotateArray[arg2]), true);}public void onNothingSelected(AdapterView<?> arg0) {}}}

XML文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical" ><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:paddingLeft="5dp"android:orientation="horizontal" ><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="缩放比率"android:textColor="@color/black"android:textSize="17sp" /><Spinnerandroid:id="@+id/sp_scale"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:spinnerMode="dialog" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="旋转角度"android:textColor="@color/black"android:textSize="17sp" /><Spinnerandroid:id="@+id/sp_rotate"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:spinnerMode="dialog" /></LinearLayout><CheckBoxandroid:id="@+id/ck_flip"android:layout_width="match_parent"android:layout_height="40dp"android:text="是否左右翻转图像"android:textColor="@color/black"android:textSize="17sp" /><com.example.picture.widget.BitmapViewandroid:id="@+id/bv_image"android:layout_width="match_parent"android:layout_height="200dp"android:background="@color/white" /><Buttonandroid:id="@+id/btn_save_image"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="保存图片"android:textColor="@color/black"android:textSize="17sp" /></LinearLayout>

创作不易 觉得有帮助请点赞关注收藏~~~

Android App开发之位图加工Bitmap中转换位图的像素色彩、裁剪内部区域、利用矩阵变换位图的讲解及实战(附源码和演示)相关推荐

  1. 【Android App】二维码的讲解及生成属于自己的二维码实战(附源码和演示 超详细必看)

    需要全部代码请点赞关注收藏后评论区留言~~~ 一.二维码基本内容介绍 条形码只能表达十几位数字编码,无法表示更复杂的数据. 二维码在二维方格上描出一个个黑点,从而表达更丰富的信息. 二维码早已在手机A ...

  2. Android App开发中OpenGL三维投影的讲解及实现(附源码和演示 简单易懂)

    运行有问题或需要源码请点赞关注收藏后评论区留言~~~ 一.三维投影 OpenGL,定义了跨语言跨平台的图形程序接口,对于Android开发者来说,OpenGL就是用来绘制三维图形的技术手段.当然Ope ...

  3. Android App开发实战项目之模仿美图秀秀的抠图工具(附源码和演示视频 简单易懂 可直接使用)

    需要图片集和源码请点赞关注收藏后评论区留言~~~ 所谓抠图神器,就是从一副图片中扣出用户想要的某块区域 一.需求描述 美图的修图功能如此强大,离不开专业的图片加工技术,抠图便是其中重要的一项功能.在A ...

  4. 【Android App】人脸识别中扫描识别二维码实战解析(附源码和演示 超详细)

    需要源码请点赞关注收藏后评论区留言私信~~~ 一.扫描识别二维码 不仅可以利用zxing库生成二维码,同样利用zxing库可以扫描二维码并解析得到原始文本,此时除了给build.gradle添加如下一 ...

  5. Android App开发实战项目之仿手机QQ动感影集动画播放(附源码和演示视频 可直接使用)

    需要图片集和源码请点赞关注收藏后评论区留言~~~ 动感影集就是只要用户添加一张图片,动感影集就能给每张图片渲染不同的动画效果,让原本静止的图片变得活泼起来,辅以各种精致的动画特效,营造一种赏心悦目的感 ...

  6. Android App开发实战项目之仿喜马拉雅的听说书App实现(超详细 附源码和演示视频)

    需要全部源码请点赞关注收藏后评论区留下QQ~~~ 一.需求分析 用户不仅能在平台上收听音频,还能成为内容创作者,总之长音频分享平台需要满足两种角色的使用:一种是作为内容创作者发布自己的音频,另一种是作 ...

  7. Android App开发实战项目之大头贴App功能实现(附源码和演示 简单易上手)

    需要图片集和源码请点赞关注收藏后评论区留言~~~ 一.需求描述 大头贴App有两个特征,第一个是头要大,拿来一张照片后把人像区域裁剪出来,这样新图片里的人头才会比较大,第二个是在周围贴上装饰物,而且装 ...

  8. 【Android App】人脸识别中使用Opencv比较两张人脸相似程度实战(附源码和演示 超详细)

    需要全部代码请点赞关注收藏后评论区留言私信~~~ 一.比较两张人脸的相似程度 直方图由一排纵向的竖条或者竖线组成,横轴代表数据类型,纵轴代表数据多少. 图像直方图经常应用于特征提取.图像匹配等方面. ...

  9. 【Android App】人脸识别中借助摄像头和OpenCV实时检测人脸讲解及实战(附源码和演示 超详细)

    需要全部代码请点赞关注收藏后评论区留言私信~~~ 一.借助摄像头实时检测人脸 与Android自带的人脸检测器相比,OpenCV具备更强劲的人脸识别功能,它可以通过摄像头实时检测人脸,实时检测的预览空 ...

最新文章

  1. java catch 空指针异常_关于Java:捕获空指针异常
  2. [vue] SSR解决了什么问题?有做过SSR吗?你是怎么做的?
  3. 福建省计算机中职类高考400分多少名,重要参考!福建高职分类各院校近两年招生计划及分数线汇总来了,快收藏...
  4. Python 批量重命名文件
  5. 制作linux镜像时哪些文件时必须打包的,如何将linux系统制作成iso镜像文件?通过Mondo Rescue工具将linux系统制作成ISO镜像...
  6. 计算机中丢失了gdiplus.dll,解决 “计算机中丢失gdiplus.dll”
  7. 善领dsa android正式版,善领dsa_善领dsa安卓版_善领dsa2016最新版p57
  8. 第一篇:手把手教你移植任天堂,没有声音、无需外置SD卡、可使用独立按键也可使用外置手柄,本人使用的芯片为ESP32,移植到STM32均可使用。(本篇主要介绍nes_main.h这个文件)
  9. 3dmax外挂神器更新了|3dmax外挂在过去几年里,食住玩都更新记录了3dmax外挂的什么功能?
  10. 海淘尺码表,贡献给论坛买衣服裤子鞋子的朋友
  11. POJ 1201 Intervals(差分约束)
  12. nested exception is java.lang.NumberFormatException: For input string: NaN
  13. 全球及中国图书出版发行业营销策略与运行前景分析报告2022版
  14. 给你一个字符串,删除其中的不是英文字母的符号,也就是说除了英文字母之外的字符都应该删除,请你输出删除后的字符串。
  15. VLIW的前世今生:为什么DL加速器都青睐于它
  16. 西餐餐饮文化、简单鸡尾酒调制~~DIY的力量无穷
  17. 英语中容易混淆的单词发音: 一
  18. 斐讯路由器宽带运营商服务器,新版斐讯p.to路由器的设置教程
  19. Android手机平板根目录详解
  20. 计算机网络笔试面试题目大全

热门文章

  1. STM32 SPI TX FIFO处理
  2. element is not attached to the page document报错解决办法
  3. GZIP文件格式简介
  4. PyTorch运行加载数据后占有大量C盘空间如何释放
  5. From line 6, column 36 to line 6, column 71: Cannot apply ‘-‘ to arguments of type ‘<VARCHAR(214748
  6. 小学计算机基础知识汇总,电脑基础知识:内存条知识大全,看完小学生都了解...
  7. Jolla 超额完成开源平板电脑众筹
  8. Arndale Octa 5420网络设置
  9. Python-爬取今日头条美图
  10. 天才学生的天才回答(爆笑)