Làm việc với Bitmap trong Android
Bitmap (hoặc đồ họa raster) là một hình ảnh kỹ thuật số bao gồm một ma trận các dấu chấm. Khi được xem ở mức 100%, mỗi dấu chấm tương ứng với một pixel riêng lẻ trên màn hình. Trong ảnh bitmap tiêu chuẩn, mỗi dấu chấm có thể được gán một màu khác nhau.
Trong trường hợp này, chúng ta có thể tạo Bitmap
theo cách trực tiếp:
Bitmap b = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
Bitmap đơn giản là một hình chữ nhật gồm các pixel. Mỗi pixel có thể được đặt thành một màu nhất định nhưng chính xác màu nào phụ thuộc vào loại pixel. Hai tham số đầu tiên cho biết chiều rộng và chiều cao tính bằng pixel. Tham số thứ ba chỉ định loại pixel bạn muốn sử dụng. Đây là nơi mọi thứ có thể trở nên phức tạp. Thông số kỹ thuật ARGB_8888
có nghĩa là tạo một pixel với bốn kênh ARGB - Alpha, Red, Green, Blue và phân bổ mỗi 8 bit dung lượng lưu trữ. Vì 4 x 8 = 32 nên đây là đồ họa 32 bit. Kênh alpha cho phép bạn đặt độ mờ.
Bạn có thể lấy Bitmap
từ Drawables thông qua mã sau.
ImageView image = (ImageView) findViewById(R.id.image);
Bitmap b = BitmapFactory.decodeResource(getResources(), R.drawable.car);
image.setImageBitmap(b);
Để chuyển đổi một Bitmap
đối tượng thành một đối tượng, Drawable
bạn có thể sử dụng đoạn mã sau.
Drawable d = new BitmapDrawable(getResources(), bitmap);
Scale Bitmap
Nếu cần thay đổi kích thước a Bitmap
, chúng ta có thể gọi createScaledBitmap
phương thức để thay đổi kích thước bất kỳ bitmap nào theo chiều rộng và chiều cao mong muốn:
// load a bitmap from the drawable folder
Bitmap b = BitmapFactory.decodeResource(getResources(), R.drawable.car);
// resize the bitmap to 150x100 (width x height)
Bitmap scaled = Bitmap.createScaledBitmap(b, 150, 100, true);
// loads the resized Bitmap into an ImageView
ImageView image = (ImageView) findViewById(R.id.image);
image.setImageBitmap(scaled);
Bạn thường muốn thay đổi kích thước bitmap nhưng vẫn giữ nguyên tỷ lệ khung hình bằng lớp tiện ích BitmapScaler với mã như sau:
public class BitmapScaler{
// Scale and maintain aspect ratio given a desired width
// BitmapScaler.scaleToFitWidth(bitmap, 100);
public static Bitmap scaleToFitWidth(Bitmap b, int width) {
float factor = width / (float) b.getWidth();
return Bitmap.createScaledBitmap(b, width, (int) (b.getHeight() * factor), true);
}
// Scale and maintain aspect ratio given a desired height
// BitmapScaler.scaleToFitHeight(bitmap, 100);
public static Bitmap scaleToFitHeight(Bitmap b, int height) {
float factor = height / (float) b.getHeight();
return Bitmap.createScaledBitmap(b, (int) (b.getWidth() * factor), height, true);
}
// ...
}
Kết hợp nhiều bitmap thành một bitmap
Bitmap image1 = BitmapFactory.decodeResource(getResources(), R.drawable.image1);
Bitmap image2 = BitmapFactory.decodeResource(getResources(), R.drawable.image2);
Bitmap merged = Bitmap.createBitmap(image1.getWidth(), image1.getHeight(), image1.getConfig());
Canvas canvas = new Canvas(merged);
canvas.drawBitmap(image1, 0f, 0f, null);
canvas.drawBitmap(image2, 10, 10, null);
imageView.setImageBitmap(merged);
Các góc tròn
Trong Android, bạn có thể nhanh chóng tạo ảnh bitmap với các góc tròn được khử răng cưa bằng đoạn mã bên dưới.
public static Bitmap getRoundedCornerBitmap(Bitmap bitmap) {
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),bitmap.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = 0xff424242;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
final RectF rectF = new RectF(rect);
final float roundPx = 12;
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return output;
}
Cách tạo bitmap hình tròn
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_photo);
Bitmap img = BitmapFactory.decodeResource(getResources(), R.drawable.girl);
ImageView iv = findViewById(R.id.imageView);
iv.setImageBitmap(getCircleBitmap1(img));
}
public Bitmap getCircleBitmap1(Bitmap source) {
int size = Math.min(source.getHeight(), source.getWidth());
Bitmap output = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(output);
int color = Color.RED;
Paint paint = new Paint();
Rect rect = new Rect(0, 0, size, size);
RectF rectF = new RectF(rect);
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawOval(rectF, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(source, rect, rect, paint);
return output;
}
public Bitmap getCircleBitmap2(Bitmap source) {
int size = Math.min(source.getWidth(), source.getHeight());
int x = (source.getWidth() - size) / 2;
int y = (source.getHeight() - size) / 2;
Bitmap squaredBitmap = Bitmap.createBitmap(source, x, y, size, size);
if (squaredBitmap != source) {
source.recycle();
}
Bitmap bitmap = Bitmap.createBitmap(size, size, source.getConfig());
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
BitmapShader shader = new BitmapShader(squaredBitmap, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP);
paint.setShader(shader);
paint.setAntiAlias(true);
float r = size / 2f;
canvas.drawCircle(r, r, r, paint);
squaredBitmap.recycle();
return bitmap;
}
public Bitmap getCircleBitmap3(Bitmap source) {
RoundedBitmapDrawable roundedBitmapDrawable= RoundedBitmapDrawableFactory.create(getResources(), source);
roundedBitmapDrawable.setCircular(true);
//int size = Math.min(source.getWidth(), source.getHeight());
//float r = size/2.0f;
//roundedBitmapDrawable.setCornerRadius(r);
return drawableToBitmap(roundedBitmapDrawable);
}
public static Bitmap drawableToBitmap (Drawable drawable) {
if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable)drawable).getBitmap();
}
int width = drawable.getIntrinsicWidth();
width = width > 0 ? width : 1;
int height = drawable.getIntrinsicHeight();
height = height > 0 ? height : 1;
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
}
Chuyển đổi một object File thành Bitmap
Bitmap bitmap = BitmapFactory.decodeFile(fileObj.getAbsolutePath());
imageView.setImageBitmap(bitmap);
Lưu Bitmap vào File
Bitmap bitmap = Bitmap.createScaledBitmap(b, 150, 150, false);
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 70, outStream);
//bitmap.compress(CompressFormat.PNG, 0, outStream);
File f = new File(Environment.getExternalStorageDirectory() + File.separator + "filename.jpg");
f.createNewFile();
try {
FileOutputStream fo = new FileOutputStream(f);
fo.write(outStream.toByteArray());
fo.flush();
fo.close();
} catch (FileNotFoundException e) {
Log.w("TAG", "Error saving image file: " + e.getMessage());
return false;
} catch (IOException e) {
Log.w("TAG", "Error saving image file: " + e.getMessage());
return false;
}
Gửi Bitmap bằng Intent
Phía activity gọi:
Intent i = new Intent(this, NextActivity.class);
Bitmap b; // your bitmap
ByteArrayOutputStream bs = new ByteArrayOutputStream();
b.compress(Bitmap.CompressFormat.PNG, 50, bs);
i.putExtra("byteArray", bs.toByteArray());
startActivity(i);
Phía activity nhận:
if (getIntent().hasExtra("byteArray")) {
ImageView preview = new ImageView(this);
byte[] byteArray = getIntent().getByteArrayExtra("byteArray");
Bitmap b = BitmapFactory.decodeByteArray(byteArray,0,byteArray.length);
preview.setImageBitmap(b);
}
Tải xuống Bitmap từ URL
public Bitmap getBitmapFromURL(String strURL) {
try {
URL url = new URL(strURL);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
Bitmap myBitmap = BitmapFactory.decodeStream(input);
return myBitmap;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
Cách vẽ gradient tuyến tính, hình chữ nhật và hình tròn trên Bitmap
iv = (ImageView) findViewById(R.id.iv);
Bitmap bitmap = Bitmap.createBitmap(200, 200, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
// BG
Paint paintBg = new Paint();
paintBg.setColor(Color.GRAY);
canvas.drawRect(0, 0, 200, 200, paintBg);
// GRADIENT
int gradientWidth = bitmap.getWidth();
int gradientHeight = 40;
Shader shader = new LinearGradient(0, 0, gradientWidth, gradientHeight,
new int[] {Color.RED, Color.TRANSPARENT}, null, Shader.TileMode.CLAMP);
Paint paintGradient = new Paint();
paintGradient.setShader(shader);
canvas.drawRect(0, 0, gradientWidth, gradientHeight, paintGradient);
// CIRCLE
Paint paintCircle = new Paint();
paintCircle.setColor(Color.GREEN);
paintCircle.setAntiAlias(true);
canvas.drawCircle(100, 100, 40, paintCircle);
Kết quả
Cách vẽ văn bản trên Bitmap
iv = (ImageView) findViewById(R.id.iv);
Bitmap bitmap = Bitmap.createBitmap(200, 200, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
// BG
Paint paintBg = new Paint();
paintBg.setColor(Color.GRAY);
canvas.drawRect(0, 0, 200, 200, paintBg);
String string = "Hello Android";
float scale = getResources().getDisplayMetrics().density;
Paint paintText = new Paint(Paint.ANTI_ALIAS_FLAG);
paintText.setColor(Color.rgb(0, 0, 0));
paintText.setTextSize((int) (14 * scale));
paintText.setShadowLayer(1f, 0f, 1f, Color.WHITE);
// draw text in the center
Rect bounds = new Rect();
paintText.getTextBounds(string, 0, string.length(), bounds);
int x = (bitmap.getWidth() - bounds.width())/2;
int y = (bitmap.getHeight() + bounds.height())/2;
canvas.drawText(string, x, y, paintText);
iv.setImageBitmap(bitmap);
Kết quả
Cách căn giữa và cắt ảnh Bitmap
public static Bitmap cropCenter(Bitmap bmp) {
// use the smallest dimension of the image to crop to
int dimension = Math.min(bmp.getWidth(), bmp.getHeight());
return ThumbnailUtils.extractThumbnail(bmp, dimension, dimension);
}
Làm thế nào để chuyển đổi dp sang px
public static int dp2px(int dp, Context context) {
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, metrics);
}
public static float px2dp(float px, Context context) {
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
return (float) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, px, metrics);
}
Chuyển đổi JPG sang PNG sang WebP theo chương trình
private fun processBitmap() {
val bitmap = assetsToBitmap("image.jpg")
// Compress bitmap and convert image format from one to another
val compressedBitmap = bitmap.compress(Bitmap.CompressFormat.PNG)
//val compressedBitmap = bitmap.compress(Bitmap.CompressFormat.WEBP)
//val compressedBitmap = bitmap.compress(Bitmap.CompressFormat.JPEG)
//val compressedBitmap = bitmap.compress(Bitmap.CompressFormat.JPEG, 10)
//val compressedBitmap = bitmap.compress(quality = 10) // Compress only
// Display the compressed bitmap into image view
imageView.setImageBitmap(compressedBitmap)
}
// Extension function to compress and change bitmap image format programmatically
fun Bitmap.compress(format:Bitmap.CompressFormat = Bitmap.CompressFormat.JPEG, quality:Int = 100):Bitmap{
// Initialize a new ByteArrayStream
val stream = ByteArrayOutputStream()
// Compress the bitmap with JPEG format and quality 50%
this.compress(
format,
quality,
stream
)
val byteArray = stream.toByteArray()
// Finally, return the compressed bitmap
return BitmapFactory.decodeByteArray(byteArray, 0, byteArray.size)
}
private fun assetsToBitmap(fileName:String):Bitmap?{
return try{
val stream = assets.open(fileName)
BitmapFactory.decodeStream(stream)
}catch (e:IOException){
e.printStackTrace()
null
}
}
Giảm tỷ lệ bitmap theo tỷ lệ khung hình
private fun processBitmap() {
val bitmap = assetsToBitmap("image.jpg")
// Resize the bitmap by keeping aspect ration
// Bitmap scaled to given maximum height and width value
val resizedBitmap = bitmap.scale(500)
imageView.setImageBitmap(resizedBitmap)
}
// Extension method to resize bitmap to maximum width and height
fun Bitmap.scale(maxWidthAndHeight:Int):Bitmap{
var newWidth = 0
var newHeight = 0
if (this.width >= this.height){
val ratio:Float = this.width.toFloat() / this.height.toFloat()
newWidth = maxWidthAndHeight
// Calculate the new height for the scaled bitmap
newHeight = Math.round(maxWidthAndHeight / ratio)
}else{
val ratio:Float = this.height.toFloat() / this.width.toFloat()
// Calculate the new width for the scaled bitmap
newWidth = Math.round(maxWidthAndHeight / ratio)
newHeight = maxWidthAndHeight
}
return Bitmap.createScaledBitmap(
this,
newWidth,
newHeight,
false
)
}
Thay đổi kích thước bitmap giữ tỷ lệ khung hình
private fun processBitmap() {
val bitmap = assetsToBitmap("image.jpg")
// Resize the bitmap by keeping aspect ration
val resizedBitmap = bitmap.resizeByWidth(900)
//val resizedBitmap = bitmap.resizeByHeight(400)
// Display the resized bitmap into image view
image_view_file.setImageBitmap(resizedBitmap)
}
// Extension function to resize bitmap using new width value by keeping aspect ratio
fun Bitmap.resizeByWidth(width:Int):Bitmap{
val ratio:Float = this.width.toFloat() / this.height.toFloat()
val height:Int = Math.round(width / ratio)
return Bitmap.createScaledBitmap(
this,
width,
height,
false
)
}
// Extension function to resize bitmap using new height value by keeping aspect ratio
fun Bitmap.resizeByHeight(height:Int):Bitmap{
val ratio:Float = this.height.toFloat() / this.width.toFloat()
val width:Int = Math.round(height / ratio)
return Bitmap.createScaledBitmap(
this,
width,
height,
false
)
}
Xoay một bitmap
private fun processBitmap() {
val bitmap = assetsToBitmap("image.jpg")
// Rotate the bitmap
val rotatedBitmap = bitmap.rotate(90)
// Display the rotated bitmap into image view
imageView.setImageBitmap(rotatedBitmap)
}
// Extension function to rotate a bitmap
fun Bitmap.rotate(degree:Int):Bitmap{
// Initialize a new matrix
val matrix = Matrix()
// Rotate the bitmap
matrix.postRotate(degree.toFloat())
// Resize the bitmap
val scaledBitmap = Bitmap.createScaledBitmap(
this,
width,
height,
true
)
// Create and return the rotated bitmap
return Bitmap.createBitmap(
scaledBitmap,
0,
0,
scaledBitmap.width,
scaledBitmap.height,
matrix,
true
)
}
Ví dụ nén bitmap
private fun processBitmap() {
// Get the bitmap from given drawable object
val drawable = ContextCompat.getDrawable(applicationContext,R.drawable.image)
val bitmap = (drawable as BitmapDrawable).bitmap
imageView.setImageBitmap(compressBitmap(bitmap,5))
}
// Method to compress a bitmap
private fun compressBitmap(bitmap:Bitmap, quality:Int):Bitmap{
// Initialize a new ByteArrayStream
val stream = ByteArrayOutputStream()
// Compress the bitmap with JPEG format and quality 50%
bitmap.compress(Bitmap.CompressFormat.JPEG, quality, stream)
val byteArray = stream.toByteArray()
// Finally, return the compressed bitmap
return BitmapFactory.decodeByteArray(byteArray, 0, byteArray.size)
}
Chuyển đổi bitmap thành tập tin
private fun processBitmap() {
val bitmap = assetsToBitmap("image.jpg")
// Save the bitmap to a file and display it into image view
val uri = bitmapToFile(bitmap)
imageView.setImageURI(uri)
}
// Method to save an bitmap to a file
private fun bitmapToFile(bitmap:Bitmap): Uri {
// Get the context wrapper
val wrapper = ContextWrapper(applicationContext)
// Initialize a new file instance to save bitmap object
var file = wrapper.getDir("Images",Context.MODE_PRIVATE)
file = File(file,"${UUID.randomUUID()}.jpg")
try{
// Compress the bitmap and save in jpg format
val stream:OutputStream = FileOutputStream(file)
bitmap.compress(Bitmap.CompressFormat.JPEG,100,stream)
stream.flush()
stream.close()
}catch (e:IOException){
e.printStackTrace()
}
// Return the saved bitmap uri
return Uri.parse(file.absolutePath)
}
Chuyển đổi bitmap thành có thể vẽ được
private fun processBitmap() {
val bitmap = assetsToBitmap("image.jpg")
imageView.setImageDrawable(bitmapToDrawable(bitmap))
}
// Method to convert a bitmap to bitmap drawable
private fun bitmapToDrawable(bitmap:Bitmap):BitmapDrawable{
return BitmapDrawable(resources,bitmap)
}
Chuyển đổi bản vẽ có thể vẽ thành bitmap
fun Context.vectorToBitmap(drawableId: Int): Bitmap? {
val drawable = getDrawable(this, drawableId) ?: return null
val bitmap = createBitmap(
drawable.intrinsicWidth, drawable.intrinsicHeight, Bitmap.Config.ARGB_8888
) ?: return null
val canvas = Canvas(bitmap)
drawable.setBounds(0, 0, canvas.width, canvas.height)
drawable.draw(canvas)
return bitmap
}
Source: https://en.proft.me/2017/08/2/how-work-bitmap-android/