FileNotFoundException when reading a BufferedImage - java

I'm trying to crop an image received from a form upload. Before I crop it I save it, then I retrieve it again as a BufferedImage (because I don't know how to turn a part into a buffered Image). I then crop this image, but when I try to save it again I get a java.io.FileNotFoundException (access denied)
The first image gets saved correctly, I get the exception when I try to pull it back.
Is it possible to turn my part into a buffered image and then save it? Instead of doing double work. or else is there some fix to my below code.
String savePath = "path";
File fileSaveDir = new File(savePath);
if (!fileSaveDir.exists()) {
fileSaveDir.mkdir();
}
for (Part part : request.getParts()) {
//functionality to ormit non images
String fileName = extractFileName(part);
part.write(savePath + "/" + fileName);
String imagePath = savePath + "/" + fileName;
BufferedImage img = null;
try {
img = ImageIO.read(new File(imagePath));
img = img.getSubimage(0, 0, 55, 55);
ImageIO.write(img, "jpg", fileSaveDir);
} catch (IOException e) {
System.out.println(e);
}
}

ImageIO.write((RenderedImage im, String formatName, File output));
Parameters:
im a RenderedImage to be written.
formatName a String containg the informal name of the format.
output a File to be written to.
As per documentation output file parameter is the file object where it would be image written where you have passed the parent directory file object.

Related

Multiple images to pdf. How do i string multiple images so bitmapfactory can decode

My user inputs a folder name. Then takes pictures which are saved in the folder. I want to take all the files in the folder which will all be jpg files and create one pdf. There wouldnt be more than 5 images in the folder.
How do i extract all of the files out of the folder so i can pass the strings to the bitmapfacory.decodeFile
So far i have tried the following code.
To test the pdfcreater i named the jpg something in the code. Then took a pic and renamed it the same. It created the pdf with my image.
I have also tried the currentPhotoPath and that works for the one current photo.
The folder that holds all the JPG's is folderName1
private void buttonCreatePDF() {
Intent folInt = getIntent();
String folderName1 = folInt.getStringExtra("Value");
String file1 = directoryPDF + folderName1 ;
Bitmap bitmap = BitmapFactory.decodeFile(file1);
PdfDocument pdfDocument = new PdfDocument();
PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo.Builder(bitmap.getWidth(), bitmap.getHeight(), 1).create();
PdfDocument.Page page = pdfDocument.startPage(pageInfo);
page.getCanvas().drawBitmap(bitmap, 0, 0, null);
pdfDocument.finishPage(page);
String pdfFile = directoryPDF + "/" + folderName1 + ".pdf";
File myPDFfile = new File(pdfFile);
try {
pdfDocument.writeTo(new FileOutputStream(myPDFfile));
Toast.makeText(this, "PDF file generated successfully.", Toast.LENGTH_SHORT).show();
} catch (IOException e) {
e.printStackTrace();
}
pdfDocument.close();
}
}

Create image file from raw string data

for example, i have String like this:
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHQAAAB0CAYAAABUmhYnAAAEd0lEQVR4Xu2c0ZLjIAwEk///6GzVvZlspWtWksNRnVcwiGmNwHaS5+v1ej38HKPAU6DHsPy3EIGexVOgh/EUqEBPU+Cw9biHCvQwBQ5bjg4V6GEKHLYcHSrQwxQ4bDk6VKCHKXDYcnSoQA9T4LDllB36fD5vlWR9fUvz0+ve9fp0/O7FU7w0n0CXhBSoDiXTRO06FBKKBLLkLvlGgkTp+UvndPzu/ul46Xq7x2/fQ8kR0wtOBaL+1J6uZ+3fPb5Aw0PRtxOWEkigAr3mCJUMuk9cM45uG3ZvJwel8dN4byW8+r1cgWYPVgRaLIlpwqWCT1cgHbr8skOgYUqkgtHwVYfQKZTiTW8rdCgQFWjtt2Pjty3TGdztOB0aHlosuVcHpglJ+h3nUFow7bE6dDOHCjRN2fBty917qEAF+jEHaI+bTlhK0Nsf/aUBpXtYdXy6noDS9dTePf74oYgWRO3dC6b57k6o7vUJFAh3Cz6dMAIV6FWB9FCQlry1f/ejQXLgt9eX6tXu0DSAtL9APysm0OYHI2mCUgVKxxOoQNOcubc/7XnF5yj3LuYPs5Ud+oc5Ry8R6GEpK1CBjlaMuwcvl1xyBC2I8im9T0xva6pPbtL1V+MjPQW6KEQJRAlAggs0vK2oCibQ4g9+LbnXb96THlQBvl5y0yclqYNQAKgAVGIJQHWPpfjf4uv+bUsagECvClCCkL46VIdecyQtKZRhlKGW3OG3LekeQ0DSBOk+1VLCdbdTAqfzlUuuQFPJe/fM9kORQAV6UYBKJslF11NJS0s8xZO2U3zpeO0lNw2g2+HV8dLbKJov1aMKWKDFfyITKKRsegqmjE7H06FpTRHoRwUoQUnu9pJLh4z0EFMdjwRI46ESWwVC8VK7QMN/TRHookDqCB1Knry261AdmmXMdG86xabzd49H83fP1+5QWkB3e7sg4eu06nra46++4K4uqHp9uyACrSKpXS/Q5kMRnUJruN6vnr7Po/VMn9KrepX3UBKgGmD1UVw6P61HoKmi0F+HfhZIhy766NDhU2F66CEgzQXjQRUjjb8aX7tDaYFpwKkgAi0SSAUXaO0Pjkk/HUoKFQ9p0wm/hjcONC2B6W3B24KKv1ZLx0vzgfQoFsyHQJe3LQINHUEZrUNre6wO1aHLw+AvO5QOHdReLbE0/vSeedyhKBWUDh00XpoAAg2/EkIAqD0FlPYXqEDp3Pix/b8/FKUOIMem7fR6j8Yr0fvlYoEWK4JAw0dplOE6dLnrqH5JrCp4NcMFejPQ6h7RnTAUT/eTKkpYiidtH99D04C6bwvS+QX65W8sUMkVaKgAlcRwuLfuNL5Ah/fQKkC6Pi2JKXB6NEjxUTslKF1P7e17KE1YbRfoZwUFuuijQ4v/l5s6VocOOzQFYv9ZBcoldzY8R08VEGiq2Ob9Bbo5oDQ8gaaKbd5foJsDSsMTaKrY5v0FujmgNDyBpopt3l+gmwNKwxNoqtjm/QW6OaA0PIGmim3eX6CbA0rDE2iq2Ob9Bbo5oDS8H8eCMw7yCzx+AAAAAElFTkSuQmCC
i want to convert it back to an image file. here's what i've tried:
public void dumpFromRawData(String rawData, String wheretoPut) throws Exception{
byte[] imageByte = rawData.getBytes();
BufferedImage bufferedImage = ImageIO.read(new ByteArrayInputStream(imageByte));
File file = new File(wheretoPut);
ImageIO.write(bufferedImage, "png", file);
}
where rawData is the example string above, and wheretoPut is the new image directory.. for example D:\\image.png
but when i run it, it gives me this:
Exception in thread "main" java.lang.IllegalArgumentException: image == null!
at javax.imageio.ImageTypeSpecifier.createFromRenderedImage(ImageTypeSpecifier.java:925)
at javax.imageio.ImageIO.getWriter(ImageIO.java:1592)
at javax.imageio.ImageIO.write(ImageIO.java:1520)
how could i resolve this? or is this not the correct way to convert it back to image?
The data of your image seems to be base64 encoded so you can not just convert this string into a byte array.
So you should use something like:
byte[] imageByte = Base64.decode(rawData, Base64.DEFAULT);
i finally found the solution. Thans #Chris623 for enlightening me :D
first, i need to separate the 'header' of the string file.. the data:image/png;base64, string, and then decode it to byte[]
String separator = ",";
String encoded = rawData.split(separator)[1];
byte[] decodedByte = Base64.getDecoder().decode(encoded.getBytes(StandardCharsets.UTF_8));
and then the rest of process is still the same.. the full method looks like this:
public void dumpFromRawData(String rawData, String wheretoPut, String fileName) throws Exception{
String separator = ",";
if(rawData.contains(separator)) {
// use this when the decoded string contains "," separator, like data:image/png;base64,
String encoded = rawData.split(separator)[1];
byte[] decodedByte = Base64.getDecoder().decode(encoded.getBytes(StandardCharsets.UTF_8));
// you can use this
// Path destinationFile = Paths.get(wheretoPut, fileName);
// Files.write(destinationFile, decodedByte);
// or this
BufferedImage bufferedImage = ImageIO.read(new ByteArrayInputStream(decodedByte));
File file = new File(wheretoPut+fileName);
ImageIO.write(bufferedImage, "png", file);
System.out.println("File has been Written as " + wheretoPut + fileName);
} else {
System.out.println("i haven't think about it yet.");
}
}

Why to upload file to AWS by writing to disk first?

This example uses a file which most likely resides not in RAM:
http://docs.aws.amazon.com/AmazonS3/latest/dev/UploadObjSingleOpJava.html
but I already got a buffered file from a certain client request and in the code below, this file gets written to disk, but why ? it makes the whole process slow by writing to disk, can't I avoid it?
EDIT (Below is explanation of what I am trying to achieve):
A user's image is uploaded then scaled by the server and then saved on the server's disk and only then this scaled image is sent to AWS, afterwards the user gets an aws link where the image resides on the amazon server.
public void transferToS3(String region, String bucket, String entity, String resolution, String filename, BufferedImage bufferedImage) {
if (bufferedImage != null) {
String objectpath = "/" + "images" + "/" + entity + "/" + resolution + "/" + filename + "." + "png";
Path tmpFile = null;
try {
tmpFile = Files.createTempFile(imagesPath, "tmp_", ".png");
} catch (IOException e) {
e.printStackTrace();
}
tmpFile.toFile().deleteOnExit();
try {
ImageIO.write(bufferedImage, "png", tmpFile.toFile());
S3AsyncClient client = S3AsyncClient.builder().region(Region.of(region)).build();
CompletableFuture<PutObjectResponse> future =
client.putObject(PutObjectRequest.builder()
.bucket(bucket)
.key(objectpath)
.contentType("image/png")
.build(),
AsyncRequestProvider.fromFile(tmpFile.toAbsolutePath()));
Path finalTmpFile = tmpFile;
future.whenComplete((resp, err) -> {
try {
if (resp != null) {
logger.debug(resp.toString());
} else {
logger.error(err.toString());
}
Files.deleteIfExists(finalTmpFile.toAbsolutePath());
} catch (IOException e) {
e.printStackTrace();
} finally {
FunctionalUtils.invokeSafely(client::close);
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
Scaling routine returns a scaled BufferedImage which is then used in the transferToS3 method.
public BufferedImage scale(int width, int height, BufferedImage bufferedImage) {
BufferedImage scaledBufferedImage = null;
if (bufferedImage != null) {
Image image = bufferedImage.getScaledInstance(width, height, Image.SCALE_SMOOTH);
scaledBufferedImage = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_ARGB);
scaledBufferedImage.getGraphics().drawImage(image, 0, 0, null);
}
return scaledBufferedImage;
}
The 2 above together:
BufferedImage scaledBufferedImage = imageService.scale(width, height finalBufferedImage);
imageService.transferToS3(region, bucket, name, k, file, scaledBufferedImage);
You can do whatever you wish with the data stream from the request. Feel free to scale the image in memory and send it back in the response. The example you linked writes the file to disk because this is by far the most common scenario. It also allows the author to focus on the details of uploading a file without polluting the example with unrelated code.
Note that bufferedImage is not a file. It is a stream. I suspect the author saved the image to disk in order to avoid assuming anything about the size of the image. If the image is too large to fit in RAM, then you will have difficulties doing the scaling in memory.

To view Tiff image on web and do image processing on it using java applet

I want to browse and display big Tiff image on web using HTML and Javascript and do image processing on it using java applet.
All the image loading and processing should be on client machine.
For viewing of image I want to use HTML and Javascript.
For image processing I want to use java applet.
i have face same prob as u face. As we all know that tiff image can't be visible on web browser. so we have to convert into Png or any other format.
File file = new File(path_of_tiff_file, name_of_tiff_file);
String newName = file.getName();
// if (!file.exists()) {
item.write(file);
if(item.getName().toLowerCase().indexOf(".tif") >=0 || item.getName().toLowerCase().indexOf(".tiff") >=0 ){
newName =item.getName().subSequence(0, item.getName().lastIndexOf(".")) + ".png";
File newFile = new File(path , newName);
BufferedImage image= null;
try {
image = Sanselan.getBufferedImage(file);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
Sanselan.writeImage(image, newFile, ImageFormat.IMAGE_FORMAT_PNG, new Hashtable());
}

How do you access an attachment stored as MIME Part?

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

Categories