[Android] 通过Menu实现图片怀旧、浮雕、模糊、光照和素描效果

2023-11-04

    由于随手拍项目想做成类似于美图秀秀那种底部有一排Menu实现不同效果的功能,这里先简单介绍如何通过Menu实现打开相册中的图片、怀旧效果、浮雕效果、光照效果和素描效果.后面可能会讲述如何通过PopupWindow实现自定义的Menu效果.
    希望文章对大家有所帮助,如果有错误或不足之处请海涵~

一. Menu效果展示

   Android手机上有个Menu按键,点击他会弹出一个菜单,通常在屏幕底部或右上角,在选项菜单OptionsMenu中最多显示2排每排3个菜单项,可以包含自定义的图片和文字.如果Menu菜单项多于6项时,第6项(Expanded Menus,扩展菜单)会变成More,点击它会显示后面所隐藏的所有选项.
   
下面讲述如何在Android 4.0项目中实现简单的Menu功能.添加如下代码:
@Override
public boolean onCreateOptionsMenu(Menu menu) { //创建Menu
	//自定义menu 添加图标(使用自带图标)
	menu.add(Menu.NONE, Menu.FIRST + 1 , 1, "打开").
		setIcon(android.R.drawable.ic_menu_slideshow);
	menu.add(Menu.NONE, Menu.FIRST + 2 , 2, "怀旧").
		setIcon(android.R.drawable.ic_menu_edit);
	menu.add(Menu.NONE, Menu.FIRST + 3 , 3, "浮雕").
		setIcon(android.R.drawable.ic_menu_gallery);
	menu.add(Menu.NONE, Menu.FIRST + 4 , 4, "模糊").
		setIcon(android.R.drawable.ic_menu_crop);
	menu.add(Menu.NONE, Menu.FIRST + 5 , 5, "光照").
		setIcon(android.R.drawable.ic_menu_camera);
	menu.add(Menu.NONE, Menu.FIRST + 6  , 6, "锐化").
		setIcon(android.R.drawable.ic_menu_view);
    return true;
}
   由于Android 4.0系统缺省UI风格有所变化,所以需要设置Activity的theme为Theme.Light.同时也可以在res/menu/main.xml设置菜单项.参考"恺风"博主关于Menu的介绍,非常不错.http://blog.csdn.net/flowingflying/article/details/11967301
<activity
    android:name="com.example.menushowimage.MainActivity"
    android:label="@string/app_name" 
    android:theme="@android:style/Theme.Light" >
   下图是设置前面的显示Menu不同效果,同时我调用的图标都是Android自带的图片,用户也可以自定义.(android默认图标列表)
                                        
    同时设置XML格式显示图片:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.touchimagetest.MainActivity"
    tools:ignore="MergeRootFrame" >
    <!-- 顶部添加文字 -->
    <RelativeLayout
        android:id="@+id/Layout_top"
        android:orientation="horizontal" 
        android:layout_width="fill_parent"
        android:layout_height="25dp"
        android:layout_alignParentTop="true"
        android:gravity="center">
         <TextView  
            android:id="@+id/textView1"  
            android:layout_width="wrap_content"  
            android:layout_height="wrap_content"  
            android:textSize="20sp"  
            android:text="请点击menu处理图片" />  
	</RelativeLayout>
    <!-- 底部显示图片 -->
    <RelativeLayout
        android:id="@+id/Layout_bottom" 
        android:orientation="horizontal"
        android:layout_below="@id/Layout_top" 
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content"
        android:background="#EFDFDF"
        android:gravity="center">
        <ImageView
	        android:id="@+id/imageView1"
	        android:layout_width="fill_parent"
	        android:layout_height="fill_parent"
	        android:layout_gravity="center_horizontal" />
    </RelativeLayout>
</RelativeLayout>

二. Menu实现打开图片

   然后通过onOptionsItemSelected(MenuItem item)实现选择图片,通过调用自定义函数实现各种功能.
@Override
public boolean onOptionsItemSelected(MenuItem item) { //选择Menu
	//选择id 对应Menu.add的参数Menu.FIRST+i
    int id = item.getItemId();
    switch(id) {
    case Menu.FIRST+1: 
    	Toast.makeText(this, "打开图片", Toast.LENGTH_SHORT).show();
    	OpenImage();
    	break;
    case Menu.FIRST+2: 
    	Toast.makeText(this, "图片怀旧效果", Toast.LENGTH_SHORT).show();
    	OldRemeberImage();
    	break;
    case Menu.FIRST+3: 
    	Toast.makeText(this, "图片浮雕效果", Toast.LENGTH_SHORT).show();
    	ReliefImage();
    	break;
    case Menu.FIRST+4: 
    	Toast.makeText(this, "图片模糊效果", Toast.LENGTH_SHORT).show();
    	FuzzyImage();
    	break;
    case Menu.FIRST+5: 
    	Toast.makeText(this, "图片光照效果", Toast.LENGTH_SHORT).show();
    	SunshineImage();
    	break;
    case Menu.FIRST+6: 
    	Toast.makeText(this, "图片锐化效果", Toast.LENGTH_SHORT).show();
    	SharpenImage();
    	break;
    }
    
    return super.onOptionsItemSelected(item);
}
   其中打开图片函数实现方法如下,而上面的很多自定义函数都将在第三部分介绍,你此处可以注释掉只验证"打开图片".首先添加自定义变量和获取ImageView布局.
//自定义变量
private ImageView imageShow;           //显示图片  
private Bitmap bmp;                    //原始图片  
private final int IMAGE_OPEN = 0;      //打开图片 
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    imageShow = (ImageView) findViewById(R.id.imageView1); 
    if (savedInstanceState == null) {
        getFragmentManager().beginTransaction()
                .add(R.id.container, new PlaceholderFragment())
                .commit();
    }
}
    然后通过自定义函数OpenImage打开函数,与前面文章介绍的方法一样.
//自定义函数 打开图片
public void OpenImage()
{
	Intent intent = new Intent(Intent.ACTION_PICK,   
            android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);  
    startActivityForResult(intent, IMAGE_OPEN);
}
//显示打开图片
protected void onActivityResult(int requestCode, int resultCode, Intent data) {   
    super.onActivityResult(requestCode, resultCode, data);    
    if(resultCode==RESULT_OK && requestCode==IMAGE_OPEN) {    
       Uri imageFileUri = data.getData();  
       DisplayMetrics dm = new DisplayMetrics();  
       getWindowManager().getDefaultDisplay().getMetrics(dm);    
       int width = dm.widthPixels;    //手机屏幕水平分辨率     
       int height = dm.heightPixels;  //手机屏幕垂直分辨率  
       try {    
           //载入图片尺寸大小没载入图片本身 true  
           BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();    
           bmpFactoryOptions.inJustDecodeBounds = true;    
           bmp = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageFileUri), null, bmpFactoryOptions);    
           int heightRatio = (int)Math.ceil(bmpFactoryOptions.outHeight/(float)height);    
           int widthRatio = (int)Math.ceil(bmpFactoryOptions.outWidth/(float)width);      
           //inSampleSize表示图片占原图比例 1表示原图  
           if(heightRatio>1&&widthRatio>1) {    
               if(heightRatio>widthRatio) {    
                   bmpFactoryOptions.inSampleSize = heightRatio;    
               }    
               else {    
                   bmpFactoryOptions.inSampleSize = widthRatio;    
               }    
           }                     
           //图像真正解码 false  
           bmpFactoryOptions.inJustDecodeBounds = false;                   
           bmp = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageFileUri), null, bmpFactoryOptions);      
           imageShow.setImageBitmap(bmp);  
       }  
       catch(FileNotFoundException e) {   
           e.printStackTrace();    
       }   
   }  //end if  
}  
    下面讲讲使用Options Menu的函数:
   onCreateOptionsMenu(Menu menu)创建options menu,这个函数只会在menu第一次显示时调用.
    onOptionsItemSelected(MenuItem item)
处理选中的菜单项.
    在通过menu.add函数实现添加菜单项,如menu.add(Menu.NONE,Menu.FIRST+1,1,"打开"),第一个参数表示组别;第二个参数menu标志编号与onOptionsItemSelected函数中值对应;第三个参数是在菜单中出现的顺序,顺序由小到大,由左至右;第四个参数是显示的文字,同时setIcon可以设置图标.
 

三. 图像各种效果实现

    最后讲讲各个效果实现过程,通过不同自定义函数实现.其中各个效果主要参照《Android图像处理总结》那篇文章和eoeAndroid社区亚瑟的文章.
    书籍下载地址:

1.图片怀旧效果
//图片怀旧处理
private void OldRemeberImage()
{
	/*
	 * 怀旧处理算法即设置新的RGB
	 * R=0.393r+0.769g+0.189b
	 * G=0.349r+0.686g+0.168b
	 * B=0.272r+0.534g+0.131b
	 */
	int width = bmp.getWidth();
	int height = bmp.getHeight();
	Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
	int pixColor = 0;
	int pixR = 0;
	int pixG = 0;
	int pixB = 0;
	int newR = 0;
	int newG = 0;
	int newB = 0;
	int[] pixels = new int[width * height];
	bmp.getPixels(pixels, 0, width, 0, 0, width, height);
	for (int i = 0; i < height; i++)
	{
		for (int k = 0; k < width; k++)
		{
			pixColor = pixels[width * i + k];
			pixR = Color.red(pixColor);
			pixG = Color.green(pixColor);
			pixB = Color.blue(pixColor);
			newR = (int) (0.393 * pixR + 0.769 * pixG + 0.189 * pixB);
			newG = (int) (0.349 * pixR + 0.686 * pixG + 0.168 * pixB);
			newB = (int) (0.272 * pixR + 0.534 * pixG + 0.131 * pixB);
			int newColor = Color.argb(255, newR > 255 ? 255 : newR, newG > 255 ? 255 : newG, newB > 255 ? 255 : newB);
			pixels[width * i + k] = newColor;
		}
	}
	bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
	imageShow.setImageBitmap(bitmap);
}
    显示效果如下图所示:
                     
2.图片浮雕效果
//图片浮雕处理
//底片效果也非常简单:将当前像素点的RGB值分别与255之差后的值作为当前点的RGB
//灰度图像:通常使用的方法是gray=0.3*pixR+0.59*pixG+0.11*pixB
private void ReliefImage()
{
	/*
	 * 算法原理:(前一个像素点RGB-当前像素点RGB+127)作为当前像素点RGB值
	 * 在ABC中计算B点浮雕效果(RGB值在0~255)
	 * B.r = C.r - B.r + 127
	 * B.g = C.g - B.g + 127
	 * B.b = C.b - B.b + 127
	 */
	int width = bmp.getWidth();
	int height = bmp.getHeight();
	Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
	int pixColor = 0;
	int pixR = 0;
	int pixG = 0;
	int pixB = 0;
	int newR = 0;
	int newG = 0;
	int newB = 0;
	int[] pixels = new int[width * height];
	bmp.getPixels(pixels, 0, width, 0, 0, width, height);
	for (int i = 1; i < height-1; i++)
	{
		for (int k = 1; k < width-1; k++)
		{
			//获取前一个像素颜色
			pixColor = pixels[width * i + k];   
			pixR = Color.red(pixColor);
			pixG = Color.green(pixColor);
			pixB = Color.blue(pixColor);
			//获取当前像素
			pixColor = pixels[(width * i + k) + 1];
			newR = Color.red(pixColor) - pixR +127;
			newG = Color.green(pixColor) - pixG +127;
			newB = Color.blue(pixColor) - pixB +127;
			newR = Math.min(255, Math.max(0, newR));
			newG = Math.min(255, Math.max(0, newG));
			newB = Math.min(255, Math.max(0, newB));
			pixels[width * i + k] = Color.argb(255, newR, newG, newB);
		}
	}
	bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
	imageShow.setImageBitmap(bitmap);
}
   显示效果如下图所示:
  

3.图像模糊效果
//图像模糊处理
private void FuzzyImage()
{
	/*
	 * 算法原理:
	 * 简单算法将像素周围八个点包括自身共九个点RGB值分别相加后平均,当前像素点的RGB值
	 * 复杂算法采用高斯模糊
	 * 高斯矩阵 int[] gauss = new int[] { 1, 2, 1, 2, 4, 2, 1, 2, 1 };
	 * 将九个点的RGB值分别与高斯矩阵中的对应项相乘的和,再除以一个相应的值作为当前像素点的RGB
	 */
    int[] gauss = new int[] { 1, 2, 1, 2, 4, 2, 1, 2, 1 };  // 高斯矩阵
    int delta = 16; // 除以值 值越小图片会越亮,越大则越暗
	int width = bmp.getWidth();
	int height = bmp.getHeight();
	Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
	int pixColor = 0;
	int pixR = 0; 
    int pixG = 0; 
    int pixB = 0; 
	int newR, newG, newB;
	int pos = 0;    //位置
	int[] pixels = new int[width * height]; 
    bmp.getPixels(pixels, 0, width, 0, 0, width, height); 
	//循环赋值
	for (int i = 1; i < height-1; i++)
	{
		for (int k = 1; k < width-1; k++)
		{
			pos = 0;
			newR = 0; 
            newG = 0; 
            newB = 0; 
			for (int m = -1; m <= 1; m++)  //宽不变
            { 
                for (int n = -1; n <= 1; n++) //高先变
                { 
                    pixColor = pixels[(i + m) * width + k + n]; 
                    pixR = Color.red(pixColor); 
                    pixG = Color.green(pixColor); 
                    pixB = Color.blue(pixColor); 
                    //3*3像素相加
                    newR = newR + (int) (pixR * gauss[pos]); 
                    newG = newG + (int) (pixG * gauss[pos]); 
                    newB = newB + (int) (pixB * gauss[pos]); 
                    pos++; 
                } 
            } 			
			newR /= delta; 
            newG /= delta; 
            newB /= delta; 
            newR = Math.min(255, Math.max(0, newR)); 
            newG = Math.min(255, Math.max(0, newG)); 
            newB = Math.min(255, Math.max(0, newB));      
            pixels[i * width + k] = Color.argb(255, newR, newG, newB);  
		}
	}
	bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
	imageShow.setImageBitmap(bitmap);
}
    该图显示效果不是很理想,对高斯模糊理解还不够,建议大家看我收藏合集里面讲述模糊的超链接.

4.图像光照效果
//图片光照效果
private void SunshineImage()
{
	/*
	 * 算法原理:(前一个像素点RGB-当前像素点RGB+127)作为当前像素点RGB值
	 * 在ABC中计算B点浮雕效果(RGB值在0~255)
	 * B.r = C.r - B.r + 127
	 * B.g = C.g - B.g + 127
	 * B.b = C.b - B.b + 127
	 * 光照中心取长宽较小值为半径,也可以自定义从左上角射过来
	 */		
	int width = bmp.getWidth();
	int height = bmp.getHeight();
	Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
	int pixColor = 0;
	int pixR = 0;
	int pixG = 0;
	int pixB = 0;
	int newR = 0;
	int newG = 0;
	int newB = 0;
	//围绕圆形光照
	int centerX = width / 2;
	int centerY = height / 2;
	int radius = Math.min(centerX, centerY);
	float strength = 150F;  //光照强度100-150
	int[] pixels = new int[width * height];
	bmp.getPixels(pixels, 0, width, 0, 0, width, height);
	for (int i = 1; i < height-1; i++)
	{
		for (int k = 1; k < width-1; k++)
		{
			//获取前一个像素颜色
			pixColor = pixels[width * i + k];   
			pixR = Color.red(pixColor);
			pixG = Color.green(pixColor);
			pixB = Color.blue(pixColor);
			newR = pixR;
			newG = pixG;
			newB = pixB;
			//计算当前点到光照中心的距离,平面坐标系中两点之间的距离
			int distance = (int) (Math.pow((centerY-i), 2) + Math.pow((centerX-k), 2));
			if(distance < radius*radius)
			{
				//按照距离大小计算增强的光照值
				int result = (int)(strength*( 1.0-Math.sqrt(distance) / radius ));
				newR = pixR + result;
				newG = newG + result;
				newB = pixB + result;
			}
			newR = Math.min(255, Math.max(0, newR));
			newG = Math.min(255, Math.max(0, newG));
			newB = Math.min(255, Math.max(0, newB));
			pixels[width * i + k] = Color.argb(255, newR, newG, newB);
		}
	}
	bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
	imageShow.setImageBitmap(bitmap);
}
    显示效果如下图所示 
                                                           
5.图片锐化效果
    本打算采用拉普拉斯算子或Sobel算子对图像进行锐化,在使用C++对24位bmp图像处理时能非常好的显示图像的轮廓,但是Android总是效果不是很好啊,而且有虚线!网上一些锐化效果完全没有实现显示图像轮廓,与原图区别不大,感觉是错误的方法.研究ing
//图像锐化处理 拉普拉斯算子处理
private void SharpenImage()
{
	/*
	 * 锐化基本思想是加强图像中景物的边缘和轮廓,使图像变得清晰
	 * 而图像平滑是使图像中边界和轮廓变得模糊
	 * 
	 * 拉普拉斯算子图像锐化
	 * 获取周围9个点的矩阵乘以模板9个的矩阵 卷积
	 */
	//拉普拉斯算子模板 { 0, -1, 0, -1, -5, -1, 0, -1, 0 } { -1, -1, -1, -1, 9, -1, -1, -1, -1 }
	int[] laplacian = new int[] {  -1, -1, -1, -1, 9, -1, -1, -1, -1 }; 
	int width = bmp.getWidth();  
    int height = bmp.getHeight();  
    Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);  
    int pixR = 0;  
    int pixG = 0;  
    int pixB = 0;  
    int pixColor = 0;  
    int newR = 0;  
    int newG = 0;  
    int newB = 0;  
    int idx = 0;  
    float alpha = 0.3F;  //图片透明度
    int[] pixels = new int[width * height];  
    bmp.getPixels(pixels, 0, width, 0, 0, width, height);  
    //图像处理
    for (int i = 1; i < height - 1; i++)  
    {  
        for (int k = 1; k < width - 1; k++)  
        {  
        	idx = 0;
        	newR = 0;  
            newG = 0;  
            newB = 0;  
            for (int n = -1; n <= 1; n++)   //取出图像3*3领域像素 
            {  
                for (int m = -1; m <= 1; m++)  //n行数不变 m列变换
                {  
                    pixColor = pixels[(i + n) * width + k + m];  //当前点(i,k)
                    pixR = Color.red(pixColor);  
                    pixG = Color.green(pixColor);  
                    pixB = Color.blue(pixColor);  
                    //图像像素与对应摸板相乘   
                    newR = newR + (int) (pixR * laplacian[idx] * alpha);  
                    newG = newG + (int) (pixG * laplacian[idx] * alpha);  
                    newB = newB + (int) (pixB * laplacian[idx] * alpha);  
                    idx++; 
                }  
            }
            newR = Math.min(255, Math.max(0, newR));  
            newG = Math.min(255, Math.max(0, newG));  
            newB = Math.min(255, Math.max(0, newB));  
            //赋值  
            pixels[i * width + k] = Color.argb(255, newR, newG, newB);   
        }
    }
    bitmap.setPixels(pixels, 0, width, 0, 0, width, height);  
    imageShow.setImageBitmap(bitmap);
}

   作图是其显示效果,而右图是我以前《数字图像处理》课用C++写的不同模版的锐化效果.

 

 


    下面再介绍些效果,下面这个效果是参考亚瑟BOY的冰冻效果.
    源代码地址:http://www.eoeandroid.com/thread-176490-1-1.html

//图片冰冻效果
private void IceImage()
{
	int width = bmp.getWidth();
	int height = bmp.getHeight();
	Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
	int pixColor = 0;
	int pixR = 0;
	int pixG = 0;
	int pixB = 0;
	int newColor = 0;
	int newR = 0;
	int newG = 0;
	int newB =0;
	int[] pixels = new int[width * height];
	bmp.getPixels(pixels, 0, width, 0, 0, width, height);
	for (int i = 0; i < height; i++)
	{
		for (int k = 0; k < width; k++)
		{
			//获取前一个像素颜色
			pixColor = pixels[width * i + k];   
			pixR = Color.red(pixColor);
			pixG = Color.green(pixColor);
			pixB = Color.blue(pixColor);
			//红色
			newColor = pixR - pixG - pixB;
			newColor = newColor * 3 / 2;
			if(newColor < 0) {
				newColor = -newColor;
			}
			if(newColor >255) {
				newColor = 255;
			}
			newR = newColor;
			//绿色
			newColor = pixG - pixB - pixR;
			newColor = newColor * 3 / 2;
			if(newColor < 0) {
				newColor = -newColor;
			}
			if(newColor >255) {
				newColor = 255;
			}
			newG = newColor;
			//蓝色
			newColor = pixB - pixG - pixR;
			newColor = newColor * 3 / 2;
			if(newColor < 0) {
				newColor = -newColor;
			}
			if(newColor >255) {
				newColor = 255;
			}
			newB = newColor;
			pixels[width * i + k] = Color.argb(255, newR, newG, newB);
		}
	}
	bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
	imageShow.setImageBitmap(bitmap);
}
    下面这个代码是CSDN的xu_fu博主的素描处理,对我软件有用.
    源代码地址:http://blog.csdn.net/xu_fu/article/details/21485461

       效果显示如下图所示,在Menu选择中调用函数IceImage或SuMiaoImage即可实现.
              

        

//素描效果
private void SuMiaoImage()
{
	//创建新Bitmap
	int width = bmp.getWidth();  
    int height = bmp.getHeight();  
    int[] pixels = new int[width * height];    //存储变换图像
    int[] linpix = new int[width * height];     //存储灰度图像
    Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);  
    bmp.getPixels(pixels, 0, width, 0, 0, width, height);
    int pixColor = 0;
	int pixR = 0;
	int pixG = 0;
	int pixB = 0;
    int newR = 0;  
    int newG = 0;  
    int newB = 0;
    //灰度图像
    for (int i = 1; i < width - 1; i++)  
    {  
        for (int j = 1; j < height - 1; j++)   //拉普拉斯算子模板 { 0, -1, 0, -1, -5, -1, 0, -1, 0 
        {  
        	//获取前一个像素颜色
			pixColor = pixels[width * i + j];   
			pixR = Color.red(pixColor);
			pixG = Color.green(pixColor);
			pixB = Color.blue(pixColor);
        	//灰度图像
        	int gray=(int)(0.3*pixR+0.59*pixG+0.11*pixB);
        	linpix[width * i + j] = Color.argb(255, gray, gray, gray);
        	//图像反向
        	gray=255-gray;
        	pixels[width * i + j] = Color.argb(255, gray, gray, gray);
        }
    }
    int radius = Math.min(width/2, height/2);
    int[] copixels = gaussBlur(pixels, width, height, 10, 10/3);   //高斯模糊 采用半径10
    int[] result = colorDodge(linpix, copixels);   //素描图像 颜色减淡
    bitmap.setPixels(result, 0, width, 0, 0, width, height);
    imageShow.setImageBitmap(bitmap);
}

//高斯模糊
public static int[] gaussBlur(int[] data, int width, int height, int radius,  
        float sigma) {  
  
    float pa = (float) (1 / (Math.sqrt(2 * Math.PI) * sigma));  
    float pb = -1.0f / (2 * sigma * sigma);  
  
    // generate the Gauss Matrix   
    float[] gaussMatrix = new float[radius * 2 + 1];  
    float gaussSum = 0f;  
    for (int i = 0, x = -radius; x <= radius; ++x, ++i) {  
        float g = (float) (pa * Math.exp(pb * x * x));  
        gaussMatrix[i] = g;  
        gaussSum += g;  
    }  
  
    for (int i = 0, length = gaussMatrix.length; i < length; ++i) {  
        gaussMatrix[i] /= gaussSum;  
    }  
  
    // x direction   
    for (int y = 0; y < height; ++y) {  
        for (int x = 0; x < width; ++x) {  
            float r = 0, g = 0, b = 0;  
            gaussSum = 0;  
            for (int j = -radius; j <= radius; ++j) {  
                int k = x + j;  
                if (k >= 0 && k < width) {  
                    int index = y * width + k;  
                    int color = data[index];  
                    int cr = (color & 0x00ff0000) >> 16;  
                    int cg = (color & 0x0000ff00) >> 8;  
                    int cb = (color & 0x000000ff);  
  
                    r += cr * gaussMatrix[j + radius];  
                    g += cg * gaussMatrix[j + radius];  
                    b += cb * gaussMatrix[j + radius];  
  
                    gaussSum += gaussMatrix[j + radius];  
                }  
            }  
  
            int index = y * width + x;  
            int cr = (int) (r / gaussSum);  
            int cg = (int) (g / gaussSum);  
            int cb = (int) (b / gaussSum);  
              
            data[index] = cr << 16 | cg << 8 | cb | 0xff000000;  
        }  
    }  
  
    // y direction   
    for (int x = 0; x < width; ++x) {  
        for (int y = 0; y < height; ++y) {  
            float r = 0, g = 0, b = 0;  
            gaussSum = 0;  
            for (int j = -radius; j <= radius; ++j) {  
                int k = y + j;  
                if (k >= 0 && k < height) {  
                    int index = k * width + x;  
                    int color = data[index];  
                    int cr = (color & 0x00ff0000) >> 16;  
                    int cg = (color & 0x0000ff00) >> 8;  
                    int cb = (color & 0x000000ff);  
  
                    r += cr * gaussMatrix[j + radius];  
                    g += cg * gaussMatrix[j + radius];  
                    b += cb * gaussMatrix[j + radius];  
  
                    gaussSum += gaussMatrix[j + radius];  
                }  
            }  
  
            int index = y * width + x;  
            int cr = (int) (r / gaussSum);  
            int cg = (int) (g / gaussSum);  
            int cb = (int) (b / gaussSum);  
            data[index] = cr << 16 | cg << 8 | cb | 0xff000000;  
        }  
    }  
    
    return data;
}  

//颜色减淡
public static int[] colorDodge(int[] baseColor, int[] mixColor) {  
	  
    for (int i = 0, length = baseColor.length; i < length; ++i) {  
        int bColor = baseColor[i];  
        int br = (bColor & 0x00ff0000) >> 16;  
        int bg = (bColor & 0x0000ff00) >> 8;  
        int bb = (bColor & 0x000000ff);  
  
        int mColor = mixColor[i];  
        int mr = (mColor & 0x00ff0000) >> 16;  
        int mg = (mColor & 0x0000ff00) >> 8;  
        int mb = (mColor & 0x000000ff);  
  
        int nr = colorDodgeFormular(br, mr);  
        int ng = colorDodgeFormular(bg, mg);  
        int nb = colorDodgeFormular(bb, mb);  
  
        baseColor[i] = nr << 16 | ng << 8 | nb | 0xff000000;  
    }  
    return baseColor;
}  
  
private static int colorDodgeFormular(int base, int mix) {  
      
    int result = base + (base * mix) / (255 - mix);  
    result = result > 255 ? 255 : result;  
    return result;  
      
}
    最后希望文章对大家有所帮助,感谢上面提到的作者,同时可能还有些如LOMO等效果可参考下面的文章,它是图像处理的一个集合超链接.后面会写PopupWindows实现美图秀秀的效果和对人脸进行处理.
    源代码下载:
    (By:Eastmount 2014-11-2 晚8点 http://blog.csdn.net/eastmount/)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

[Android] 通过Menu实现图片怀旧、浮雕、模糊、光照和素描效果 的相关文章

  • 没有这样的属性:类的 useLibrary

    我的项目在Android Studio上使用ndk 所以 build gradle如下 dependencies classpath com android tools build gradle experimental 0 4 0 app
  • MediaPlayer 大约 5 秒后停止播放

    我目前正在开发一个简单的游戏 现在是时候添加音乐和音效了 我尝试使用MediaPlayer 就像这里描述的那样 Android 媒体播放器错误 https stackoverflow com questions 5219722 androi
  • Android:检查是否必须询问运行时权限

    我想检查特定应用程序是否需要在运行时处理 Android Marshmallow 运行时权限 下面的假设正确吗 Checks whether runtime permissions must be handled or not param
  • 如何在android中将时间转换为“时间之前”

    我的服务器 返回时间 2016 01 24T16 00 00 000Z I want 1 转换为字符串 2 我希望它在从服务器加载时显示 不久前 请 帮我 我认为主要有三种方式 a 内置选项使用SimpleDateFormat and 日期
  • android 弹出菜单文本颜色(AppCompat)

    我需要更改 popuo 菜单的文本颜色 但我找不到任何方法来执行此操作 我可以更改 popomenu 的背景但不能更改文本 我以这种方式编辑 style xml
  • android 4 中的 android RadioButton 问题

    我有一个简单的应用程序 屏幕是在相对布局内构建的 我还有 LinearLayout s 其中之一显示 2 个 RadioButton s 如下所示
  • React Native fetch() 在 Android 7 上抛出“网络请求失败”,但在 Android 6 上工作正常

    我已经发现 question https stackoverflow com questions 45144938 react native android fetch for https returns network request f
  • 如何监听自定义 URI

    我正在开发一个有自己的 URI 前缀的应用程序 在本例中为 dchub 到处搜索并阅读了很多 但我有点困惑 当有人点击以以下开头的链接时 是否可以启动我的应用程序dchub 在浏览器中 到目前为止 找到了很多从应用程序打开浏览器的其他示例
  • getRunningAppProcesses 在 Android L (5.1.1) 上返回空列表 [重复]

    这个问题在这里已经有答案了 我刚刚测试了我的应用程序和 CM ATM Android Assistant 等 它们都无法获取正在运行的进程列表 但它们在预操作系统版本上运行良好 那么 Android L 5 1 1 发生了什么 请帮忙 am
  • Recycler查看可见项目的数量

    我正在我的应用程序中创建一个水平 RecyclerView 它必须一次在屏幕上显示 2 个图像 因此每个图像的宽度必须为屏幕的 50 目前它工作正常 但每个项目都会占用屏幕的所有宽度 这是我的代码 mRecyclerView Recycle
  • Firebase 实时数据库 .info/connected 本应为 True 时为 False

    我有一个 Android 服务 它的调用地址为onCreate FirebaseDatabase database FirebaseDatabase getInstance database getReference info connec
  • 使用 JWT 创建 Firebase 自定义身份验证令牌

    为了创建 firebase 自定义身份验证令牌 我使用第三方 JWT 库 https github com jwtk jjwt https github com jwtk jjwt 在此库中 有一个选项可以添加 firebase 自定义令牌
  • VideoView中的seekTo

    我在寻找视频时遇到问题 我的应用程序应该从上次停止的位置恢复视频 所以我这样做 videoView seekTo bookmark videoView start 然而 当它播放时 我听到视频开头的声音大约 1 2 秒 只有在该视频寻找到正
  • 在不同的活动上显示 OnItemClickListener 的结果

    我使用 OnItemClickListener 从列表视图中选择一个项目 如下所示 listView setTextFilterEnabled true final TextView disp TextView findViewById R
  • 在 Android 应用程序中使用传单来显示在线地图

    是否有任何示例项目展示如何正确使用传单在 Android 应用程序中显示在线地图 因为我尝试了很多示例 但每次我的应用程序中都有一个空的网络视图 这是我的代码 private WebView mWebView Override protec
  • 回购:找不到命令?

    我是 git 和 repo 的新手 我使用的是window 7 所以我使用cygwin 我已经从 cygwin 安装程序安装了 git 之后我尝试在 cygwin 中使用以下命令进行存储 repo init u git android gi
  • 如何在不打开浏览器的情况下查看 Android 应用程序中的网页?

    嘿 我正在开发一个 Android 应用程序 我想连接到该应用程序内的网络 不过 我在某种程度上尝试过 WebView 但它在我的目录中显示的文件很好 但当连接到 google com 时 它显示错误 然后我添加了这个文件
  • 启动 Activity 时自动弹出键盘

    我有一个相对简单的问题 我有一个包含很多 EditText 的活动 当我打开活动时 它会自动聚焦到第一个 EditText 并显示虚拟键盘 我怎样才能防止这种情况发生 在 XML 文件的布局标签中使用此属性 android focusabl
  • 无法放置双重 SharedPreferences

    出现错误 这种类型的共享首选项编辑器的 put double 方法未定义 Eclipse 提供了一种快速修复方法 将强制类型转换添加到编辑器 但是当我这样做时 它仍然给出错误 为什么我不能 put double 代码 Override pr
  • Android:如何实现“分布式控制”

    对于与 Android 开发者论坛的交叉发帖表示歉意 那里没有收到任何答复 我有一个有趣的设计挑战 我有一个前端 Activity 和一个后端 用本机 C C 编写 代码 后端是一个复杂的对象 它部分控制 应用程序流程一旦启动就在它自己的线

随机推荐

  • Imagination官方信息速递2023年8月期

    白皮书下载 通过Photon架构创建身临其境的图形体验 2023 年 Imagination 将基于 PowerVR Photon 架构的光加线速集群 RAC 的演进引入 IMG DXT 图形处理单元 GPU IMG DXT GPU 不仅通
  • 第十五节课 使用Samba或NFS实现文件共享及DNS域名解释服务

    这节课主要讲解了Samba文件共享服务和NFS网络文件系统配置及使用 autofs自动挂载服务 DNS域名解释服务及bind服务程序配置等
  • 测试:概念篇

    目录 简单介绍测试 我们先简单的介绍一下测试工程师 简单来看看测试和开发的区别 测试的基本概念 什么是需求 BUG 的概念 测试用例 什么是测试用例 为什么有测试用例 测试周期 开发模型 瀑布模型 螺旋模型 敏捷软件开发 V 模型 W 模型
  • java编码技巧

    判断某个集合是否包含某值 ArrayUtils contains Object array Object objectToFind 缓存 service层先判断缓存是否有此数据 有则返回该数据 没有则从数据库获取 并存入缓存 往插入数据以后
  • QEMU安装及测试

    QEMU README QEMU is a generic and open source machine userspace emulator and virtualizer QEMU官网链接 https www qemu org Git
  • EasyPoi导出Excel

    这几天一直在忙工作中的事情 在工作中有一个问题 可能是因为刚开始接触这个EasyPoi 对其也没有太多的理解 在项目中就使用了 有一个需求 是要导出项目中所有的表格 今天就对这个需求进行分析和实现吧 需求 导出项目中所有的表格 导出文件为E
  • osgFBO(九)多pass---2,pass2,shader将背景从红色变为绿色

    二 pass2是比较完整的 同时有输入纹理和输出纹理 与pass1类似 这里只列出不同的地方 1 pass2摄像机输入tex1 osg ref ptr
  • 火焰检测 数据集

    开源项目1 https github com gengyanlei fire smoke detect yolov4 tree master yolov5 有数据集 Pytorch YOLOV4 火焰目标检测 石头儿啊的博客 CSDN博客
  • SpringBoot接口实现视频在线播放

    获取所有的mp4在线播放地址 并当前端调用该接口时返回mp4视频文件名及其播放地址 mp4视频存放在D盘的video文件夹下 ApiOperation 获取所有MP4播放地址 GetMapping get video address pub
  • 1. Qt小游戏 --- 推箱子

    1 说明 这个小游戏主要使用Qt中的绘制事件函数 paintEvent 在画布上面不停的绘制图形 并使用定时器做时间上的触发处理 这个小游戏只是做了简单的逻辑处理 具体复杂的功能读者可自行发挥 效果展示如下 Qt制作推箱子小游戏 2 相关代
  • 正负压产生电路(9V,12V)

    正负压输出电路 开关电源知识储备 xl6007 电荷泵 原理图和PCB 开关电源知识储备 在dc dc拓扑中有着buck 降压 boost 升压 buck boost 升降压 其原理简单总结是 利用储能元件 如电容电感 对电流的释放进行控制
  • vue3.0--使用element-plus的$message

    前题已经按如上步骤安装了按需加载的element plus 项目中使用this message 使用成功了 import ElMessage from element plus components ElMessage ElMessage
  • Error setting null for parameter #2 with JdbcType OTHER

    mybatis执行时报错内容如下 Error setting null for parameter 2 with JdbcType OTHER Try setting a different JdbcType for this parame
  • atcoder ABC 128

    目录 B guidebook c switches D equeue B guidebook B Guidebook atcoder jp 多关键字排序 按主要关键字 次要关键字排序 用结构体存储主次要关键字 用sort排序 sort可以对
  • squid 高匿配置 用户名密码配置

    1 安装squidyum install squid2 修改配置文件 在 http access deny all 上面加上如下权限配置 注意 一定要在这句上面 用户名密码配置 auth param basic program usr li
  • openGL之API学习(五)光照

    基本的光照模型主要包括 环境光 漫反射 镜面反射 环境光是在晴天室外到处看到的光的类型 环境光也就被建模为一个没有光源 没有方向并且对场景中的所有物体产生相同的点亮效果的一种光 环境光在很多情况下会被尽量的避免去考虑 因为它看上去有点太人工
  • PlacingObjectsontheGlobe_译

    PlacingObjectsontheGlobe 译 已经创建了一个关卡并且输入一些像CesiumWorldTerrain或者一个城市的摄影测量模型真实世界资产 接下来你可能想要从标准UnrealEngine工具箱添加一些对象 格网 植物
  • 对Spring loC DI的理解

    文章转自https www cnblogs com Mr Rocker p 7721824 html 仅供个人学习所用 好东西当然要多多学习啊 学习过Spring框架的人一定都会听过Spring的IoC 控制反转 DI 依赖注入 这两个概念
  • 如何编写一个可变参数函数?如何让所有单片机的所有串口实现printf函数?

    前言 1 由于真的复习不下去 就想着写一篇博客拉回自己的心思 于是想到了长期有疑惑 但是一直没有进行深入了解的C语言可变参数函数 2 本人查阅了一些网上的资料 以及自己的理解写出来了这一片博客 首先再次感谢肯哥的答疑 3 借鉴文章 C51单
  • [Android] 通过Menu实现图片怀旧、浮雕、模糊、光照和素描效果

    由于随手拍项目想做成类似于美图秀秀那种底部有一排Menu实现不同效果的功能 这里先简单介绍如何通过Menu实现打开相册中的图片 怀旧效果 浮雕效果 光照效果和素描效果 后面可能会讲述如何通过PopupWindow实现自定义的Menu效果 希