Preserve Bitmap dimensions when saving to file from ImageView - java

I am trying to save the drawable inside of a ImageView to a file.
I use Glide to load an image into the ImageView like this:
Glide.with(context)
//items[position] is a string that represents a url
.load(items[position])
.listener(object : RequestListener<Drawable> {
override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Drawable>?, isFirstResource: Boolean): Boolean {
holder.progressBar.visibility = View.GONE
return false
}
override fun onResourceReady(resource: Drawable?, model: Any?, target: Target<Drawable>?, dataSource: DataSource?, isFirstResource: Boolean): Boolean {
holder.progressBar.visibility = View.GONE
return false
}
})
.into(holder.imageView)
If the ImageView contains a GIF, I can save it without trouble to a file using the following method:
//In a typical use case, gifDrawable will equal holder.imageView.(gifDrawable.constantState.newDrawable().mutate()) as GifDrawable
private fun gifDrawableToFile(gifDrawable: GifDrawable, gifFile: File) {
val byteBuffer = gifDrawable.buffer
val output = FileOutputStream(gifFile)
val bytes = ByteArray(byteBuffer.capacity())
(byteBuffer.duplicate().clear() as ByteBuffer).get(bytes)
output.write(bytes, 0, bytes.size)
output.close()
}
However, if the ImageView contains a static image - then the dimensions are not preserved when I save it to a file using the following method:
//In a typical use case, bitmapDrawable will equal holder.imageView.drawable.constantState.newDrawable().mutate() as BitmapDrawable
bitmapDrawable.bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream)
The above code fails to maintain the dimensions the static image had inside of the imageview.
For example - notice how the GIF maintains the dimensions that it had inside of the imageView:
But notice here how the static image has drastically expanded in size:
(In both these examples, I am sending a file to the Facebook Messenger app, which it uses to display an image inside of a chat).
Although my code samples are in Kotlin, answers in Java would be helpful too.
Update 1 - I printed the width of the ImageView and of the Bitmap with the following code and they are the same.
val bitmap = (holder.imageView.drawable as BitmapDrawable).bitmap
Log.d("APP","Bwidth: " + bitmap.width)
Log.d("APP","Bheight:" + bitmap.height)
Log.d("APP","Iwidth" + holder.imageView.width)
Log.d("PP","Iheight" + holder.imageView.height)
But the output of both heights/widths was 315, and 300.
Update 2 -
I printed the width of the bitmap after saving it to a file like this. The width and height were still 315 and 300.
val bmOptions = BitmapFactory.Options()
val bitmap = BitmapFactory.decodeFile(imageFile.absolutePath, bmOptions)
Log.d("APP","Bitmap from file width: " + bitmap.width)
Log.d("APP","Bitmap from file height: " + bitmap.height)

Related

Using glide to display multiple images

For a scanning ticket app, I want to display full screen image.
The app does sequential operation. You scan your QrCode (first image), the device reach server (second image indicating to wait), then I display a third image if the ticket is validate, else I display the last one.
I'm using glide and the image path is indicated in a second activity, I transmit URI to main activity with a sharedPreferences file.
Here is the issue:
val settings = getSharedPreferences("PrefFile", 0)
if (S_mod){//priority on S_mod
uri_State_init = Uri.parse(settings.getString("mainUri", "none"))
uri_State_waiting = Uri.parse(settings.getString("waitUri", "none"))
uri_State_validated = Uri.parse(settings.getString("okUri", "none"))
uri_State_refused = Uri.parse(settings.getString("errorUri", "none"))
displayUri( uri_State_init, background)
image.setImageResource(R.drawable.empty)
}
where displayUri is
fun displayUri( uri: Uri?, dir:ImageView){//use to display image known by uri, only for full screen
Glide.with(this)
.load(uri)
.error(R.drawable.imagenotfound) // image in case of error
.override(1280, 800) // resizing if user doesn't respect the indicated dim
.centerCrop()//type of resizing
.into(dir)
}
The issue is that only the first image called by displayUri is displayed, the other call show the error image (imagenotfound)
It seem that I've not totally understood the glide extension.
If someone know about this particular issue thanks a lot!!
Here
val settings = getSharedPreferences("PrefFile", 0)
if (S_mod){//priority on S_mod
uri_State_init = Uri.parse(settings.getString("mainUri", "none"))
uri_State_waiting = Uri.parse(settings.getString("waitUri", "none"))
uri_State_validated = Uri.parse(settings.getString("okUri", "none"))
uri_State_refused = Uri.parse(settings.getString("errorUri", "none"))
displayUri( uri_State_init, background)
image.setImageResource(R.drawable.empty)
}
displayUri( uri_State_init, background)
You are just calling the display Image function with the same uri which means if you didn't passed the uri, then uri will be null and you will definitely get errors. What you can do is to send uri like this ,
val settings = getSharedPreferences("PrefFile", 0)
if (S_mod){//priority on S_mod
uri = Uri.parse(settings.getString("main_uri", "none"))
displayUri( uri_State_init, background)
image.setImageResource(R.drawable.empty)
}
Just change the value of main_uri in Shared Preferences whenever you want to change the state. You can also use onSharedPreferencesChanged Listener.

How to fill an external area of ​a marked region in an image using opencv?

I am developing an application using kotlin and opencv. The application has an image segmentation step in which the user marks a region of interest which I need to fill in the entire outside of that region with black. I'm taking the coordinates of the marked region and using floodFill to fill the image. However, with the code below it ends up filling the whole image, and not just the external region of the mark.
Code:
private fun extractBackground(coordinates: Coordinates, currentPhotoPath: String): String {
// TODO: Provide complex object that has both path and extension
val width: Int
val height: Int
width = bitmap.getWidth()
height = bitmap.getHeight()
val rect = Rect(coordinates.first, coordinates.second)
val rgba = Mat()
val gray_mat = Mat()
val threeChannel = Mat()
Utils.bitmapToMat(bitmap, gray_mat)
Imgproc.cvtColor(gray_mat, rgba, Imgproc.COLOR_RGBA2RGB)
Imgproc.cvtColor(rgba, threeChannel, Imgproc.COLOR_RGB2GRAY)
val mask = Mat.zeros(rgba.rows() + 2, rgba.cols() + 2, CvType.CV_8UC1)
Imgproc.floodFill(rgba, mask, Point(0.0, 0.0), Scalar(255.0), rect, Scalar(0.0), Scalar(0.0), 4 + (255 shl 8) + Imgproc.FLOODFILL_MASK_ONLY)
Core.subtract(mask, Scalar.all(0.0), mask)
val roi = Rect(1, 1, rgba.cols() - 2, rgba.rows() - 2)
val temp = Mat()
mask.submat(roi).copyTo(temp)
Imgcodecs.imwrite(currentPhotoPath + "_tmp.png", temp)
return currentPhotoPath
}
Input:
Output:
Expected output:
can someone help me fix this?

Imebra library shows completely gray image for transfer syntax 1.2.840.10008.1.2.1

Iam trying to use Imebra library to display DICOM images in android. Iam using version 5.0 of the library.
The bitmap shown is completely gray, transfer syntax for image is 1.2.840.10008.1.2.1.For other supported transfer syntax i.e JPEG it works fine.
Also I am unable to add VOILUT transform functionality as mentioned in documentation it gives error cons tructor not found for VOILUT.
Below is the code Iam using, VOILUT transform part is giving constructor not found. if i remove VOILUT transform part things work fine but for image with transfer syntax 1.2.840.10008.1.2.1 it shows completely grey image
private Bitmap fromDicom(String filePath, int frameNumber){
// have been applied).
Image dicomImage = loadedDataSet.getImageApplyModalityTransform(frameNumber);
// Use a DrawBitmap to build a stream of bytes that can be handled by the
// Android Bitmap class.
com.imebra.TransformsChain chain = new com.imebra.TransformsChain();
if( com.imebra.ColorTransformsFactory.isMonochrome(dicomImage.getColorSpace()))
{
// Retrieve the VOIs (center/width pairs)
com.imebra.VOIs vois = loadedDataSet.getVOIs();
if(!vois.isEmpty())
{
// Get the first VOI setting from the dataset
chain.addTransform(new VOILUT(vois.get(0)));
}
else
{
// The dataset does not have any VOI setting, find the optimal one
com.imebra.SWIGTYPE_p_imebra__VOIDescription voiDescription = VOILUT.getOptimalVOI(dicomImage, 0, 0, dicomImage.getWidth(), dicomImage.getHeight());
chain.addTransform(new VOILUT(voiDescription));
}
}
DrawBitmap drawBitmap = new DrawBitmap(chain);
Memory memory = drawBitmap.getBitmap(dicomImage, drawBitmapType_t.drawBitmapRGBA, 4);
// Build the Android Bitmap from the raw bytes returned by DrawBitmap.
Bitmap renderBitmap = Bitmap.createBitmap((int)dicomImage.getWidth(), (int)dicomImage.getHeight(), Bitmap.Config.ARGB_8888);
byte[] memoryByte = new byte[(int)memory.size()];
memory.data(memoryByte);
ByteBuffer byteBuffer = ByteBuffer.wrap(memoryByte);
renderBitmap.copyPixelsFromBuffer(byteBuffer);
// Update the image
return renderBitmap;
}
After changing the code suggested by you, I don't find classes mentioned
VOIDescription instead i see class SWIGTYPE_p_imebra__VOIDescription should i use that class
There is one more error no getWidth() method available with vois.get(0).getWidth
One last Error i don't see class vois_t instead there is a class VOIs should VOIs be used
Thanks for the reponse
The VOILUT must be initialized with the proper contrast settings from the dataset like in the code below.
However, the dataset contains a VOI setting that is wrong (the window width is 0) so this file will be displayed correctly only if you use custom VOI settings or just use automatic settings when width is zero (see alternative code below which checks for width > 0).
Code that does not check for width:
if(com.imebra.ColorTransformsFactory.isMonochrome(dicomImage.getColorSpace());
{
// Retrieve the VOIs (center/width pairs)
com.imebra.vois_t vois = loadedDataSet.getVOIs();
if(!vois.isEmpty())
{
// Get the first VOI setting from the dataset
chain.addTransform(new VOILUT(vois.get(0)));
}
else
{
// The dataset does not have any VOI setting, find the optimal one
com.imebra.VOIDescription voiDescription = VOILUT.getOptimalVOI(dataSetImage, 0, 0, width, height);
chain.addTransform(new VOILUT(voiDescription));
}
}
Alternative code that checks if width is 0:
if(com.imebra.ColorTransformsFactory.isMonochrome(dicomImage.getColorSpace());
{
// Retrieve the VOIs (center/width pairs)
com.imebra.vois_t vois = loadedDataSet.getVOIs();
if(!vois.isEmpty() && vois.get(0).getWidth() > 0.1)
{
// Get the first VOI setting from the dataset
chain.addTransform(new VOILUT(vois.get(0)));
}
else
{
// The dataset does not have any VOI setting, find the optimal one
com.imebra.VOIDescription voiDescription = VOILUT.getOptimalVOI(dataSetImage, 0, 0, width, height);
chain.addTransform(new VOILUT(voiDescription));
}
}

How do I load SVG String into ImageView

I have an SVG string
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 30" width="1200" height="600"><clipPath id="a"><path d="M30 15h30v15zv15h-30zh-30v-15zv-15h30z"/></clipPath><path d="M0 0v30h60v-30z" fill="#00247d"/><path d="M0 0l60 30m0-30l-60 30" stroke="#fff" stroke-width="6"/><path d="M0 0l60 30m0-30l-60 30" clip-path="url(#a)" stroke="#cf142b" stroke-width="4"/><path d="M30 0v30m-30-15h60" stroke="#fff" stroke-width="10"/><path d="M30 0v30m-30-15h60" stroke="#cf142b" stroke-width="6"/></svg>
How do I render it on ImageView?
If this was .svg file, I can load it with Glide in Android or other SVG library but don't know how to get around it with this svg string.
Try this out I think this may help you.let me know if this works
String yourSvgFile = "Your svg file";
InputStream stream = new ByteArrayInputStream(yourSvgFile.getBytes(StandardCharsets.UTF_8));
Glide.with(this).load(stream).into(yourView)
Accepted Answer does not really help me as Glide was throwing an exception asking to create a ModelLoader for type ByteArrayInputStream.Adding to the #Aweda's answer I used the AndroidSVG library as below.
Dependencies
//AndroidSVG
implementation 'com.caverock:androidsvg-aar:1.4'
//Glide (add only if you're going to use Glide to load the image)
implementation 'com.github.bumptech.glide:glide:4.12.0'
kapt 'com.github.bumptech.glide:compiler:4.12.0'
Code snippet
//SVG string content
val svgString =
"<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 60 30\" width=\"1200\" height=\"600\"><clipPath id=\"a\"><path d=\"M30 15h30v15zv15h-30zh-30v-15zv-15h30z\"/></clipPath><path d=\"M0 0v30h60v-30z\" fill=\"#00247d\"/><path d=\"M0 0l60 30m0-30l-60 30\" stroke=\"#fff\" stroke-width=\"6\"/><path d=\"M0 0l60 30m0-30l-60 30\" clip-path=\"url(#a)\" stroke=\"#cf142b\" stroke-width=\"4\"/><path d=\"M30 0v30m-30-15h60\" stroke=\"#fff\" stroke-width=\"10\"/><path d=\"M30 0v30m-30-15h60\" stroke=\"#cf142b\" stroke-width=\"6\"/></svg>"
//convert SVG string to an object of type SVG
val svg = SVG.getFromString(svgString)
//create a drawable from svg
val drawable = PictureDrawable(svg.renderToPicture())
//finally load the drawable with Glide.
Glide.with(this)
.load(drawable)
.into(yourImageView)
In case you do not want to use Glide and want to set the SVG image to ImageView directly, do as follow:
yourImageView.setImageDrawable(drawable);

How to calculate Image Size in JS or jQuery or JAVA?

I need to calculate the size of an image. I've an image src and base64 data also. I want to show the current image size.
I'm using java and javascript.
Is there any option using which I can calculate size of the image?
Using javascript you do it this way...
Bind the load event and when that particular src loads, just fetch this.width and this.height to have width and height of image.
var imgLoad = $("<img />");
imgLoad.attr("src", yourSrc);
imgLoad.unbind("load");
imgLoad.bind("load", function () {
var width = this.width;
var height = this.height;
});
you can use p = object.fileSize for file size
and for image dimension
var image= document.getElementById('imageId');
var width = image.clientWidth;
var height = image.clientHeight;
the best way you can use is :
var obj = new XMLHttpRequest();
obj.open('HEAD', 'check-image-load.zip', true);
obj.onreadystatechange = function(){
if ( obj.readyState == 4 ) {
if ( obj.status == 200 ) {
alert('Size in bytes: ' + obj.getResponseHeader('Content-Length'));
} else { alert('ERROR'); } }};
obj.send(null);

Categories