I've been working on an Android app where I am getting an RSS feed and I need to parse some additional HTML for image source links. So, I figured I would use JSoup and see how it went. It IS working and I can get the image src link correctly. However the .Parse method is taking a very long time to complete and I can't have the user waiting that long. All of this fetching of the RSS takes place in onStart() in the app by the way.
My ultimate goal is to retrieve the images from the src url's and display them next to article text. I've had my fair share of dealing with the common OutOfMemory errors in relation to the heap. As of now I seem to have sort of dealt with it. But I still cannot figure out why the loading of the program is taking so long. Right now there are 10 articles in the RSS feed and the HTML parsing for each one is not really long. Maybe someone can spot something stupid I'm doing and figure out why the loading of my program is taking so long. I would certainly appreciate it! Here is my code involving the images and Jsoup.
public static Bitmap parseForImg(String desc) throws IOException
{
Document doc = Jsoup.parse(desc);
Elements images = doc.select("img[src~=(?i)\\.(png|jpe?g|gif)]");
String imgURL = "";
Bitmap img = null;
if(images.size() > 0)
{
for (Element image : images)
{
imgURL = image.attr("src");
break;
}
String editedImgURL = imgURL.replace("/sites/", "https://www.").trim();
img = ArticleRSSReader.grabImgFromURL(editedImgURL);
}
else
{
//in the event there is no image related to a description in the rss feed, just display
//the logo for now...
InputStream inputS = MainActivity.globalTHIS.getResources().getAssets().open("defaultlogo.png");
img = BitmapFactory.decodeStream(inputS);
//no need to grab image from url, just return
}
return img;
}
public static Bitmap grabImgFromURL(String imageURLLoc)
{
URL imageURL = null;
Bitmap resizedBit = null;
try
{
imageURL = new URL(imageURLLoc);
}
catch (MalformedURLException e)
{
e.printStackTrace();
}
try
{
HttpURLConnection connection = (HttpURLConnection) imageURL
.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream inputStream = connection.getInputStream();
//bitmap = BitmapFactory.decodeStream(inputStream);// Convert to
// bitmap
// image_view.setImageBitmap(bitmap);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 8;
options.inPurgeable = true;
resizedBit = Bitmap.createScaledBitmap(BitmapFactory.decodeStream(inputStream,null,options), 100, 100, false);
}
catch (IOException e)
{
e.printStackTrace();
}
return resizedBit;
}
Related
Currently, I'm building a camera app using camera2 api. I record the video and that file is sent to another activity to make sure we can correct orientation and watch the video. Then the altered video or picture is saved to the device.
When I use a still image it works, because I can pull the bitmap image and then resave the image like this:
public String saveImage() {
//Getting a new file name and file path
//Should we delete these images after were done with them?
File newImageFile = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File newImageFolder = new File(newImageFile, "camera2VideoImage");
if (newImageFolder.exists())
{
newImageFolder.mkdirs();
}
String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String prepend = "Image_" + timestamp + "_";
File imageFile = null;
try {
imageFile = File.createTempFile(prepend, ".jpg", newImageFolder);
} catch (IOException e) {
e.printStackTrace();
}
String newFileName = imageFile.getAbsolutePath();
Bitmap bitmap = ((BitmapDrawable) imageView.getDrawable()).getBitmap();
try {
FileOutputStream fos = new FileOutputStream(newFileName);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
//returning the new file path.
return newFileName;
}
This works, they view the image and have the option to change orientation on the image in case it is messed up and then we resave.
I'm trying to do the same with a video, but not sure how to pull the video from the textureView so I can save again with the corrected orientation as the front facing camera is upside down sometimes depending on the phone.
The recording save method:
public String saveVideo() {
//Getting a new file name and file path
//Should we delete these images after were done with them?
File newVideoFile = getExternalFilesDir(Environment.DIRECTORY_MOVIES);
File newVideoFolder = new File(newVideoFile, "camera2VideoImage");
if (newVideoFolder.exists())
{
newVideoFolder.mkdirs();
}
String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String prepend = "Video_" + timestamp + "_";
File videoFile = null;
try {
videoFile = File.createTempFile(prepend, ".jpg", newVideoFolder);
} catch (IOException e) {
e.printStackTrace();
}
String newFileName = videoFile.getAbsolutePath();
textureView.getBitmap();
FileOutputStream fos = new FileOutputStream(newFileName);
//returning the new file path.
return newFileName;
}
How do I get the corrected video from the texture view and then save it, like the Image method above?
This is not a recommended way; the cost of getBitmap on TextureView is high, and not likely suitable for 30fps video recording.
But if you really want to try, you need to feed the Bitmap to a MediaRecorder; you may be able to use MediaRecorder.getSurface() for that, then lock the Surface Canvas and draw your Bitmap into it.
However, I would not be surprised if the performance is poor, or if the MediaRecorder Surface won't accept RGB Bitmaps.
In general, you want to connect the camera API directly to the MediaRecorder or MediaCodec Surface. If you really need to edit frames in the middle, using the GPU is generally the most performant option, though it's a lot of code to write to do that.
I ended up changing the configuration on the Media Recorder, looks like I was trying to correct other orientation problems and caused this. So under my set up mediaRecorder I did this:
private void setupMediaRecorder() throws IOException {
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mMediaRecorder.setOutputFile(mVideoFileName);
mMediaRecorder.setVideoEncodingBitRate(100000000);
mMediaRecorder.setVideoFrameRate(30);
mMediaRecorder.setVideoSize(mVideoSize.getWidth(),mVideoSize.getHeight());
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
if (cameraCheck.contains("1") && mTotalRotation == 180){
//This corrects problems for the front facing camera when recording, the default settings work, so we do nothing here.
}else {
mMediaRecorder.setOrientationHint(mTotalRotation);
}
mMediaRecorder.prepare();
}
This checks if it is the front-facing camera and the phone is positioned at 180. If it is do nothing for correction, else use the correction.
I'm having problem with getting continuous successful QR decoding after PDF conversion. I keep getting,
"Exception in thread "main" com.google.zxing.FormatException."
My conversion attempts were done in:
PDFBox
public static BufferedImage convertPDFtoBufferedImageType2(String PDFPath) throws IOException{
PDDocument document = null;
try {
document = PDDocument.load(PDFPath);
PDPage firstPage = (PDPage) document.getDocumentCatalog().getAllPages().get(0);
return firstPage.convertToImage();
} catch (IOException ex) {
Logger.getLogger(PDF_Utility.class.getName()).log(Level.SEVERE, null, ex);
return null;
} finally {
if(document != null)
document.close();
}
}
Second Attempt with ghost4j
public static BufferedImage convertPDFtoBufferedImage(String PDFPath) throws IOException, RendererException, DocumentException{
System.setProperty("jna.library.path", "C:\\Program Files\\gs\\gs9.16\\bin\\");
PDFDocument document = new PDFDocument();
document.load(new File(PDFPath));
SimpleRenderer renderer = new SimpleRenderer();
renderer.setResolution(300);
List<Image> imgs = renderer.render(document);
Image im = imgs.get(0);
BufferedImage bi = new BufferedImage
(im.getWidth(null),im.getHeight(null),BufferedImage.TYPE_INT_RGB);
Graphics bg = bi.getGraphics();
bg.drawImage(im, 0, 0, null);
bg.dispose();
return bi;
}
My QR Decoder is:
public static String readQRCode(BufferedImage image, String charset, Map hintMap)
throws FileNotFoundException, IOException, NotFoundException, ChecksumException, FormatException {
Result qrCodeResult = null;
BinaryBitmap binaryBitmap = new BinaryBitmap(
new HybridBinarizer(new BufferedImageLuminanceSource(image)));
try{
qrCodeResult = new com.google.zxing.qrcode.QRCodeReader().decode(binaryBitmap,hintMap);
}catch(NotFoundException | FormatException e){ //attempt without hints
qrCodeResult = new com.google.zxing.qrcode.QRCodeReader().decode(binaryBitmap);
}
return qrCodeResult.getText();
}
And the reason why I called decode twice was because sometimes the "try harder"
hintMap.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
actually didn't catch the QR code, but the default did.
Anyways, these code snippets do catch most of my QR scans from a pile of documents, but there are times where it does not catch it at all. I even attempted to write it out as an image and then re-read it in:
ImageIO.write((RenderedImage) im, "png", new File("/path/to/my/img.png"));
Interestingly, http://zxing.org/w/decode.jspx does decode that output image, but my code couldn't.
I also tried different charset:
CHAR_SET = "UTF-8"; and CHAR_SET = "ISO-8859-1";
By getting Format Exceptions, the code was found, but "did not conform to the barcode's format rules. This could have been due to a mis-detection."
Apology for the messy code, but those attempts have gained majority of successful scans. 9/10 rate? Interestingly, sometimes another scanned copy of the same doc worked. Any help/advice/crazy voodoo combination is appreciated! Thanks!
EDIT: I got a sample (after whiting out the contents around. The real image has contents! Zxing website was able to catch this QR code too (with and without contents! (My program already ignored the other 1Ds at this same format and those with contents).
#Tilman Hausherr pointed out for the PDFBox default rendering size as low so I changed the default to 300dpi as he suggested. Overall, it worked for my case but definitely slowed down the speed. Will need to tweak my algorithm to run both a fast and this slower one as a backup.
return firstPage.convertToImage(BufferedImage.TYPE_4BYTE_ABGR, 300);
EDIT: Increased the success rate of catching barcodes, but did not successfully catch all. Increasing the dpi does not help.
It seems to me there are two ways to store an attachment in a NotesDocument.
Either as a RichTextField or as a "MIME Part".
If they are stored as RichText you can do stuff like:
document.getAttachment(fileName)
That does not seem to work for an attachment stored as a MIME Part. See screenshot
I have thousands of documents like this in the backend. This is NOT a UI issue where I need to use the file Download control of XPages.
Each document as only 1 attachment. An Image. A JPG file. I have 3 databases for different sizes. Original, Large, and Small. Originally I created everything from documents that had the attachment stored as RichText. But my code saved them as MIME Part. that's just what it did. Not really my intent.
What happened is I lost some of my "Small" pictures so I need to rebuild them from the Original pictures that are now stored as MIME Part. So my ultimate goal is to get it from the NotesDocument into a Java Buffered Image.
I think I have the code to do what I want but I just "simply" can't figure out how to get the attachment off the document and then into a Java Buffered Image.
Below is some rough code I'm working with. My goal is to pass in the document with the original picture. I already have the fileName because I stored that out in metaData. But I don't know how to get that from the document itself. And I'm passing in "Small" to create the Small image.
I think I just don't know how to work with attachments stored in this manner.
Any ideas/advice would be appreciated! Thanks!!!
public Document processImage(Document inputDoc, String fileName, String size) throws IOException {
// fileName is the name of the attachment on the document
// The goal is to return a NEW BLANK document with the image on it
// The Calling code can then deal with keys and meta data.
// size is "Original", "Large" or "Small"
System.out.println("Processing Image, Size = " + size);
//System.out.println("Filename = " + fileName);
boolean result = false;
Session session = Factory.getSession();
Database db = session.getCurrentDatabase();
session.setConvertMime(true);
BufferedImage img;
BufferedImage convertedImage = null; // the output image
EmbeddedObject image = null;
InputStream imageStream = null;
int currentSize = 0;
int newWidth = 0;
String currentName = "";
try {
// Get the Embedded Object
image = inputDoc.getAttachment(fileName);
System.out.println("Input Form : " + inputDoc.getItemValueString("form"));
if (null == image) {
System.out.println("ALERT - IMAGE IS NULL");
}
currentSize = image.getFileSize();
currentName = image.getName();
// Get a Stream of the Imahe
imageStream = image.getInputStream();
img = ImageIO.read(imageStream); // this is the buffered image we'll work with
imageStream.close();
Document newDoc = db.createDocument();
// Remember this is a BLANK document. The calling code needs to set the form
if ("original".equalsIgnoreCase(size)) {
this.attachImage(newDoc, img, fileName, "JPG");
return newDoc;
}
if ("Large".equalsIgnoreCase(size)) {
// Now we need to convert the LARGE image
// We're assuming FIXED HEIGHT of 600px
newWidth = this.getNewWidth(img.getHeight(), img.getWidth(), 600);
convertedImage = this.getScaledInstance(img, newWidth, 600, false);
this.attachImage(newDoc, img, fileName, "JPG");
return newDoc;
}
if ("Small".equalsIgnoreCase(size)) {
System.out.println("converting Small");
newWidth = this.getNewWidth(img.getHeight(), img.getWidth(), 240);
convertedImage = this.getScaledInstance(img, newWidth, 240, false);
this.attachImage(newDoc, img, fileName, "JPG");
System.out.println("End Converting Small");
return newDoc;
}
return newDoc;
} catch (Exception e) {
// HANDLE EXCEPTION HERE
// SAMLPLE WRITE TO LOG.NSF
System.out.println("****************");
System.out.println("EXCEPTION IN processImage()");
System.out.println("****************");
System.out.println("picName: " + fileName);
e.printStackTrace();
return null;
} finally {
if (null != imageStream) {
imageStream.close();
}
if (null != image) {
LibraryUtils.incinerate(image);
}
}
}
I believe it will be some variation of the following code snippet. You might have to change which mimeentity has the content so it might be in the parent or another child depending.
Stream stream = session.createStream();
doc.getMIMEEntity().getFirstChildEntity().getContentAsBytes(stream);
ByteArrayInputStream bais = new ByteArrayInputStream(stream.read());
return ImageIO.read(bais);
EDIT:
session.setConvertMime(false);
Stream stream = session.createStream();
Item itm = doc.getFirstItem("ParentEntity");
MIMEEntity me = itm.getMIMEEntity();
MIMEEntity childEntity = me.getFirstChildEntity();
childEntity.getContentAsBytes(stream);
ByteArrayOutputStream bo = new ByteArrayOutputStream();
stream.getContents(bo);
byte[] mybytearray = bo.toByteArray();
ByteArrayInputStream bais = new ByteArrayInputStream(mybytearray);
return ImageIO.read(bais);
David have a look at DominoDocument,http://public.dhe.ibm.com/software/dw/lotus/Domino-Designer/JavaDocs/XPagesExtAPI/8.5.2/com/ibm/xsp/model/domino/wrapped/DominoDocument.html
There you can wrap every Notes document
In the DominoDocument, there such as DominoDocument.AttachmentValueHolder where you can access the attachments.
I have explained it at Engage. It very powerful
http://www.slideshare.net/flinden68/engage-use-notes-objects-in-memory-and-other-useful-java-tips-for-x-pages-development
i have a code to decode a qrcode that take a image file and decode it. am using zxing library. but how can i make this capture qrcode from webcam and decode it. what are the changes i need to do?? can any one plz explain this step by step.
here is the code:
public class QrCodeDecoder
{
public String decode(File imageFile)
{
BufferedImage image;
try
{
image = ImageIO.read(imageFile);
}
catch (IOException e1)
{
return "io outch";
}
// creating luminance source
LuminanceSource lumSource = new BufferedImageLuminanceSource(image);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(lumSource));
// barcode decoding
QRCodeReader reader = new QRCodeReader();
Result result = null;
try {
result = reader.decode(bitmap);
}
catch (ReaderException e)
{
return "reader error";
}
return result.getText();
}
}
You are pretty far away from a solution, I don't think anyone can explain it "step by step". You will first need to find a library that is capable of grabbing an image from a webcam. You might start with this library, though I'm sure there are others.
Once you can capture an image, start to figure out if it is in a format that the above code expects. If you are lucky, it will be, if not you will have to convert between the two formats.
I know how to display local images in J2me. How can I display an online image? The following code (the image URL below is just for demo purposes) does not yield anything.
Image logo = Image.createImage("http://whatever.com/img/whatever.png");
Thanks
You need to load the image manually via a HttpConnection
Use this method to load the image:
public Image loadImage(String url) throws IOException {
HttpConnection hpc = null;
DataInputStream dis = null;
try {
hpc = (HttpConnection) Connector.open(url);
int length = (int) hpc.getLength();
byte[] data = new byte[length];
dis = new DataInputStream(hpc.openInputStream());
dis.readFully(data);
return Image.createImage(data, 0, data.length);
} finally {
if (hpc != null)
hpc.close();
if (dis != null)
dis.close();
}
}
See also this tutorial
Your first port of call for questions like this should be the MIDP 2.0 Javadocs.
There you will see that createImage has an overload which accepts an InputStream; this will do what you need.
Alternatively, you can download the entire image into a byte array and use yet another alternative form of createImage.