diff --git a/example/src/main/java/jp/wasabeef/example/glide/MainActivity.java b/example/src/main/java/jp/wasabeef/example/glide/MainActivity.java index 20074c6..7819568 100644 --- a/example/src/main/java/jp/wasabeef/example/glide/MainActivity.java +++ b/example/src/main/java/jp/wasabeef/example/glide/MainActivity.java @@ -18,6 +18,8 @@ public class MainActivity extends AppCompatActivity { recyclerView.setLayoutManager(new GridLayoutManager(this, 2)); List dataSet = new ArrayList<>(); + dataSet.add(Type.Mask); + dataSet.add(Type.NinePatchMask); dataSet.add(Type.CropTop); dataSet.add(Type.CropCenter); dataSet.add(Type.CropBottom); diff --git a/example/src/main/java/jp/wasabeef/example/glide/MainAdapter.java b/example/src/main/java/jp/wasabeef/example/glide/MainAdapter.java index 86df8ab..dc7b9ee 100644 --- a/example/src/main/java/jp/wasabeef/example/glide/MainAdapter.java +++ b/example/src/main/java/jp/wasabeef/example/glide/MainAdapter.java @@ -9,15 +9,21 @@ import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; + import com.bumptech.glide.Glide; import com.bumptech.glide.load.Transformation; +import com.bumptech.glide.load.resource.bitmap.CenterCrop; + import java.util.List; + import jp.wasabeef.glide.transformations.BlurTransformation; import jp.wasabeef.glide.transformations.ColorFilterTransformation; import jp.wasabeef.glide.transformations.CropCircleTransformation; import jp.wasabeef.glide.transformations.CropSquareTransformation; import jp.wasabeef.glide.transformations.CropTransformation; import jp.wasabeef.glide.transformations.GrayscaleTransformation; +import jp.wasabeef.glide.transformations.MaskTransformation; +import jp.wasabeef.glide.transformations.NinePatchMaskTransformation; import jp.wasabeef.glide.transformations.RoundedCornersTransformation; import jp.wasabeef.glide.transformations.gpu.BrightnessFilterTransformation; import jp.wasabeef.glide.transformations.gpu.ContrastFilterTransformation; @@ -39,6 +45,8 @@ public class MainAdapter extends RecyclerView.Adapter { private List mDataSet; enum Type { + Mask, + NinePatchMask, CropTop, CropCenter, CropBottom, @@ -73,6 +81,22 @@ public class MainAdapter extends RecyclerView.Adapter { @Override public void onBindViewHolder(MainAdapter.ViewHolder holder, int position) { Transformation transformation = null; switch (mDataSet.get(position)) { + case Mask: + transformation = new MaskTransformation(mContext, R.drawable.mask210); + Glide.with(mContext) + .load(R.drawable.demo) + .override(210, 210) + .bitmapTransform(new CenterCrop(mContext), transformation) + .into(holder.image); + break; + case NinePatchMask: + transformation = new NinePatchMaskTransformation(mContext, R.drawable.chat_me_mask, 300, 300); + Glide.with(mContext) + .load(R.drawable.demo) + .override(300, 300) + .bitmapTransform(new CenterCrop(mContext), transformation) + .into(holder.image); + break; case CropTop: transformation = new CropTransformation(mContext, 300, 100, CropTransformation.CropType.TOP); @@ -136,7 +160,9 @@ public class MainAdapter extends RecyclerView.Adapter { break; } - Glide.with(mContext).load(R.drawable.demo).bitmapTransform(transformation).into(holder.image); + if (mDataSet.get(position) != Type.Mask && mDataSet.get(position) != Type.NinePatchMask) { + Glide.with(mContext).load(R.drawable.demo).bitmapTransform(transformation).into(holder.image); + } holder.title.setText(mDataSet.get(position).name()); } diff --git a/example/src/main/res/drawable-xxhdpi/chat_me_mask.9.png b/example/src/main/res/drawable-xxhdpi/chat_me_mask.9.png new file mode 100644 index 0000000..a5b2390 Binary files /dev/null and b/example/src/main/res/drawable-xxhdpi/chat_me_mask.9.png differ diff --git a/example/src/main/res/drawable-xxhdpi/mask210.png b/example/src/main/res/drawable-xxhdpi/mask210.png new file mode 100644 index 0000000..f8d0757 Binary files /dev/null and b/example/src/main/res/drawable-xxhdpi/mask210.png differ diff --git a/transformations/src/main/java/jp/wasabeef/glide/transformations/MaskTransformation.java b/transformations/src/main/java/jp/wasabeef/glide/transformations/MaskTransformation.java new file mode 100644 index 0000000..00eb5e6 --- /dev/null +++ b/transformations/src/main/java/jp/wasabeef/glide/transformations/MaskTransformation.java @@ -0,0 +1,93 @@ +package jp.wasabeef.glide.transformations; + +/** + * Copyright (C) 2015 Wasabeef + * + * 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. + */ + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.os.Build; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.load.Transformation; +import com.bumptech.glide.load.engine.Resource; +import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool; +import com.bumptech.glide.load.resource.bitmap.BitmapResource; + +public class MaskTransformation implements Transformation { + + private Context mContext; + private BitmapPool mBitmapPool; + private int mMaskId; + + public MaskTransformation(Context context, int maskId) { + mBitmapPool = Glide.get(context).getBitmapPool(); + mContext = context; + mMaskId = maskId; + } + + @Override + public Resource transform(Resource resource, int outWidth, int outHeight) { + Bitmap source = resource.get(); + + boolean maskFromBitmapPool = true; + Bitmap mask = mBitmapPool.get(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888); + if (mask == null) { + maskFromBitmapPool = false; + mask = Bitmap.createBitmap(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888); + } + + Drawable drawable; + if (Build.VERSION.SDK_INT >= 21) { + drawable = mContext.getDrawable(mMaskId); + } else { + drawable = mContext.getResources().getDrawable(mMaskId); + } + drawable.setBounds(0, 0, source.getWidth(), source.getHeight()); + Canvas canvas = new Canvas(mask); + drawable.draw(canvas); + + Bitmap bitmap = mBitmapPool.get(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888); + if (bitmap == null) { + bitmap = Bitmap.createBitmap(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888); + } + + Paint paint = new Paint(); + paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); + + canvas = new Canvas(bitmap); + canvas.drawBitmap(mask, new Rect(0, 0, mask.getWidth(), mask.getHeight()), new Rect(0, 0, + source.getWidth(), source.getHeight()), null); + canvas.drawBitmap(source, 0, 0, paint); + + if (maskFromBitmapPool) { + mBitmapPool.put(mask); + } + + return BitmapResource.obtain(bitmap, mBitmapPool); + } + + @Override + public String getId() { + return "MaskTransformation(maskId=" + mMaskId + ")"; + } + +} diff --git a/transformations/src/main/java/jp/wasabeef/glide/transformations/NinePatchMaskTransformation.java b/transformations/src/main/java/jp/wasabeef/glide/transformations/NinePatchMaskTransformation.java new file mode 100644 index 0000000..b7d3b53 --- /dev/null +++ b/transformations/src/main/java/jp/wasabeef/glide/transformations/NinePatchMaskTransformation.java @@ -0,0 +1,102 @@ +package jp.wasabeef.glide.transformations; + +/** + * Copyright (C) 2015 Wasabeef + * + * 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. + */ + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.os.Build; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.load.Transformation; +import com.bumptech.glide.load.engine.Resource; +import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool; +import com.bumptech.glide.load.resource.bitmap.BitmapResource; +import com.bumptech.glide.request.target.Target; + +public class NinePatchMaskTransformation implements Transformation { + + private Context mContext; + private BitmapPool mBitmapPool; + private int mMaskId; + private int mWidth; + private int mHeight; + + public NinePatchMaskTransformation(Context context, int maskId, int width, int height) { + mBitmapPool = Glide.get(context).getBitmapPool(); + mContext = context; + mMaskId = maskId; + mWidth = width; + mHeight = height; + } + + @Override + public Resource transform(Resource resource, int outWidth, int outHeight) { + Bitmap source = resource.get(); + + int width = outWidth == Target.SIZE_ORIGINAL ? source.getWidth() : outWidth; + int height = outHeight == Target.SIZE_ORIGINAL ? source.getHeight() : outHeight; + + boolean maskFromBitmapPool = true; + Bitmap mask = mBitmapPool.get(width, height, Bitmap.Config.ARGB_8888); + if (mask == null) { + maskFromBitmapPool = false; + mask = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); + } + + Drawable drawable; + if (Build.VERSION.SDK_INT >= 21) { + drawable = mContext.getDrawable(mMaskId); + } else { + drawable = mContext.getResources().getDrawable(mMaskId); + } + drawable.setBounds(0, 0, width, height); + Canvas canvas = new Canvas(mask); + drawable.draw(canvas); + + Bitmap bitmap = mBitmapPool.get(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888); + if (bitmap == null) { + bitmap = Bitmap.createBitmap(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888); + } + + Paint paint = new Paint(); + paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); + + canvas = new Canvas(bitmap); + canvas.drawBitmap(mask, new Rect(0, 0, mask.getWidth(), mask.getHeight()), new Rect(0, 0, + source.getWidth(), source.getHeight()), null); + canvas.drawBitmap(source, 0, 0, paint); + + if (maskFromBitmapPool) { + mBitmapPool.put(mask); + } + + return BitmapResource.obtain(bitmap, mBitmapPool); + } + + @Override + public String getId() { + return "NinePatchMaskTransformation(mMaskId=" + mMaskId + + ", width=" + mWidth + ", height=" + mHeight + ")"; + } + +}