治疗白癜风有那些偏方 http://baidianfeng.39.net/bdfby/yqyy/需求背景分析:
产品和美工给了个根据专辑封面取主题色做背景,并且专辑封面还要融入背景的效果图,一开始看到取色觉得简单啊,不就是之前看过的palette嘛,可是专辑封面渐变消失融入背景怎么做呢,我们一步步分析。
1.首先是背景取色,Palette这个比较简单,因为已经有现成的API让我们调用
Palette.from(bitmap).generate(newPalette.PaletteAsyncListener(){
OverridepublicvoidonGenerated(Palettepalette){//todo}}});palette可以获取到6种颜色,而且palette还有其他功能,这里就不介绍了,网上有很多案例,我们继续。
因为背景色是渐变的,由深变浅,所以要这里取出两个颜色通过paint的shader绘制一张渐变效果的bitmap,具体代码如下:
//......省略一些Palette.from(resource).generate(newPalette.PaletteAsyncListener(){
OverridepublicvoidonGenerated(Palettepalette){//记得判空if(palette==null)return;//palette取色不一定取得到某些特定的颜色,这里通过取多种颜色来避免取不到颜色的情况if(palette.getDarkVibrantColor(Color.TRANSPARENT)!=Color.TRANSPARENT){createLinearGradientBitmap(palette.getDarkVibrantColor(Color.TRANSPARENT),palette.getVibrantColor(Color.TRANSPARENT));}elseif(palette.getDarkMutedColor(Color.TRANSPARENT)!=Color.TRANSPARENT){createLinearGradientBitmap(palette.getDarkMutedColor(Color.TRANSPARENT),palette.getMutedColor(Color.TRANSPARENT));}else{createLinearGradientBitmap(palette.getLightMutedColor(Color.TRANSPARENT),palette.getLightVibrantColor(Color.TRANSPARENT));}}});//创建线性渐变背景色privatevoidcreateLinearGradientBitmap(intdarkColor,intcolor){intbgColors[]=newint[];bgColors[0]=darkColor;bgColors[1]=color;if(bgBitmap==null){bgBitmap=Bitmap.createBitmap(ivBg.getWidth(),ivBg.getHeight(),Bitmap.Config.ARGB_);}if(mCanvas==null){mCanvas=newCanvas();}if(mPaint==null){mPaint=newPaint();}mCanvas.setBitmap(bgBitmap);mCanvas.drawColor(Color.TRANSPARENT,PorterDuff.Mode.CLEAR);LinearGradientgradient=newLinearGradient(0,0,0,bgBitmap.getHeight(),bgColors[0],bgColors[1],Shader.TileMode.CLAMP);mPaint.setShader(gradient);RectFrectF=newRectF(0,0,bgBitmap.getWidth(),bgBitmap.getHeight());//mCanvas.drawRoundRect(rectF,16,16,mPaint);这个用来绘制圆角的哈mCanvas.drawRect(rectF,mPaint);ivBg.setImageBitmap(bgBitmap);}先给大家看看目前效果,免得枯燥
ok,目前背景色就实现到这了
.接着是最蛋疼的让他渐变融入到背景色中了
我目前有两种思路(两种我都用过了,推荐第二种)
思路优点缺点在图片上面叠加一层颜色渐变的图片方便简单,只需多加一个控件需要获取旁边背景色对应的颜色值,这个比较难,而且我目前才用的算法获得有时候不准确通过修改图片的透明度来达到渐变效果无需计算旁边颜色,最终效果较佳图片较大时,计算量比较大,速度较慢ok,由于我最后还是采用了第二种,这里就只介绍第二种方法了,思路很简单,就是获取图片的bitmap数组,通过遍历来判断修改相应的透明度,具体代码如下:
//修改透明度publicstaticBitmapgetImageToChange(BitmapmBitmap){Log.d(TAG,"with="+mBitmap.getWidth()+"--height="+mBitmap.getHeight());BitmapcreateBitmap=Bitmap.createBitmap(mBitmap.getWidth(),mBitmap.getHeight(),Bitmap.Config.ARGB_);intmWidth=mBitmap.getWidth();intmHeight=mBitmap.getHeight();for(inti=0;imHeight;i++){for(intj=0;jmWidth;j++){intcolor=mBitmap.getPixel(j,i);intg=Color.green(color);intr=Color.red(color);intb=Color.blue(color);inta=Color.alpha(color);floatindex=i*1.0f/mHeight;if(index0.5f){floattemp=i-mHeight/.0f;a=55-(int)(temp/*55);}color=Color.argb(a,r,g,b);createBitmap.setPixel(j,i,color);}}returncreateBitmap;}
(ps:代码中采用的一些宽高和数值,要看具体效果来设置,这里仅做参考!)
.1增加一种修改透明度的方法该算法使用位移和模运算来单独修改透明值,不用把ARGB的四个颜色都取出来,会比之前的速度快很多
//透明渐变int[]argb=newint[ALBUM_SIZE*ALBUM_SIZE];localBitmap.getPixels(argb,0,localBitmap.getWidth(),0,0,localBitmap.getWidth(),localBitmap.getHeight());//循环开始的下标,设置从什么时候开始改变intstart=argb.length/;intmid=argb.length*83/;intlines=((mid-start)/localBitmap.getHeight())+;intwidth=localBitmap.getWidth();for(inti=0;ilines;i++){for(intj=0;jwidth;j++){intindex=start-width+i*width+j;//由于默认图片透明色为0,所以要增加判断,不然后续处理的颜色会变为黑色if(argb[index]!=0){argb[index]=((int)((1-((float)i/lines))*55)4)
(argb[index]0x00FFFFFF);}}}for(inti=mid;iargb.length;i++){argb[i]=(argb[i]0x00FFFFFF);}localBitmap=Bitmap.createBitmap(argb,localBitmap.getWidth(),localBitmap.getHeight(),Bitmap.Config.ARGB_);
(ps:算法中的数值也是仅供参考,具体还要看自己想要实现的效果,比如4和0x00FFFFFF是由于bitmap采用Config.ARGB_,大家根据自身需求修改就好,这里只提供思路)
.适配图片透明处理对于原图中带有透明的情况,获取像素点的时候透明的位置颜色值为0,所以在做透明渐变的时候要判断一下,避免后续颜色变成黑色
if(argb[index]!=0){argb[index]=((int)((1-((float)i/lines))*55)4)
(argb[index]0x00FFFFFF);}
最终效果如下:
总结本次内容不难,重要是实现思路,我一开始采用第一种叠加图片的方法,寻找计算线性渐变某一位置的值,后来找到了但最终效果不如上述的第二种方法,但是我发现第二种方法在计算比较大的Bitmap的时候速度是真很慢的(遍历一个Bitmap数组,脑壳痛),所以具体还是看大家的需求吧
源码