NullPointerException when convert and save Image file on Android device - java

I'm trying to save a Image type data as a jpg file to SD card, what I plan to do is first converting it to Bitmap, compress bitmap as jpeg format, then use FileOutputStream to save it to SD card.
Here's my code:
File imagefile = new File(sdCardPath, "image.jpg");
Image image = fromFrame.getImage();
ByteBuffer bbuffer = image.getPlanes()[0].getBuffer();
byte[] byts = new byte[bbuffer.capacity()];
bbuffer.get(byts);
Bitmap bitmapImage = BitmapFactory.decodeByteArray(byts, 0, byts.length, null);
try{
FileOutputStream out = new FileOutputStream(imagefile);
bitmapImage.compress(Bitmap.CompressFormat.JPEG, 100, out);
out.flush();
out.close();
} catch (FileNotFoundException e) {
Log.v(TAG, "FileNotFoundExceptionError " + e.toString());
} catch (IOException e) {
Log.v(TAG, "IOExceptionError " + e.toString());
}
It gives error:
java.lang.NullPointerException: Attempt to invoke virtual method 'boolean
android.graphics.Bitmap.compress(android.graphics.Bitmap$CompressFormat,
int, java.io.OutputStream)' on a null object reference
Is there anything I missed or did it wrong?

It turns out that the image file has to be re-organized and as for Depth16 file, every pixel has 16 bits of data, so the code to convert it into a jpg file is:
Image depthimage = fromFrame.getImage();
int imwidth = depthImage.getWidth();
int imheight = depthImage.getHeight();
Image.Plane plane = depthImage.getPlanes()[0];
ShortBuffer shortDepthBuffer = plane.getBuffer().asShortBuffer();
File sdCardFile = Environment.getExternalStorageDirectory();
File file = new File(sdCardFile, "depthImage.jpg");
Bitmap disBitmap = Bitmap.createBitmap(imwidth, imheight, Bitmap.Config.RGB_565);
for (int i = 0; i < imheight; i++) {
for (int j = 0; j < imwidth; j++) {
int index = (i * imwidth + j) ;
shortDepthBuffer.position(index);
short depthSample = shortDepthBuffer.get();
short depthRange = (short) (depthSample & 0x1FFF);
byte value = (byte) depthRange ;
disBitmap.setPixel(j, i, Color.rgb(value, value, value));
}
}
Matrix matrix = new Matrix();
matrix.setRotate(90);
Bitmap rotatedBitmap = Bitmap.createBitmap(disBitmap, 0, 0, imwidth, imheight, matrix, true);
try {
FileOutputStream out = new FileOutputStream(file);
rotatedBitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
MainActivity.num++;
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
I also rotate the picture to make it easier to review on mobile devices

Related

how convert multiple images to single PDF from folder in android?

I want to make android app to merge multiple image from single folder into single pdf file.
ex :
folder name :
- images
- 1.jpg
- 2.jpg
- 3.jpg
- 4.jpg
- 5.jpg
there are 5 images are in folder named images
how can i make pdf of that images?
if anyone have possible solution then please comment answer :)
Try this after 4.4 version it will work.
private void createPDF() {
final File file = new File(uploadFolder, "AnswerSheet_" + queId + ".pdf");
final ProgressDialog dialog = ProgressDialog.show(this, "", "Generating PDF...");
dialog.show();
new Thread(() -> {
Bitmap bitmap;
PdfDocument document = new PdfDocument();
// int height = 842;
//int width = 595;
int height = 1010;
int width = 714;
int reqH, reqW;
reqW = width;
for (int i = 0; i < array.size(); i++) {
// bitmap = BitmapFactory.decodeFile(array.get(i));
bitmap = Utility.getCompressedBitmap(array.get(i), height, width);
reqH = width * bitmap.getHeight() / bitmap.getWidth();
Log.e("reqH", "=" + reqH);
if (reqH < height) {
// bitmap = Bitmap.createScaledBitmap(bitmap, reqW, reqH, true);
} else {
reqH = height;
reqW = height * bitmap.getWidth() / bitmap.getHeight();
Log.e("reqW", "=" + reqW);
// bitmap = Bitmap.createScaledBitmap(bitmap, reqW, reqH, true);
}
// Compress image by decreasing quality
// ByteArrayOutputStream out = new ByteArrayOutputStream();
// bitmap.compress(Bitmap.CompressFormat.WEBP, 50, out);
// bitmap = BitmapFactory.decodeStream(new ByteArrayInputStream(out.toByteArray()));
//bitmap = bitmap.copy(Bitmap.Config.RGB_565, false);
//Create an A4 sized page 595 x 842 in Postscript points.
//PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo.Builder(595, 842, 1).create();
PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo.Builder(reqW, reqH, 1).create();
PdfDocument.Page page = document.startPage(pageInfo);
Canvas canvas = page.getCanvas();
Log.e("PDF", "pdf = " + bitmap.getWidth() + "x" + bitmap.getHeight());
canvas.drawBitmap(bitmap, 0, 0, null);
document.finishPage(page);
}
FileOutputStream fos;
try {
fos = new FileOutputStream(file);
document.writeTo(fos);
document.close();
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
runOnUiThread(() -> {
dismissDialog(dialog);
});
}).start();
}
If you want to create a pdf file with multiple images you can use PdfDocument from Android. Here is a demo:
private void createPDFWithMultipleImage(){
File file = getOutputFile();
if (file != null){
try {
FileOutputStream fileOutputStream = new FileOutputStream(file);
PdfDocument pdfDocument = new PdfDocument();
for (int i = 0; i < images.size(); i++){
Bitmap bitmap = BitmapFactory.decodeFile(images.get(i).getPath());
PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo.Builder(bitmap.getWidth(), bitmap.getHeight(), (i + 1)).create();
PdfDocument.Page page = pdfDocument.startPage(pageInfo);
Canvas canvas = page.getCanvas();
Paint paint = new Paint();
paint.setColor(Color.BLUE);
canvas.drawPaint(paint);
canvas.drawBitmap(bitmap, 0f, 0f, null);
pdfDocument.finishPage(page);
bitmap.recycle();
}
pdfDocument.writeTo(fileOutputStream);
pdfDocument.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private File getOutputFile(){
File root = new File(this.getExternalFilesDir(null),"My PDF Folder");
boolean isFolderCreated = true;
if (!root.exists()){
isFolderCreated = root.mkdir();
}
if (isFolderCreated) {
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(new Date());
String imageFileName = "PDF_" + timeStamp;
return new File(root, imageFileName + ".pdf");
}
else {
Toast.makeText(this, "Folder is not created", Toast.LENGTH_SHORT).show();
return null;
}
}
Here images is the ArrayList of the images with path.
Break your problem down into smaller problems. It's a fairly simple application.
Get the folder name from the user. See the native file open dialog to find a folder. See here.
Search its files for images
Create a pdf of the images. Use a library such as apache pdfbox.
Use this iText library
Create a document
String FILE = "{folder-path}/FirstPdf.pdf";
Document document = new Document();
PdfWriter.getInstance(document, new FileOutputStream(FILE));
document.open();
Add image in the document
try {
// get input stream
String fileName = "OfflineMap/abc.jpg";
String path =
Environment.getExternalStorageDirectory()+"/"+fileName;
File file = new File(path);
FileInputStream fileInputStream = new FileInputStream(file);
InputStream ims = getAssets().open("myImage.png");
Bitmap bmp = BitmapFactory.decodeStream(ims);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.PNG, 100, stream);
Image image = Image.getInstance(stream.toByteArray());
document.add(image);
document.close();
}
catch(IOException ex)
{
return;
}

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

Steganography, only jpg as input works, when using png the resulting image looks strange

I built a little java program that hides messages in an image using the least significant bit method. It works fine when inputting a jpg file. The output may be png or jpg. When inputting a png though, the result looks very stange.
Here are the original and the result images respectively:
public abstract class Builder{
public static void leastSignificantBitEncryption(String imageSource, String message, String newPath) {
BufferedImage image = returnImage(imageSource);
//prepare variables
String[] messageBinString = null;
String[] pixelBinString = null;
final byte[] messageBin = message.getBytes(StandardCharsets.UTF_8);
final byte[] pixelsBin = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
//convert message and image to binary string array
try {
messageBinString = stringToBinaryStrings(messageBin);
pixelBinString = stringToBinaryStrings(pixelsBin);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
String[] messageBinStringCut = splitIn2Bit(messageBinString); //split message binary into 2 bit strings
String[] pixelBinStringNew = pixelBinString.clone(); //insert 2 bit strings in last 2 bits of bytes from bitmap
insert2Bit(messageBinStringCut, pixelBinStringNew);
byte[] pixelsBinNew = stringArrayToByteArray(pixelBinStringNew); //Convert string array to byte array
try { //Create new image out of bitmap
int w = image.getWidth();
int h = image.getHeight();
BufferedImage imageNew = new BufferedImage(w, h, BufferedImage.TYPE_3BYTE_BGR);
imageNew.setData(Raster.createRaster(imageNew.getSampleModel(), new DataBufferByte(pixelsBinNew, pixelsBinNew.length), new Point()));
File imageFile = new File(newPath);
ImageIO.write(imageNew, "png", imageFile);
} catch (IOException e) {
e.printStackTrace();
}
}
private static String[] stringToBinaryStrings(byte[] messageBin) throws UnsupportedEncodingException{
String[] bytes = new String[messageBin.length];
int i = 0;
for(byte b : messageBin) {
bytes[i] = String.format("%8s", Integer.toBinaryString(b & 0xFF)).replace(' ', '0');
i++;
}
return bytes;
}
private static String binaryStringsToString(String[] messageBin) throws UnsupportedEncodingException{
StringBuilder stringBuilder = new StringBuilder();
int i = 0;
while(messageBin[i] != null) {
stringBuilder.append((char) Integer.parseInt(messageBin[i], 2));
i++;
}
return stringBuilder.toString();
}
private static BufferedImage returnImage(String imageSource) {
try{
try {
return ImageIO.read(new URL(imageSource));
} catch (MalformedURLException e) {
return ImageIO.read(new File(imageSource));
}
} catch (IOException ioe) {
ioe.printStackTrace();
return null;
}
}
private static byte[] stringArrayToByteArray(String[] stringArray) {
byte[] byteArray = new byte[stringArray.length];
for(int i = 0; i < stringArray.length; i++) {
byteArray[i] = (byte) Integer.parseInt(stringArray[i], 2);
}
return byteArray;
}
private static String[] splitIn2Bit(String[] inputArray) {
String[] outputArray = new String[inputArray.length * 4];
for(int i = 0; i < outputArray.length; i += 4) {
String[] splitByte = inputArray[i / 4].split("(?<=\\G..)");
outputArray[i] = splitByte[0];
outputArray[i + 1] = splitByte[1];
outputArray[i + 2] = splitByte[2];
outputArray[i + 3] = splitByte[3];
}
return outputArray;
}
private static String[] insert2Bit(String[] twoBitArray, String[] insertArray) {
for(int i = 0; i < twoBitArray.length; i++) {
insertArray[i] = insertArray[i].substring(0, 6) + twoBitArray[i];
}
return insertArray;
}
}
Also, the testclass:
public class Test {
public static void main(String[] args) {
Builder.leastSignificantBitEncryption("IMAGEPATH OR URL", "MESSAGE", "PATH FOR IMAGE CONTAINING MESSAGE");
Builder.leastSignificantBitDecryption("PATH OF IMAGE CONTAINING MESSAGE", "PATH FOR TXT CONTAINING OUTPUT");
}
}
The error originates from the fact that the png image has an extra channel for transparency. System.out.println(pixelsBin.length); returns 338355 bytes for the jpg and 451140 bytes for the png.
The simplest solution would be to create the appropriate imageNew depending on the format file. For example,
int w = image.getWidth();
int h = image.getHeight();
BufferedImage imageNew = null;
if (imageSource.matches(".*jpg$")) {
imageNew = new BufferedImage(w, h, BufferedImage.TYPE_3BYTE_BGR);
} else if (imageSource.matches(".*png$")) {
imageNew = new BufferedImage(w, h, BufferedImage.TYPE_4BYTE_ABGR);
} else {
// whatever
}
imageNew.setData(Raster.createRaster(imageNew.getSampleModel(), new DataBufferByte(pixelsBinNew, pixelsBinNew.length), new Point()));
However, you have to be aware that the message is not embedded in both types in the same pixels. The byte array of a 3-channel image (no transparency) goes like this
first-pixel-BLUE, first-pixel-GREEN, first-pixel-RED, second-pixel-BLUE, etc
while for a 4-channel image
first-pixel-ALPHA, first-pixel-BLUE, first-pixel-GREEN, first-pixel-RED, second-pixel-ALPHA, etc
If you care about that detail, you might be interested in removing the alpha channel from the png first, so you're always working with 3-channel images.

Combining PNG Images Java

I am trying to loop through a file of png images and stitch them together to form one image. I have gotten it to work without using a for loop and just combining two images from the file. So I am assuming it is the looping that isn't working. The images are located in a file called "images".
I would appreciate your input!
File file = new File("images");
File [] moreFile = file.listFiles();
String [] images = new String [moreFile.length];
for(int i =0; i <images.length; i++)
{images[i] = moreFile[i].getName();
}
int x = 0;
int y = 0;
BufferedImage result = new BufferedImage(
controller.getSize().width*2, controller.getSize().height, //work these out
BufferedImage.TYPE_INT_RGB);
Graphics g = result.getGraphics();
for(String image : images){
System.out.println(image);
File path = new File("images");
try{ImageIO.read(new File(path, image));
System.out.println("it definitely goes here");
BufferedImage bi = new BufferedImage((2*510),(2*439),BufferedImage.TYPE_INT_ARGB);
bi =ImageIO.read(new File(path, image));
g.drawImage(bi, x, y, null);
g.dispose();
/// System.out.println(dafuck);
x += bi.getWidth();
if(x > result.getWidth()){
x = 0;
y += bi.getHeight();
}
}catch (Exception e) {
System.out.println("is it an exception>?");
}
}
try {
ImageIO.write(result,"png",new File("results"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

How to save GLSurfaceView to texture/buffer/bitmap

I'm developing application for Android with GLSurfaceView. One moment i have to replace my GLSurfaceView with an image of it in that moment. The question is, how to get an image right? I used this code:
v.setDrawingCacheEnabled(true);
v.measure(View.MeasureSpec.makeMeasureSpec(500, View.MeasureSpec.AT_MOST),
View.MeasureSpec.makeMeasureSpec(500, View.MeasureSpec.AT_MOST));
v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
v.buildDrawingCache(true);
Bitmap b = Bitmap.createBitmap(v.getDrawingCache());
v.setDrawingCacheEnabled(false); // clear drawing cache
return b;
but it always return black bitmap.
Maybe we can make something other then Bitmap (which also can be placed to GLSurfaceView)?
I don't think it works this way with a GLSurfaceView. The framebuffer may live inside the GPU, where it's not directly accessible on the CPU.
You can use a framebuffer object to render the image to a texture, then use glReadPixels to download the data into a buffer and turn the buffer into a Bitmap.
Save GLSurfaceView to bitmap. Its working Correct.
MyRenderer Class :
#Override
public void onDrawFrame(GL10 gl) {
try {
int w = width_surface ;
int h = height_surface ;
Log.i("hari", "w:"+w+"-----h:"+h);
int b[]=new int[(int) (w*h)];
int bt[]=new int[(int) (w*h)];
IntBuffer buffer=IntBuffer.wrap(b);
buffer.position(0);
GLES20.glReadPixels(0, 0, w, h,GLES20.GL_RGBA,GLES20.GL_UNSIGNED_BYTE, buffer);
for(int i=0; i<h; i++)
{
//remember, that OpenGL bitmap is incompatible with Android bitmap
//and so, some correction need.
for(int j=0; j<w; j++)
{
int pix=b[i*w+j];
int pb=(pix>>16)&0xff;
int pr=(pix<<16)&0x00ff0000;
int pix1=(pix&0xff00ff00) | pr | pb;
bt[(h-i-1)*w+j]=pix1;
}
}
Bitmap inBitmap = null ;
if (inBitmap == null || !inBitmap.isMutable()
|| inBitmap.getWidth() != w || inBitmap.getHeight() != h) {
inBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
}
//Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
inBitmap.copyPixelsFromBuffer(buffer);
//return inBitmap ;
// return Bitmap.createBitmap(bt, w, h, Bitmap.Config.ARGB_8888);
inBitmap = Bitmap.createBitmap(bt, w, h, Bitmap.Config.ARGB_8888);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
inBitmap.compress(CompressFormat.JPEG, 90, bos);
byte[] bitmapdata = bos.toByteArray();
ByteArrayInputStream fis = new ByteArrayInputStream(bitmapdata);
final Calendar c=Calendar.getInstance();
long mytimestamp=c.getTimeInMillis();
String timeStamp=String.valueOf(mytimestamp);
String myfile="hari"+timeStamp+".jpeg";
dir_image=new File(Environment.getExternalStorageDirectory()+File.separator+
"printerscreenshots"+File.separator+"image");
dir_image.mkdirs();
try {
File tmpFile = new File(dir_image,myfile);
FileOutputStream fos = new FileOutputStream(tmpFile);
byte[] buf = new byte[1024];
int len;
while ((len = fis.read(buf)) > 0) {
fos.write(buf, 0, len);
}
fis.close();
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Log.v("hari", "screenshots:"+dir_image.toString());
}
}catch(Exception e) {
e.printStackTrace() ;
}

Categories

Resources