Get width and height of Image app engine - java

ImagesService imagesService = ImagesServiceFactory.getImagesService();
BlobKey bk = currentProfile.getProfileBlobKey();
Image oldImage = ImagesServiceFactory.makeImageFromBlob(bk);
Transform resize = ImagesServiceFactory.makeResize(500, 500);
Image newImage = imagesService.applyTransform(resize, oldImage);
int imageWidth = newImage.getWidth();
int imageHeight = newImage.getHeight();
This code doesn't seem to work since ImagesServiceFactory.makeImageFromBlob(bk); doesn't return a real Image. Does anyone know a workaround for this? This seems to be the expected behavior. This issue is discussed here but they don't have a solution for getting the height and width just the byte[]

Try this:
FileService fileService = FileServiceFactory.getFileService();
AppEngineFile blobFile = fileService.getBlobFile(blobKey);
FileReadChannel readChannel = fileService.openReadChannel(blobFile, false);
byte[] imageData = getBytes(Channels.newInputStream(readChannel));
Image oldImage = ImagesServiceFactory.makeImage(imageData);
// now you have the real Image
and this little snippet for reading an input stream:
public static byte[] getBytes(InputStream is) throws IOException {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int len;
byte[] data = new byte[10000];
while ((len = is.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, len);
}
buffer.flush();
return buffer.toByteArray();
}

have you tried the ImageReader Class?

Related

Java Android - JPEG Image rotation

I'm working on an application to capture images but I'd like to rotate a JPEG image before saving it, I already saw this link :
Android Rotate Picture before saving
This is what I'm doing right now.
ByteBuffer byteBuffer = mImage.getPlanes()[0].getBuffer();
byte[] bytes = new byte[byteBuffer.remaining()];
byteBuffer.get(bytes);
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(mImageFileName);
fileOutputStream.write(bytes);
} catch (IOException e) {
e.printStackTrace();
}
I tried this to rotate the image like this :
// Bytes array to bitmap and matrix rotation
Bitmap sourceBitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
Matrix m = new Matrix();
m.setRotate((float)90, sourceBitmap.getWidth(), sourceBitmap.getHeight());
Bitmap targetBitmap = Bitmap.createBitmap(sourceBitmap, 0, 0, sourceBitmap.getWidth(), sourceBitmap.getHeight(), m, true);
// Bitmap to bytes array
int size = targetBitmap.getRowBytes() * targetBitmap.getHeight();
ByteBuffer targetByteBuffer = ByteBuffer.allocate(size);
targetBitmap.copyPixelsToBuffer(targetByteBuffer);
bytes = targetByteBuffer.array();
But when I look into the file into my gallery, I cannot read it, the image seems broken.
EDIT: Doesn't work on Android 7.1.1 :/ Any idea ? Can I do something similar for a video record?
You are Coverting Your Bitmap to bytes array,
Now You stop That way save Bitmap directly to File
Bitmap sourceBitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
Matrix m = new Matrix();
m.setRotate((float)90, sourceBitmap.getWidth(), sourceBitmap.getHeight());
Bitmap rotatedBitmap= Bitmap.createBitmap(sourceBitmap, 0, 0, sourceBitmap.getWidth(), sourceBitmap.getHeight(), m, true);
// Save Bitmap directly to the file
String filename = "hello.jpg";
File sd = Environment.getExternalStorageDirectory();
File dest = new File(sd, filename);
try {
FileOutputStream out = new FileOutputStream(dest);
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
This little change apparently did the trick ! Thanks Nikunj !
ByteBuffer byteBuffer = mImage.getPlanes()[0].getBuffer();
byte[] bytes = new byte[byteBuffer.remaining()];
byteBuffer.get(bytes);
Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
Matrix matrix = new Matrix();
matrix.setRotate((float)90, bitmap.getWidth(), bitmap.getHeight());
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(mImageFileName);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fileOutputStream);
fileOutputStream.flush();
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}

Fast way to convert BufferedImage to Jpeg

i'm trying to stream a camera feed over the network,
the main problem that i encountered is the ImageIO latency to encode BufferedImage to jpg
Here is my code:
long cameraTimer = 0, cameraTimerFPS = 0, cameraFPS = 0, cameraSize = 0;
while (!Thread.interrupted()) {
cameraTimer = System.currentTimeMillis();
BufferedImage imageBuffered = // Get the image
ImageWriter imageWriter = ImageIO.getImageWritersByFormatName("jpg").next();
ImageWriteParam imageWriterParameter = imageWriter.getDefaultWriteParam();
imageWriterParameter.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
imageWriterParameter.setCompressionQuality(cameraCompression / 100F);
ByteArrayOutputStream imageBuffer = new ByteArrayOutputStream();
imageWriter.setOutput(new MemoryCacheImageOutputStream(imageBuffer));
IIOImage outputImage = new IIOImage(imageBuffered, null, null);
imageWriter.write(null, outputImage, imageWriterParameter); // ~600ms latency
imageWriter.dispose();
// Send the image
cameraSize += imageBuffer.size();
cameraTimer = System.currentTimeMillis() - cameraTimer;
cameraTimer = (1000 / cameraFramerate) - cameraTimer;
if (cameraTimerFPS - System.currentTimeMillis() < -1000) {
System.out.println(String.format("Avg Image Size: %s", formatBytes(cameraSize / (cameraFPS + 1))));
System.out.println(String.format("Frame per second: %s", cameraFPS));
cameraTimerFPS = System.currentTimeMillis();
cameraSize = 0;
cameraFPS = 0;
}
cameraFPS++;
if (cameraTimer > 0) {
Thread.sleep(cameraTimer);
}
}
So, my question is how can i get rid of the ImageIO api?
i searched on internet and i didn't find any library that can replace the ImageIO.

convert Image to byte

I want to resize an image and then to write it back to outputstream, for this I need to convert the scaled image into bytes, how can I convert it?
ByteArrayInputStream bais = new ByteArrayInputStream(ecn.getImageB());
BufferedImage img = ImageIO.read(bais);
int scaleX = (int) (img.getWidth() * 0.5);
int scaleY = (int) (img.getHeight() * 0.5);
Image newImg = img.getScaledInstance(scaleX, scaleY, Image.SCALE_SMOOTH);
outputStream.write(newImg); //cannot resolve
how to fix outputStream.write(newImg)???
Use this method for scaling:
public static BufferedImage scale(BufferedImage sbi,
int imageType, /* type of image */
int destWidth, /* result image width */
int destHeight, /* result image height */
double widthFactor, /* scale factor for width */
double heightFactor /* scale factor for height */ )
{
BufferedImage dbi = null;
if(sbi != null) {
dbi = new BufferedImage(destWidth, destHeight, imageType);
Graphics2D g = dbi.createGraphics();
AffineTransform at = AffineTransform.getScaleInstance(widthFactor, heightFactor);
g.drawRenderedImage(sbi, at);
}
return dbi;
}
Then you'll have a BufferedImage which you can write to a byte array
public static byte[] writeToByteArray(BufferedImage bi, String dImageFormat) throws IOException, Exception {
byte[] scaledImageData = null;
ByteArrayOutputStream baos = null;
try {
if(bi != null) {
baos = new ByteArrayOutputStream();
if(! ImageIO.write(bi, dImageFormat, baos)) {
throw new Exception("no appropriate writer found for the format " + dImageFormat);
}
scaledImageData = baos.toByteArray();
}
} finally {
if(baos != null) {
try {
baos.close();
} catch(Exception e) {
e.printStackTrace();
}
}
}
return scaledImageData;
}
Include this line and check:-
ByteArrayOutputStream outputStream=new ByteArrayOutputStream();
ImageIO.write(originalImage, "jpg", outputStream);
byte[] imageInByte=outputStream.toByteArray();

Converting Multiple Images to Byte Array

i trying to give responce as multiple images byte array to another application.
I get the vehicle images list from database and convert to byte array.
ByteArrayInputStream instream = null;
ServletOutputStream out = null ;
for(Vehicle vehicle : vehicleList)
{
byte[] imageInByte = null;
VehicleImage vehicleImage=VehicleImagePeer.doSelectFirst(c.add(VehicleImagePeer.VEHICLE_ID, getId()));
c.clear();
String path = TaxiApp.getConfigValue("IMAGE.PATH")+vehicleImage.getPath();
System.out.print(path);
BufferedImage originalImage = ImageIO.read(new File(path));
ImageIO.write(originalImage, "png", baos);
imageInByte = baos.toByteArray();
baos.close();
using this code i convert all the images to byte Array.
As Now i need to give response.
i used this code to response
out = response.getOutputStream();
response.setContentLength(imageInByte.length);
response.setCharacterEncoding(Charset.forName("UTF-8").name());
int bufferSize = response.getBufferSize();
byte[] buffer = new byte[bufferSize];
instream = new ByteArrayInputStream(imageInByte);
TaxiApp.logprintf("Total page size in bytes: %s and default response bufferSize in bytes: %s%n", new Object[]
{
Integer.valueOf(imageInByte.length), Integer.valueOf(bufferSize)
});
int length = 0;
while ((length = instream.read(buffer, 0, bufferSize)) != -1)
{
out.write(buffer, 0, length);
out.flush();
}
Here is a problem for me.
The response can send the first image byte array only.but i need to send all the image byte Array...please sort out this problem.

Sending an image as a byte array between client and server

I can successfully send and draw a resized, 125 x 125 image from my client to my server. only problem is, thats way too small. I want to be able to send a larger image but the byte array can't handle it and I get a java heap exception. currently I'm using this to interpret my image. Is there a more efficient way?
On the client
screenShot = new Robot().createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()));
screenShot = resize(screenShot, 125, 125);
ByteArrayOutputStream byteArrayO = new ByteArrayOutputStream();
ImageIO.write(screenShot,"PNG",byteArrayO);
byte [] byteArray = byteArrayO.toByteArray();
out.writeLong(byteArray.length);
out.write(byteArray);
resize method as called above.
public static BufferedImage resize(BufferedImage img, int newW, int newH) {
int w = img.getWidth();
int h = img.getHeight();
BufferedImage dimg = new BufferedImage(newW, newH, img.getType());
Graphics2D g = dimg.createGraphics();
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.drawImage(img, 0, 0, newW, newH, 0, 0, w, h, null);
g.dispose();
return dimg;
}
server that interprets the image
in = new DataInputStream(Client.getInputStream());
long nbrToRead = in.readLong();
byte[] byteArray = new byte[(int) nbrToRead];
int nbrRd = 0;
int nbrLeftToRead = (int) nbrToRead;
while (nbrLeftToRead > 0) {
int rd = in.read(byteArray, nbrRd, nbrLeftToRead);
if (rd < 0)
break;
nbrRd += rd; // accumulate bytes read
nbrLeftToRead -= rd;
}
ByteArrayInputStream byteArrayI = new ByteArrayInputStream(
byteArray);
image = ImageIO.read(byteArrayI);
if (image != null) {
paint(f.getGraphics(), image);
} else {
System.out.println("null image.");
}
as you can tell the code is massive and most likely inefficient. I could send 1/10 of the image 10 times for with and height, drawing on those parts instead but I wanted to know if there was an easier way to do this.
You should probably think of transferring data as stream over the network. You can make use of third-party libraries like RMIIO . In case you can make data transfer using web service then you can look at Message Transmission Optimization Mechanism (MTOM) which lets you transfer data as stream in more efficient manner. For more details please have a look here
this worked for me
public class ImageClient {
public static void main(String[] args) throws AWTException, IOException {
BufferedImage screenShot = new Robot().createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()));
Socket socket = new Socket("localhost",11111);
MemoryCacheImageOutputStream byteArrayO = new MemoryCacheImageOutputStream(socket.getOutputStream());
ImageIO.write(screenShot, "PNG", byteArrayO);
byteArrayO.flush();
socket.close();
}
}
public class ImageServer {
public static void main(String[] args) throws IOException, ClassNotFoundException {
ServerSocket ss = new ServerSocket(11111);
try{
Socket s = ss.accept();
InputStream is = s.getInputStream();
MemoryCacheImageInputStream ois = new MemoryCacheImageInputStream(is);
ImageIO.read(ois);
s.close();
}finally{
ss.close();
}
}
}

Categories

Resources