/*
* Copyright (C) 2013 Peng fei Pan <sky@xiaopan.me>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.xiaopan.sketch.process;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Shader.TileMode;
import me.xiaopan.sketch.Sketch;
import me.xiaopan.sketch.cache.BitmapPool;
import me.xiaopan.sketch.request.Resize;
/**
* 倒影图片处理器
*/
@SuppressWarnings("unused")
public class ReflectionImageProcessor extends WrappedImageProcessor {
private static final int DEFAULT_REFLECTION_SPACING = 2;
private static final float DEFAULT_REFLECTION_SCALE = 0.3f;
protected String logName = "ReflectionImageProcessor";
private int reflectionSpacing;
private float reflectionScale;
/**
* 创建一个倒影图片处理器
*
* @param reflectionSpacing 倒影和图片之间的距离
* @param reflectionScale 倒影的高度所占原图高度比例,取值为0.0到1
* @param wrappedImageProcessor 嵌套一个图片处理器
*/
public ReflectionImageProcessor(int reflectionSpacing, float reflectionScale, WrappedImageProcessor wrappedImageProcessor) {
super(wrappedImageProcessor);
this.reflectionSpacing = reflectionSpacing;
this.reflectionScale = reflectionScale;
}
/**
* 创建一个倒影图片处理器
*
* @param reflectionSpacing 倒影和图片之间的距离
* @param reflectionScale 倒影的高度所占原图高度比例,取值为0.0到1
*/
public ReflectionImageProcessor(int reflectionSpacing, float reflectionScale) {
this(reflectionSpacing, reflectionScale, null);
}
public ReflectionImageProcessor(WrappedImageProcessor wrappedImageProcessor) {
this(DEFAULT_REFLECTION_SPACING, DEFAULT_REFLECTION_SCALE, wrappedImageProcessor);
}
public ReflectionImageProcessor() {
this(DEFAULT_REFLECTION_SPACING, DEFAULT_REFLECTION_SCALE, null);
}
@Override
public String onGetKey() {
return String.format("%s(scale=%s,spacing=%d)", logName, reflectionScale, reflectionSpacing);
}
@Override
public Bitmap onProcess(Sketch sketch, Bitmap bitmap, Resize resize, boolean forceUseResize, boolean lowQualityImage) {
if (bitmap == null || bitmap.isRecycled()) {
return bitmap;
}
int srcHeight = bitmap.getHeight();
int reflectionHeight = (int) (srcHeight * reflectionScale);
int reflectionTop = srcHeight + reflectionSpacing;
Bitmap.Config config = lowQualityImage ? Bitmap.Config.ARGB_4444 : Bitmap.Config.ARGB_8888;
BitmapPool bitmapPool = sketch.getConfiguration().getBitmapPool();
Bitmap reflectionBitmap = bitmapPool.getOrMake(bitmap.getWidth(), reflectionTop + reflectionHeight, config);
// 在上半部分绘制原图
Canvas canvas = new Canvas(reflectionBitmap);
canvas.drawBitmap(bitmap, 0, 0, null);
// 在下半部分绘制倒影
Matrix matrix = new Matrix();
matrix.postScale(1, -1);
matrix.postTranslate(0, srcHeight + reflectionTop);
canvas.drawBitmap(bitmap, matrix, null);
// 在倒影部分绘制半透明遮罩,让倒影部分产生半透明渐变的效果
Paint paint = new Paint();
paint.setShader(new LinearGradient(0, reflectionTop, 0, reflectionBitmap.getHeight(), 0x70ffffff, 0x00ffffff, TileMode.CLAMP));
paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
canvas.drawRect(0, reflectionTop, reflectionBitmap.getWidth(), reflectionBitmap.getHeight(), paint);
return reflectionBitmap;
}
public float getReflectionScale() {
return reflectionScale;
}
public int getReflectionSpacing() {
return reflectionSpacing;
}
}