I am trying to get the edit text bitmap by using createBitmap() but there is an error.
I have gone through different answers but they didn't work for me. Can anyone solve this issue?
Here is my code:
case : I am trying to place the edit text over the image just like a photo editor where we can edit and place the image
val bmp: Bitmap = Bitmap.createBitmap(binding.editImage.getDrawingCache())
editImage is the edit text where i can take the string from user
combineImages(test, bmp)
test is the URI bitmap that I am getting when I clicked the image from the camera.
private fun combineImages(background: Bitmap?, foreground: Bitmap?): Bitmap {
val matrix = Matrix()
matrix.setValues(floatArrayOf(1f, .5f, 0f, 0f, 1f, 0f, 0f, 0f, 1f))
var width = 0
var height = 0
width = background!!.width
height = background.height
val cs: Bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
val comboImage = Canvas(cs)
val storage = Bitmap.createScaledBitmap(background, width, height, true)
comboImage.drawBitmap(storage,matrix, null)
if (foreground != null) {
comboImage.drawBitmap(foreground, matrix, null)
}
return cs
}
Please Help me!
Update
I have resolved this issue: Used the below answer
view.getDrawingCache() is deprecated in Android API 28
Related
I am new to this site, and I come with a question about Android.
Is there any way to convert a Bitmap to grayscale? I know how to draw a grayscale bitmap (using canvas operations: http://www.mail-archive.com/android-developers#googlegroups.com/msg38890.html) but I really need The actual bitmap in gray colors (or at least something that could be converted to a bitmap later on).
Do I have to implement it by hand (pixel by pixel operations)?
I've searched a lot, and still could not find. Anyone knows a easy/efficient way to do it?
Thanks a lot!
OH, yes, it does.
I was using it wrong, thanks for pointing it out to me.
(Sorry for the useless question)
Here is the end code (heavily based on the one linked) since it may help someone:
public Bitmap toGrayscale(Bitmap bmpOriginal)
{
int width, height;
height = bmpOriginal.getHeight();
width = bmpOriginal.getWidth();
Bitmap bmpGrayscale = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(bmpGrayscale);
Paint paint = new Paint();
ColorMatrix cm = new ColorMatrix();
cm.setSaturation(0);
ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);
paint.setColorFilter(f);
c.drawBitmap(bmpOriginal, 0, 0, paint);
return bmpGrayscale;
}
Any remarks or comments on it are very welcome.
Thanks
If you are going to show that Bitmap on ImageView. Then Instead of converting Bitmap to Gray Scale, you can try below code:
ColorMatrix matrix = new ColorMatrix();
matrix.setSaturation(0);
ColorMatrixColorFilter filter = new ColorMatrixColorFilter(matrix);
imageview.setColorFilter(filter);
For reference
Isn't that exactly what the code you're linking to does? It takes a color bitmap ("bmp"), creates a duplicate bitmap ("bm"), and then draws the color bitmap into "bm" using the filter to turn it into grayscale. From that point on, you can use "bm" as an actual grayscale bitmap and do whatever you want to do with it.
You'd need to tweak the sample a bit (it's using hard-coded sizes, you may want to just clone the size of the original bitmap), but other than that, this seems to be as ready-to-use as it gets, depending on what you want.
I'd like to mention that with this approach one important aspect must be taken in account. BitMap's on Android are stored in the NativeHeap. By just "creating bitmaps", you'll eventually clog the memory, getting an OutOfMemoryException (OOM).
Therefor, the bitmap must always be .recycled().
Here's a more efficient way, which I've made to support all versions of Android:
// https://xjaphx.wordpress.com/2011/06/21/image-processing-grayscale-image-on-the-fly/
#JvmStatic
fun getGrayscaledBitmapFallback(src: Bitmap, redVal: Float = 0.299f, greenVal: Float = 0.587f, blueVal: Float = 0.114f): Bitmap {
// create output bitmap
val bmOut = Bitmap.createBitmap(src.width, src.height, src.config)
// pixel information
var A: Int
var R: Int
var G: Int
var B: Int
var pixel: Int
// get image size
val width = src.width
val height = src.height
// scan through every single pixel
for (x in 0 until width) {
for (y in 0 until height) {
// get one pixel color
pixel = src.getPixel(x, y)
// retrieve color of all channels
A = Color.alpha(pixel)
R = Color.red(pixel)
G = Color.green(pixel)
B = Color.blue(pixel)
// take conversion up to one single value
B = (redVal * R + greenVal * G + blueVal * B).toInt()
G = B
R = G
// set new pixel color to output bitmap
bmOut.setPixel(x, y, Color.argb(A, R, G, B))
}
}
// return final image
return bmOut
}
#TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
#JvmStatic
fun getGrayscaledBitmap(context: Context, src: Bitmap): Bitmap {
// https://gist.github.com/imminent/cf4ab750104aa286fa08
// https://en.wikipedia.org/wiki/Grayscale
val redVal = 0.299f
val greenVal = 0.587f
val blueVal = 0.114f
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1)
return getGrayscaledBitmapFallback(src, redVal, greenVal, blueVal)
val render = RenderScript.create(context)
val matrix = Matrix4f(floatArrayOf(-redVal, -redVal, -redVal, 1.0f, -greenVal, -greenVal, -greenVal, 1.0f, -blueVal, -blueVal, -blueVal, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f))
val result = src.copy(src.config, true)
val input = Allocation.createFromBitmap(render, src, Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT)
val output = Allocation.createTyped(render, input.type)
// Inverts and do grayscale to the image
#Suppress("DEPRECATION")
val inverter =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
ScriptIntrinsicColorMatrix.create(render)
else
ScriptIntrinsicColorMatrix.create(render, Element.U8_4(render))
inverter.setColorMatrix(matrix)
inverter.forEach(input, output)
output.copyTo(result)
src.recycle()
render.destroy()
return result
}
val bitmapHeight: Int =
if (webview.measuredHeight < webview.contentHeight) view.contentHeight else view.measuredHeight
val bitmap = Bitmap.createBitmap(webview.measuredWidth, bitmapHeight, Bitmap.Config.ARGB_8888)
val canvas = Canvas(bitmap)
view.draw(canvas)
val scrollOffset =
if (scrollTo + view.getMeasuredHeight() > bitmap.height) bitmap.height else scrollTo
val resized = Bitmap.createBitmap(bitmap, 0, scrollOffset, bitmap.width, bitmap.contentHeight)
I want to let the user select the range of the screenshot to be taken of webview by scrolling.
How can I programmatically take a screenshot of a webview, capturing the full page?
I found the answer to this problem on the link above and implemented but it seems that the solution wasn't perfect.
The code above resulted in the extra white space being just added to the current range of view.
My scenario is iam designing design for print using canvas and my customview to load that canvas.In my case i have created multiple inner canvas inside parent canvas so iam created parentcanvas from activity and attached with one parentbitmap and designed each inner canvas as section by section with startpositon ,at the end i can able see my design on ui but while converting my customview as bitmap and saving in sd storage its doesnt have my design,its showing white as empty while debugging find only my inner created canvas and bitmap images have design but my parent bitmap doesnt contain design.so How Can i get whole design on parent bitmap.
PrintToolActivity:
setContentView(R.layout.activity_printtool)
customView = findViewById(R.id.customPrintView)
customView.setPrintDetails(mappedPrintProfileDetail, mappedPrintFieldDetail, printModel, null)
val tempBitmap = Bitmap.createBitmap(customView.canvasWidth.toInt(), customView.canvasHeight.toInt(), Bitmap.Config.ARGB_8888)
val parentCanvas = Canvas(tempBitmap)
parentCanvas.drawBitmap(tempBitmap, 0f, 0f, null)
customView.parentBitmap = tempBitmap
customView.init(null)
customView.invalidate()
customView.draw(parentCanvas)
customView.saveImage(tempBitmap, customView.bitmapPath)
HeaderSection.kt:
val headerBitmap = Bitmap.createBitmap((printProfileDetail.headerWidth * mmToPixelConvertorValue).toInt(),bitmapHeight.toInt(), Bitmap.Config.ARGB_8888)
val headerCanvas = Canvas(headerBitmap)
headerCanvas.drawColor(-1)
canvas.drawBitmap(headerBitmap, ((canvasWidth/2) - (printProfileDetail.headerWidth * mmToPixelConvertorValue)/2).toFloat() ,0f, paint)
headerCanvas.drawText(headerSegment.colName, (headerSegment.xPosition * mmToPixelConvertorValue).toFloat(), (headerSegment.yPosition * mmToPixelConvertorValue).toFloat(), paint)
DetailSection.Kt:
detailBitmap = Bitmap.createBitmap((printProfileDetail.paperWidth * mmToPixelConvertorValue).toInt(), parentBitmapHeight.toInt(), Bitmap.Config.ARGB_8888)
detailCanvas = Canvas(detailBitmap)
detailCanvas.drawColor(-1)
canvas.drawBitmap(detailBitmap, ((canvasWidth/2) - (printProfileDetail.paperWidth * mmToPixelConvertorValue)/2).toFloat(),canvasTop, paint)
detailCanvas.drawText(colName, (detailSegment.xPosition * mmToPixelConvertorValue).toFloat() , totalYposition.toFloat(), paint)
CustomView.kt:
//Ondraw method
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
canvas.drawColor(-1);
paint.style = Paint.Style.STROKE;
paint.strokeWidth = 2f;
paint.isAntiAlias = true
Controller(canvas,paint,this,parentBitmap).segmentSeparator(printProfileDetail,printFieldDetail,printModel)
}
I have bitmap that need to draw to canvas. The image is of a fixed size, but the canvas will change according to the user's screen size and density (bitmap coule be larger/smaller than the canvas).
I need to draw the bitmap to canvas scaling all the way into the canvas size (without distorting the image), I have done the code as below but the bitmap still filling only a portion of the screen.
Rect dest = new Rect(0, 0, drawCanvas.getWidth(), drawCanvas.getHeight());
Paint paint = new Paint();
paint.setFilterBitmap(true);
drawCanvas.drawBitmap(canvasBitmap, null, dest, paint);
May I know if anybody can shed light on a good solution? Thanks.
This example is in javascript but it should still help you out scale an image
jsFiddle : https://jsfiddle.net/CanvasCode/7oghuwe2/3/
javascript
var canvas1 = document.getElementById('canvas1');
var context1 = canvas1.getContext('2d')
var canvas2 = document.getElementById('canvas2');
var context2 = canvas2.getContext('2d');
var image1 = new Image();
image1.src = "http://media.giphy.com/media/iNk83OBPzlA8o/giphy.gif";
image1.onload = function () {
context1.fillStyle = "#F00";
context1.fillRect(0, 0, canvas1.width, canvas1.height);
context2.fillStyle = "#00F";
context2.fillRect(0, 0, canvas2.width, canvas2.height);
ratio(context1, canvas1, image1);
ratio(context2, canvas2, image1);
}
function ratio(context1, canvas1, image1) {
var imageRatio = image1.width / image1.height;
var newHeight = canvas1.width / imageRatio;
var newWidth = canvas1.height * imageRatio;
var heightDiff = newHeight - canvas1.height;
var widthDiff = newWidth - canvas1.width;
if (widthDiff >= heightDiff) {
context1.drawImage(image1, 0, 0, canvas1.width, canvas1.width / imageRatio);
} else {
context1.drawImage(image1, 0, 0, canvas1.height * imageRatio, canvas1.height);
}
}
Basically you need to calculate what the width would be if you scaled the image by the canvas height and what the height would be if you scale the image by the canvas width, and which ever is smaller, then you scale by that dimension.
The reason why it might not work for you might be because the function drawBitmap() ignores the density of the bitmap. The following is from the documentation.
public void drawBitmap (Bitmap bitmap, Rect src, Rect dst, Paint
paint)
This function ignores the density associated with the bitmap. This is
because the source and destination rectangle coordinate spaces are in
their respective densities, so must already have the appropriate
scaling factor applied.
What you could do is use public void drawBitmap (Bitmap bitmap, Matrix matrix, Paint paint) instead. First you need to map the source Matrix with the desination Matrix. You do this via Matrix.setRectToRect() or Matrix.setPolyToPoly(). This will give you an accurate mapping. Just make sure you map them correctly, otherwise things will be distorted.
For more info refer here: What code should I use with 'drawMatrix.setPolyToPoly' to manipulate and draw just a rectangular part of a bitmap, rather than the entire bitmap?
I want to crop image by polygon area, but couldn`t find any library, which can make it.
OpenCV is too big for this small thing. JJIL [enter link description here] crop just rectangle area.
Maybe you have any ideas how i can achieve it? Thanks for help!
FOR Nidhi:
Try something like this, if doesnot work - create another canvas for path, and than get Bitmap from it (for mask), and apply this mask bitmap to your initial canvas instead drawPath.
Bitmap obmp = BitmapFactory.decodeResource(getResources(), R.drawable.image1);
Bitmap resultImg = Bitmap.createBitmap(obmp.getWidth(), obmp.getHeight(), Bitmap.Config.ARGB_8888);
Bitmap maskImg = Bitmap.createBitmap(obmp.getWidth(), obmp.getHeight(), Bitmap.Config.ARGB_8888);
Canvas mCanvas = new Canvas(resultImg);
Canvas maskCanvas = new Canvas(maskImg);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.FILL);;
paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
Path path = new Path();
path.moveTo(view.mx,view.my);
path.lineTo(view.x1,view.y1);
path.lineTo(view.x2,view.y2 );
path.lineTo(view.x3,view.y3);
path.lineTo(view.x4,view.y4);
path.close();
maskCanvas.drawPath(path, paint);
mCanvas.drawBitmap(obmp, 0, 0, null);
mCanvas.drawBitmap(maskImg, 0, 0, paint);
Thanks for Eddy_Em, i have achieved this by using PorterDuffXfermode.
Good example
This a working Kotlin example, that clips and image to a polygon share depending on the path
private fun createBitmap() {
var bitmap = BitmapFactory.decodeResource(resources, R.drawable.gr)
val mutableBitmap: Bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true)
val bitmap2 = Bitmap.createBitmap(400, 400, Bitmap.Config.ARGB_8888)
val polyCanvas = Canvas(bitmap2)
val canvas = Canvas(mutableBitmap)
var paint = Paint()
paint.strokeWidth = 9f
val path = Path()
path.moveTo(150f, 0f)
path.lineTo(230f, 120f)
path.lineTo(290f, 160f)
path.lineTo(150f, 170f)
path.lineTo(70f, 200f)
path.lineTo(150f, 0f)
polyCanvas.drawPath(path, paint)
paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN);
polyCanvas.drawBitmap(mutableBitmap, 0f, 0f, paint)
imageView.setImageBitmap(bitmap2)
}