Reputation: 409
Recently I have got involved into Storlet project which is a middleware of OpenStack Swift Project. I do not intend to talk about Storlet but, in short Storlet running a java code on objects(files) that stored into swift object storage. Files read by the storlet and send to the java application in form of InputSream which means we don't direct access to files.
this is a sample code of a storlet which gets the image as an inputstream and make a thumbnail of it.
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.io.InputStream;
import java.io.OutputStream;
import org.openstack.storlet.common.IStorlet;
import org.openstack.storlet.common.StorletException;
import org.openstack.storlet.common.StorletInputStream;
import org.openstack.storlet.common.StorletLogger;
import org.openstack.storlet.common.StorletObjectOutputStream;
import org.openstack.storlet.common.StorletContainerHandle;
import org.openstack.storlet.common.StorletOutputStream;
import org.openstack.storlet.common.StorletUtils;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.awt.Image;
import java.awt.Transparency;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
public class ThumbnailStorlet implements IStorlet {
@Override
public void invoke(ArrayList<StorletInputStream> inputStreams,
ArrayList<StorletOutputStream> outputStreams,
Map<String, String> parameters, StorletLogger log)
throws StorletException {
log.emitLog("ThumbnailStorlet Invoked");
/*
* Get input stuff
*/
HashMap<String, String> object_md;
StorletInputStream storletInputStream = inputStreams.get(0);
InputStream thumbnailInputStream = storletInputStream.getStream();
object_md = storletInputStream.getMetadata();
/*
* Get output stuff
*/
StorletObjectOutputStream storletObjectOutputStream = (StorletObjectOutputStream)outputStreams.get(0);
OutputStream thumbnailOutputStream = storletObjectOutputStream.getStream();
/*
* Set the output metadata
*/
log.emitLog("Setting metadata");
storletObjectOutputStream.setMetadata(object_md);
/*
* Read Input to BufferedImage
*/
log.emitLog("Reading Input");
BufferedImage img = null;
try {
img = ImageIO.read(thumbnailInputStream);
} catch (Exception e) {
log.emitLog("Failed to read input stream to buffered image");
throw new StorletException("Failed to read input stream to buffered image " + e.getMessage());
} finally {
try {
thumbnailInputStream.close();
} catch (IOException e) {
log.emitLog("Failed to close input stream");
}
}
try {
thumbnailInputStream.close();
} catch (IOException e) {
log.emitLog("Failed to close input stream");
}
/*
* Convert
*/
log.emitLog("Converting");
int newH = img.getHeight()/8;
int newW = img.getWidth()/8;
int type = img.getTransparency() == Transparency.OPAQUE ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
BufferedImage thumbnailImage = new BufferedImage(newW, newH, type);
Graphics2D g = thumbnailImage.createGraphics();
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.drawImage(img, 0, 0, newW, newH, null);
g.dispose();
/*
* Write
*/
log.emitLog("Writing Output");
try {
ImageIO.write(thumbnailImage, "PNG" , thumbnailOutputStream);
} catch (Exception e) {
log.emitLog("Failed to write image to out stream");
throw new StorletException("Failed to write image to out stream " + e.getMessage());
} finally {
try {
thumbnailOutputStream.close();
} catch (IOException e) {
}
}
try {
thumbnailOutputStream.close();
} catch (IOException e) {
}
log.emitLog("Done");
}
}
Now .. I want to using some external application which running on images such as GDAL inside my java code ,assume code like the code above(not exactly doing the same as above). GDLA has some cli commands. For example this command
gdal_translate -of JPEG -co QUALITY=50 input.tif output.jpg
The input.tif has already stored into my object storage and storlet can read it and give it to me as inputstream, also I have some practice how to run external process inside java with java ProcessBuilder but, imagine I receive input.tif as InputStream not a file.
Next, I don't want to write back InputStream to local storage where my application running there because of lack of storage ( maybe the object are very large, more the 2GBs) and also degrading performance.
Is there any way in java to pass InputStream to external process as a file argument without storing it on disk.
I am running my code on Ubuntu Docker
Upvotes: 0
Views: 216
Reputation: 2546
I don´t think you can do that, a File
needs to be stored in a File system
(either local or remote) to be read. You could try to base a ByteArrayInputStream
to the reading process but the GDAL process should support that type of input:
https://gdal.org/programs/gdal_translate.html#cmdoption-gdal_translate-arg-src_dataset
As per the GDAL documentation, it does not seem possible:
<src_dataset>
The source dataset name. It can be either file name, URL of data source or subdataset name for multi-dataset files.
Upvotes: 1