How can I display a bitmap in Compose Image - android-jetpack-compose

I have a function that returns a bitmap (which "contains" a QR code) and I wanted to display that bitmap inside an Image (composable function) but I didn't find any way to either convert the bitmap into a ImageBitmap or just displaying that bitmap.

Based on this blog post, it should be possible to display a bitmap like this :
#Composable
fun BitmapImage(bitmap: Bitmap) {
Image(
bitmap = bitmap.asImageBitmap(),
contentDescription = "some useful description",
)
}
I haven't tried it out myself, but recently came across the blog post when looking into displaying maps using Jetpack Compose.

Coil is capable of displaying a Bitmap inside Image:
Image(
painter = rememberAsyncImagePainter(imageBitmap),
contentDescription = null,
)

To sum up and keep answers up to date)
There are several options to display a bitmap in Compose
Using Image
Image(
bitmap = bitmap.asImageBitmap(),
...)
Using Coil AsyncImage
AsyncImage(model = bitmap,
...)
If you have Unsupported bla bla exception when using AsyncImage, check that you are using Bitmap and not ImageBitmap

Related

Using PdfStamper to add an image with AffineTransform

I am using PdfStamper getOverContent() so I can add an image to the output PDF file using an AffineTransform of Identity type.
PdfContentByte content = stamper.getOverContent(1);
data.image.setAbsolutePosition(desc.X,desc.Y);
content.addImage(data.image,desc.transform);
//content.addImage(data.image);
if I use the commented line without the transform it works perfectly adding the image to the PDF generated but with the AffineTransform (setToIdentity()) it does not show up.
could someone help me out with that ? I intend to use more sophisticated transform but the Identity should work first...
EDIT (copied from the invalid answer)
I removed the call to setAbsolutePosition and used a setToIdentity() as the only transformation and the image is not show... Then added the setToTranslation(X,Y) where X and Y are the same values used in the successful case where I do NOT give the transformation as the second parameter and still it does NOT show the image. Is there an example with the AffineTransform as a parameter to PdfContentByte addImage() call using an AffineTransform as a parameter ? I have bought your book but could not fins any.
I have examined your problem and I am pretty sure that your image gets added. However: you can't see it because the dimension of the image is 1 user unit by 1 user unit.
I've made an example to show you how to fix this problem: AddImageAffineTransform
public void manipulatePdf(String src, String dest) throws IOException, DocumentException {
PdfReader reader = new PdfReader(src);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
Image image = Image.getInstance(IMG);
AffineTransform at = AffineTransform.getTranslateInstance(36, 300);
at.concatenate(AffineTransform.getScaleInstance(image.getScaledWidth(), image.getScaledHeight()));
PdfContentByte canvas = stamper.getOverContent(1);
canvas.addImage(image, at);
stamper.close();
reader.close();
}
In this example, I start with a translation: 36 user units from the left border and 300 user units from the bottom. If I would add the image using this transformation, I'd add the image at those coordinates, but it would be too small to see with the naked eye.
To make sure the image is visible, I concatenate a scale transformation scaling the image to its width in X direction and to its height in Y direction.

Crop an Image to the shape of a Vector or Overlay a Shape

I imagine this is a shot in the dark, but is it possible to have a vector file of a shape (in this case a hexagon with rounded corners), and pass an image through some code and have it coming out cropped in the shape of that vector?
I'm attempting to utilize hexagons in my design and have gone through every page I possibly can. I've seen the many HTML and CSS solutions, but none of them achieve what I'm looking for flawlessly.
Another idea I have is maybe overlaying a transparent hexagon shape with white corners on top of the existing image with imagemagick, and then going through and making any white transparent. Thoughts?
I don't have any code for cropping in the shape of a vector file, but here's what I have for overlaying an outline of the shape I want on top of the other picture:
imgfile = "public/" + SecureRandom.uuid + ".png"
SmartCropper.from_file(art.url(:original)).smart_square.resize(225,225).write(imgfile)
overlay = Magick::Image.read("app/assets/images/overlay.png")
img = Magick::Image.read(imgfile)
img.composite(overlay,0,0, Magick::OverCompositeOp)
Right now it's giving me an undefined method error for composite, which is strange because I've followed some other stack overflow questions using the same thing in their models.
Any help is appreciated!
You have fallen for a common ImageMagick trap - the objects you get from the .read method are not Magick::Image objects but Magick::ImageList ones, and for most image types you want the first item from the list.
Without knowing how you have set up your overlay.png file, it is difficult to tell what the best composite option is. However, in a similar situation I found CopyOpacityCompositeOp to be useful, and to have the overlay's transparency control the transparency in the final image.
I tested the following code and it looks like it would do what you want if overlay.png was set up that way:
require 'smartcropper'
imgfile = "test_square.png"
SmartCropper.from_file( 'test_input.png' ).
smart_square.resize( 225, 225 ).write( imgfile )
overlay = Magick::Image.read( 'overlay.png' ).first
img = Magick::Image.read( imgfile ).first
img.composite( overlay, 0, 0, Magick::CopyOpacityCompositeOp ).
write( "test_result.png" )
Instead of reading overlay from a file, you could create it using Magick::Draw like this:
overlay = Magick::Image.new( 225, 225 ) do |i|
i.background_color= "Transparent"
end
gc = Magick::Draw.new
gc.stroke('white').stroke_width(10)
gc.fill('white')
gc.polygon(97.5, 26.25, 178.5, 73.125, 178.5, 167,
97.5, 213.75, 16.5, 167, 16.5, 73.125)
gc.draw( overlay )
NB That's a hexagon, but I've not bothered centering it.

Background is black in image.clipTo in Fabric.js

I am in the process of making a Fabric.js based application that users can upload images and make posters. Recently I started work on a clip function to crop images using a path drawn by the user.
How it works: User selects an image from the canvas and clicks on a crop button. The activeElement is choose from the canvas, its image src is extracted. This SRC is used to place an image on a canvas on a Bootstra Modal. The user clicks on the image where a path will be drawn and finally crops the image.
Once the crop button is clicked, a SVG path is made from the dot points. Then this value is used to crop the image.
Issue: If the image is a PNG with no background ( we only use PNGs ), it will make the background 'black'.
Below, #_path refers to the fabric. Path object created using a svg path by user clicks. #_image is image fabric.Image.
clipPath: () ->
path_x = #_path.getLeft() - ( #_image.getWidth() / 2 )
path_y = #_path.getTop()- ( #_image.getHeight() / 2 )
#_path.setLeft path_x
#_path.setTop path_y
# console.log 'Fill white'
# #_image.setFill('white')
#_image.clipTo = ( ctx ) =>
#_path.render( ctx )
#_image._clipToPath = #getPathSVG()
#_canvas.renderAll()
return
I tried #_image.setFIll('white') and #_image.backgroundColor = 'rgba(255,255,255,1)' but doesn't seem to be having an effect.
Questions:
Have I clipped/cropped the image the correct way ( ie: using clipTo )? Why do you think
Why do you think the image is black where there was trnsparency?
Thanks in advance.

Dart - Draggable Image

I'm trying to get a draggable image in Dart. Though setting the draggable bool of my image doesn't work.
image = new ImageElement();
image.src = ImageSourceByName(name);
image.on.load.add((event) {Context.drawImage(image, 10, 10, CARD_SMALL_WIDTH, CARD_SMALL_HEIGHT);});
image.draggable = true;
(Note: Context is the 2D context I get from my Canvas.)
The drawing works perfectly, I can see my card, though I can't drag it around. I'm pretty new to Dart, so it might be something obvious, though I can't find any tutorial explaining it.
You're using an ImageElement as the source to paint something on your CanvasElement.
Once the pixels are on the canvas(through drawImage()), your image data is not an HTMLElement but, well, pixels :)
The draggable attr, however, is an attribute of an HTMLElement.
If you add the image to your document, you'll notice that you can study the behaviour of draggable, like this:
document.body.nodes.add(image);
If you 'only' want to have draggable images, you can take it from there and maybe look at http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html
Otherwise, if you want stuff on a canvas to be draggable, thats a different(more complicated?) story.

Overlay smaller image in a larger image in OpenCV

I would like to replace a part of the image with my image in Opencv
I used
cvGetPerspectiveMatrix() with a warpmatrix and using cvAnd() and cvOr()
but could not get it to work
This is the code that is currently displaying the image and a white polygon for the replacement image. I would like to replace the white polygon for a pic with any dimension to be scaled and replaced with the region pointed.
While the code is in javacv I could convert it to java even if c code is posted
grabber.start();
while(isDisp() && (image=grabber.grab())!=null){
if (dst_corners != null) {// corners of the image to be replaced
CvPoint points = new CvPoint((byte) 0,dst_corners,0,dst_corners.length);
cvFillConvexPoly(image,points, 4, CvScalar.WHITE, 1, 0);//white polygon covering the replacement image
}
correspondFrame.showImage(image);
}
Any pointers to this will be very helpful.
Update:
I used warpmatrix with this code and I get a black spot for the overlay image
cvSetImageROI(image, cvRect(x1,y1, overlay.width(), overlay.height()));
CvPoint2D32f p = new CvPoint2D32f(4);
CvPoint2D32f q = new CvPoint2D32f(4);
q.position(0).x(0);
q.position(0).y(0);
q.position(1).x((float) overlay.width());
q.position(1).y(0);
q.position(2).x((float) overlay.width());
q.position(2).y((float) overlay.height());
q.position(3).x(0);
q.position(3).y((float) overlay.height());
p.position(0).x((int)Math.round(dst_corners[0]);
p.position(0).y((int)Math.round(dst_corners[1]));
p.position(1).x((int)Math.round(dst_corners[2]));
p.position(1).y((int)Math.round(dst_corners[3]));
p.position(3).x((int)Math.round(dst_corners[4]));
p.position(3).y((int)Math.round(dst_corners[5]));
p.position(2).x((int)Math.round(dst_corners[6]));
p.position(2).y((int)Math.round(dst_corners[7]));
cvGetPerspectiveTransform(q, p, warp_matrix);
cvWarpPerspective(overlay, image, warp_matrix);
I get a black spot for the overlay image and even though the original image is a polygon with 4 vertices the overlay image is set as a rectangle. I believe this is because of the ROI. Could anyone please tell me how to fit the image as is and also why I am getting a black spot instead of the overlay image.
I think cvWarpPerspective(link) is what you are looking for.
So instead of doing
CvPoint points = new CvPoint((byte) 0,dst_corners,0,dst_corners.length);
cvFillConvexPoly(image,points, 4, CvScalar.WHITE, 1, 0);//white polygon covering the replacement image
Try
cvWarpPerspective(yourimage, image, M, image.size(), INTER_CUBIC, BORDER_TRANSPARENT);
Where M is the matrix you get from cvGetPerspectiveMatrix
One way to do it is to scale the pic to the white polygon size and then copy it to the grabbed image setting its Region of Interest (here is a link explaining the ROI).
Your code should look like this:
resize(pic, resizedImage, resizedImage.size(), 0, 0, interpolation); //resizedImage should have the points size
cvSetImageROI(image, cvRect(the points coordinates));
cvCopy(resizedImage,image);
cvResetImageROI(image);
I hope that helps.
Best regards,
Daniel

Resources