How do I load SVG String into ImageView - java

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);

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 draw specific drawable resource programmatically?

I have a set of images in my drawable resources. Now I want to be able to change a placeholder image accordingly with image.setImageResource(R.id.name_of_image) programmatically.
My ImageView is defined as ImageView image = findViewById(R.id.placeholder);
How would I do this? I have tried getIdentifier but that didn't work.
The images have the format Name.jpg
EDIT:
I currently have the following construction:
int resID = getResources().getIdentifier(name.toLowerCase(), "drawable", this.getPackageName());
ImageView image = findViewById(R.id.placeholder);
image.setImageResource(resID);
I have changed the image name to lowercase and it is now a png file.
Your images has to be in png format (prefered by android) and must contain only lowercase letters and digits ([a-z0-9_.].
Then you can use
image.setImageResource(R.drawable.name_of_image);
You can get the name of the drawable with this:
String name = context.getResources().getResourceEntryName(R.drawable.name_of_image);
To get the drawable with the string name:
int id = context.getResources().getIdentifier("name_of_image", "drawable", context.getPackageName());
image.setImageResource(id);

Preserve Bitmap dimensions when saving to file from ImageView

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)

Get image URL from XML tag using Jsoup

I'm trying to get an image URL that in XML file, but i can't !
Other Tags like "Description, title, etc" gotten successfully !
XML File:
<DOC>
<DOCNO>annotations/01/1001.eng</DOCNO>
<TITLE>Godchild Gustavo Javier Cuchiparte Umaginga</TITLE>
<DESCRIPTION>a dark-skinned boy wearing a black cap;</DESCRIPTION>
<NOTES></NOTES>
<LOCATION>Quilotoa, Ecuador</LOCATION>
<DATE>April 2002</DATE>
<IMAGE>images/01/1001.jpg</IMAGE>
<THUMBNAIL>thumbnails/01/1001.jpg</THUMBNAIL>
</DOC>
My code:
Elements titles = doc.getElementsByTag("TITLE");
Elements descriptions = doc.getElementsByTag("DESCRIPTION");
Elements img = doc.getElementsByTag("IMAGE");
String Imgurl=img.get(0).text();
System.out.println(Imgurl);//EMPTY !!
Like you can see here, if JSoup parse it as a HTML file, your IMAGE tag is being modified and becomes <img>.
Here is how to parse an XML file properly :
Document doc = Jsoup.parse(yourXMLstring,"",Parser.xmlParser());
EDIT
It does work like this :
public static void main(String[] args) {
String xml = "<DOC><DOCNO>annotations/01/1001.eng</DOCNO><TITLE>Godchild Gustavo Javier Cuchiparte Umaginga</TITLE><DESCRIPTION>a dark-skinned boy wearing a black cap;</DESCRIPTION><NOTES></NOTES><LOCATION>Quilotoa,Ecuador</LOCATION><DATE>April 2002</DATE><IMAGE>images/01/1001.jpg</IMAGE><THUMBNAIL>thumbnails/01/1001.jpg</THUMBNAIL></DOC>";
Document doc = Jsoup.parse(xml,"",Parser.xmlParser());
String image = doc.select("IMAGE").first().text();
String image2 = doc.getElementsByTag("IMAGE").get(0).text();
System.out.println(image);
System.out.println(image2);
}
Output
images/01/1001.jpg
images/01/1001.jpg
If it does not work for you, you certainly have another problem. It does not lay in your code.

pdfbox and itext extracting image with incorrect dpi

When I extract an image using pdfbox I am getting incorrect dpi of the image for some PDFs. When I extract an image using Photoshop or Acrobat Reader Pro I can see that the dpi of the image is 200 using windows photo viewer, but when I extract the image using pdfbox the dpi is 72.
For extracting the image I am using following code :
Not able to extract images from PDFA1-a format document
When I check the logs I see an unusual entry:
2015-01-23-main--DEBUG-org.apache.pdfbox.util.TIFFUtil:
<?xml version="1.0" encoding="UTF-8"?><javax_imageio_jpeg_image_1.0>
<JPEGvariety>
<app0JFIF majorVersion="1" minorVersion="2" resUnits="0" Xdensity="1" Ydensity="1" thumbWidth="0" thumbHeight="0"/>
</JPEGvariety>
<markerSequence>
<dqt>
<dqtable elementPrecision="0" qtableId="0"/>
<dqtable elementPrecision="0" qtableId="1"/>
</dqt>
<dht>
<dhtable class="0" htableId="0"/>
<dhtable class="0" htableId="1"/>
<dhtable class="1" htableId="0"/>
<dhtable class="1" htableId="1"/>
</dht>
<sof process="0" samplePrecision="8" numLines="0" samplesPerLine="0" numFrameComponents="3">
<componentSpec componentId="1" HsamplingFactor="2" VsamplingFactor="2" QtableSelector="0"/>
<componentSpec componentId="2" HsamplingFactor="1" VsamplingFactor="1" QtableSelector="1"/>
<componentSpec componentId="3" HsamplingFactor="1" VsamplingFactor="1" QtableSelector="1"/>
</sof>
<sos numScanComponents="3" startSpectralSelection="0" endSpectralSelection="63" approxHigh="0" approxLow="0">
<scanComponentSpec componentSelector="1" dcHuffTable="0" acHuffTable="0"/>
<scanComponentSpec componentSelector="2" dcHuffTable="1" acHuffTable="1"/>
<scanComponentSpec componentSelector="3" dcHuffTable="1" acHuffTable="1"/>
</sos>
</markerSequence>
</javax_imageio_jpeg_image_1.0>
I tried to google but I can see to find out what pdfbox means by this log. What does this mean?
You can download a sample pdf with this problem from this link:
http://myslams.com/test/1.pdf
I have even tried itext but it is extracting image with 96 dpi.
Am I doing something wrong? Or pdfbox and itext have this limitation?
After some digging I found your 1.pdf. Thus,...
PDFBox
In comments to this recent answer #Tilman and you were discussing this older answer in which #Tilman pointed towards the PrintImageLocations PDFBox example. I ran it for your file and got:
Processing page: 0
*******************************************************************
Found image [Im0]
position = 0.0, 0.0
size = 1704px, 888px
size = 613.44, 319.68
size = 8.52in, 4.44in
size = 216.408mm, 112.776mm
Processing page: 1
*******************************************************************
Found image [Im0]
position = 0.0, 0.0
size = 1704px, 2800px
size = 613.44, 1008.0
size = 8.52in, 14.0in
size = 216.408mm, 355.6mm
Processing page: 2
*******************************************************************
Found image [Im0]
position = 0.0, 0.0
size = 1704px, 2800px
size = 613.44, 1008.0
size = 8.52in, 14.0in
size = 216.408mm, 355.6mm
Processing page: 3
*******************************************************************
Found image [Im0]
position = 0.0, 0.0
size = 1704px, 1464px
size = 613.44, 527.04
size = 8.52in, 7.3199997in
size = 216.408mm, 185.928mm
On all pages this amounts to 200 dpi both in x and y directions (1704px / 8.52in = 888px / 4.44in = 2800px / 14.0in = 1464px / 7.32in = 200 dpi).
So PDFBox gives you the dpi values you are after.
(#Tilman: The current 2.0.0-SNAPSHOT version of that sample returns utter nonsense; you might want to fix this.)
iText
A simplified iText version of that PDFBox example would be this:
public void printImageLocations(InputStream stream) throws IOException
{
PdfReader reader = new PdfReader(stream);
PdfReaderContentParser parser = new PdfReaderContentParser(reader);
ImageRenderListener listener = new ImageRenderListener();
for (int page = 1; page <= reader.getNumberOfPages(); page++)
{
System.out.printf("\nPage %s:\n", page);
parser.processContent(page, listener);
}
}
static class ImageRenderListener implements RenderListener
{
public void beginTextBlock() { }
public void renderText(TextRenderInfo renderInfo) { }
public void endTextBlock() { }
public void renderImage(ImageRenderInfo renderInfo)
{
try
{
PdfDictionary imageDict = renderInfo.getImage().getDictionary();
float widthPx = imageDict.getAsNumber(PdfName.WIDTH).floatValue();
float heightPx = imageDict.getAsNumber(PdfName.HEIGHT).floatValue();
float widthUu = renderInfo.getImageCTM().get(Matrix.I11);
float heigthUu = renderInfo.getImageCTM().get(Matrix.I22);
System.out.printf("Image %.0fpx*%.0fpx, %.0fuu*%.0fuu, %.2fin*%.2fin\n", widthPx, heightPx, widthUu, heigthUu, widthUu/72, heigthUu/72);
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
(Beware: I assumed unrotated and unskewed images.)
The results for your file:
Page 1:
Image 1704px*888px, 613uu*320uu, 8,52in*4,44in
Page 2:
Image 1704px*2800px, 613uu*1008uu, 8,52in*14,00in
Page 3:
Image 1704px*2800px, 613uu*1008uu, 8,52in*14,00in
Page 4:
Image 1704px*1464px, 613uu*527uu, 8,52in*7,32in
Thus, also 200dpi all along. So iText, too, gives you the dpi values you are after.
Your code
Obviously the code you referenced had no chance to report a dpi value sensible in the context of the PDF because it only extracts the images as found in the resources but ignores how the respective image resource is used on the page.
An image resource can be stretched, rotated, skewed, ... any way the author likes when he uses it in the page content.
BTW, a dpi value only makes sense if the author did not skew and rotated only by a multiple of 90°.

Categories