Error on compressing bitmat - android

I am trying to compress a bitmap, but getting a null pointer exception..the logcat is displaying uncaught exception
Bitmap bitmap = BitmapFactory.decodeByteArray(imageAsBytes , 0, imageAsBytes .length);
Bitmap bPNGcompress =codec(bitmap, Bitmap.CompressFormat.PNG, 0);
Bitmap scaled = bPNGcompress.createScaledBitmap( bPNGcompress, 100, 100, true );
method implementation
private static Bitmap codec(Bitmap map, Bitmap.CompressFormat format,
int quality) {
ByteArrayOutputStream os = new ByteArrayOutputStream();
map.compress(format, quality, os);
try {
os.flush();
os.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
byte[] array = os.toByteArray();
return BitmapFactory.decodeByteArray(array, 0, array.length);
}

Please try this,
private static Bitmap codec(Bitmap src, Bitmap.CompressFormat format,int quality)
{
ByteArrayOutputStream os = new ByteArrayOutputStream();
src.compress(format, quality, os);
byte[] array = os.toByteArray();
return BitmapFactory.decodeByteArray(array, 0, array.length);
}
private static class SampleView extends View {
// CONSTRUCTOR
public SampleView(Context context) {
super(context);
setFocusable(true);
}
#Override
protected void onDraw(Canvas canvas) {
Paint paint = new Paint();
canvas.drawColor(Color.GRAY);
// you need to insert some image flower_blue into res/drawable folder
Bitmap b = BitmapFactory.decodeResource(getResources(), R.drawable.flower_blue);
// Best of quality is 80 and more, 3 is very low quality of image
Bitmap bJPGcompress = codec(b, Bitmap.CompressFormat.JPEG, 3);
// get dimension of bitmap getHeight() getWidth()
int h = b.getHeight();
canvas.drawBitmap(b, 10,10, paint);
canvas.drawBitmap(bJPGcompress, 10,10 + h + 10, paint);
}
}

Related

getting low image quality from the camera after Lollipop while using bitmap factory

I use surface view for camera operation, After the image is captures am passing the image data to storeByteImage method.
But for certain devices or android lolipop version onwards am getting low resolution image.
In some new devices I get only 1/4 of the image captured.
public boolean storeByteImage(Context mContext, byte[] imageData, int quality) {
FileOutputStream fileOutputStream = null;
try {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 2;
Bitmap myImage = BitmapFactory.decodeByteArray(imageData, 0, imageData.length, options);
_getdate.setDrawingCacheEnabled(true);
_getdate.measure(
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
_getdate.layout(0, 0, _getdate.getMeasuredWidth(),
_getdate.getMeasuredHeight()); // set the layout of the date in the image
_getdate.buildDrawingCache(true);
_getdate.buildDrawingCache();
try {
textimage = Bitmap.createBitmap(_getdate.getDrawingCache());
} catch (Exception e) {
e.getMessage();
e.printStackTrace();
}
_getdate.setDrawingCacheEnabled(false); // clear drawing
// cache
Matrix matrix = new Matrix();
// the image height and width
int width, height;
height = myImage.getHeight();
width = myImage.getWidth();
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas comboImage = new Canvas(bitmap);
myImage = Bitmap.createScaledBitmap(myImage, width, height, true);
comboImage.drawBitmap(myImage, 0, 0, null);
comboImage.drawBitmap(textimage, matrix, null);
fileOutputStream = new FileOutputStream(
getResources().getString(R.string.sdpath_files_dir) + IMAGEFILE_EXT_JPG);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return true;
}

OutOfMemory Error in processing frames from onPreviewFrame

I am capturing frames in OnPreviewFrame() and then processing them in a thread to check if they are valid or not.
public void onPreviewFrame(byte[] data, Camera camera) {
if (imageFormat == ImageFormat.NV21) {
//We only accept the NV21(YUV420) format.
frameCount++;
if (frameCount > 19 && frameCount % 2 == 0) {
Camera.Parameters parameters = camera.getParameters();
FrameModel fModel = new FrameModel(data);
fModel.setPreviewWidth(parameters.getPreviewSize().width);
fModel.setPreviewHeight(parameters.getPreviewSize().height);
fModel.setPicFormat(parameters.getPreviewFormat());
fModel.setFrameCount(frameCount);
validateFrame(fModel);
}
}
}
In validateFrame(), i submit a ValidatorThread runnable instance to a ThreadPoolExecutor with 4 core and max threads, to process the frames parallelly.
public class ValidatorThread implements Runnable {
private FrameModel frame;
public ValidatorThread(FrameModel fModel) {
frame = fModel;
}
#Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
processNV21Data();
}
private void processNV21Data() {
YuvImage yuv = new YuvImage(frame.getData(), frame.getPicFormat(),
frame.getPreviewWidth(), frame.getPreviewHeight(), null);
frame.releaseData();
ByteArrayOutputStream out = new ByteArrayOutputStream();
yuv.compressToJpeg(new Rect(0, 0, frame.getPreviewWidth(), frame.getPreviewHeight()), 100, out);
byte[] bytes = out.toByteArray();
yuv = null;
try {
if (out != null)
out.close();
out = null;
} catch (IOException e) {
e.printStackTrace();
}
Bitmap baseBitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
bytes = null;
// rotate bitmap
baseBitmap = rotateImage(baseBitmap, frame.getRotation());
//create copy of original bitmap to use later
Bitmap mCheckedBitmap = baseBitmap.copy(Bitmap.Config.ARGB_8888, true);
// convert base bitmap to greyscale for validation
baseBitmap = toGrayscale(baseBitmap);
boolean isBitmapValid = Util.isBitmapValid(baseBitmap);
if (isBitmapValid) {
baseBitmap.recycle();
mCheckedBitmap.recycle();
frame = null;
} else {
baseBitmap.recycle();
mCheckedBitmap.recycle();
frame = null;
}
}
public Bitmap toGrayscale(Bitmap bmpOriginal) {
int width, height;
height = bmpOriginal.getHeight();
width = bmpOriginal.getWidth();
Bitmap bmpGrayscale = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
Canvas c = new Canvas(bmpGrayscale);
Paint paint = new Paint();
bmpOriginal.recycle();
return bmpGrayscale;
}
private Bitmap rotateImage(final Bitmap source, float angle) {
Matrix matrix = new Matrix();
matrix.postRotate(angle);
Bitmap rotatedBitmap = Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true);
source.recycle();
return rotatedBitmap;
}
}
The FrameModel class has such declaration :
public class FrameModel {
private byte[] data;
private int previewWidth;
private int previewHeight;
private int picFormat;
private int frameCount;
public void releaseData() {
data = null;
}
// getters and setters
}
I am getting OutOf Memory error while processing multiple frames.
Can anyone help what memory optimisation does the code need?
You can reduce memory usage if you produce grayscale bitmap from YUV data without going through Jpeg. This will also be significantly faster.
public Bitmap yuv2grayscale(byte[] yuv, int width, int height) {
int[] pixels = new int[width * height];
for (int i = 0; i < height*width; i++) {
int y = yuv[i] & 0xff;
pixels[i] = 0xFF000000 | y << 16 | y << 16 | y;
}
return Bitmap.createBitmap(pixels, width, height, Bitmap.Config.RGB_565);
}
Alternatively, you can create an RGB_565 bitmap without going through int[width*height] pixels array, and manipulate the bitmap pixels in place using NDK.

How to convert a dynamic string to bitmap?

I'd like to convert a dynamic string to Bitmap and save it on disk. The image should appear like the image below with the corner around the string.
I couldnt find a way to direct convert a String to bitmap, I tried to create a textView and convert it to bitmap, but it dont work properly.
Obs: I saw some questions that is similar, but they really don't have a solution to this question.
public static String StringToBitMap(Context context, String name){
TextView textView = new TextView(context);
textView.setText(name);
try{
int w = textView.getWidth();
int h = textView.getHeight();
Bitmap bitmap = Bitmap.createBitmap(w, h,Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
canvas.drawColor(Color.WHITE);
Drawable bgDrawable = textView.getBackground();
if (bgDrawable!=null) {
bgDrawable.draw(canvas);
}
else {
canvas.drawColor(Color.WHITE);
}
textView.draw(canvas);
FileOutputStream out = null;
File file = null;
try {
String path = Environment.getExternalStorageDirectory().toString();
file = new File(path + "/Download/", "item.png");
out = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, out); // bmp is your Bitmap instance
// PNG is a lossless format, the compression factor (100) is ignored
out.close();
MediaStore.Images.Media.insertImage(context.getContentResolver(),file.getAbsolutePath(),file.getName(),file.getName());
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return file.getAbsolutePath();
}catch(Exception e){
e.getMessage();
return null;
}
}
I just found the solution:
public static String StringToBitMap(Context context, String name){
try{
// Create bitmap
Bitmap bitmap = Bitmap.createBitmap(250, 16,Bitmap.Config.ARGB_8888);
bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);
Canvas canvas = new Canvas(bitmap);
canvas.drawColor(0xffffffff);
// new antialised Paint
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
// text color - #3D3D3D
paint.setColor(Color.BLACK);
// text size in pixels
paint.setTextSize(12);
// draw text to the Canvas center
Rect bounds = new Rect();
paint.getTextBounds(name, 0, name.length(), bounds);
int x = (bitmap.getWidth() - bounds.width())/2;
int y = (bitmap.getHeight() + bounds.height())/2;
canvas.drawText(name, x, y, paint);
paint.setColor(Color.BLACK);
paint.setStrokeWidth(3);
paint.setStyle(Paint.Style.STROKE);
// draw corner to the Canvas
canvas.drawRect(x - 5, 0.0f, x + bounds.width() + 5, 16.0f, paint);
// save on disk
FileOutputStream out = null;
File file = null;
try {
String path = Environment.getExternalStorageDirectory().toString();
file = new File(path + "/Download/", "item.png");
out = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, out); // bmp is your Bitmap instance
// PNG is a lossless format, the compression factor (100) is ignored
out.close();
MediaStore.Images.Media.insertImage(context.getContentResolver(),file.getAbsolutePath(),file.getName(),file.getName());
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return file.getAbsolutePath();
}catch(Exception e){
e.getMessage();
return null;
}
}

cache a array list of bitmap in android

i have a ArrayList that contains more than 15 bitmaps. this bitmaps have to be read from sdcard. my array is in the loop .so i dont want to read bitmaps from storage each time and i want to save this bitmaps as cache. my arraylist of bitmap is less than 2 Mb.
i wanna display it with canvas in my Custom View.so i think it's good to save it as cache or something else because of the number of bitmaps. i think it doesn't make sense to read more than 15 bitmap from sdcard even if they are very light(about 15kb) pleas help me how to do this.
in additional each bitmap is 256*256 pixel.
Bitmap bmp;
String zoom = String.valueOf(ZoomLevel);
File file = new File(Environment.getExternalStorageDirectory()+"/GreatMap/"+zoom);
File image = FolderExist(ZoomLevel);
if (file.exists())
{
if(image.exists())
{
for(int a = 1; a < 20 ;a++)
{
bmp = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory()+"/GreatMap/"+zoom+"/"+a+".jpg");
Images.add(a,bmp);
}
postInvalidate();
}
}
Use below class to get image from sd card. It will remain image in cache. You can get also image from url as well as from sd card. This will work for both.
Just initialize this class and get image.
imageLoader = new ImageLoader(this);
And call its method to get image from sd card and set photo where you want.
public class ImageLoader {
MemoryCache memoryCache = new MemoryCache();
FileCache fileCache;
private Map<ImageView, String> imageViews = Collections.synchronizedMap(new WeakHashMap<ImageView, String>());
ExecutorService executorService;
Handler handler = new Handler();// handler to display images in UI thread
Context mContext;
boolean imageWithReflection;
public ImageLoader(Context context) {
fileCache = new FileCache(context);
executorService = Executors.newFixedThreadPool(5);
this.mContext = context;
this.stubImageBitmap = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.default_image);
}
final Bitmap stubImageBitmap;
public void displayImageFromUrl(String url, ImageView imageView, boolean imageWithReflection) {
this.imageWithReflection = imageWithReflection;
imageViews.put(imageView, url);
Bitmap bitmap = memoryCache.get(url);
if (bitmap != null) {
if (this.imageWithReflection)
imageView.setImageBitmap(createReflectedImage(bitmap));
else
imageView.setImageBitmap(bitmap);
} else {
queuePhoto(url, imageView);
if (this.imageWithReflection)
imageView.setImageBitmap(createReflectedImage(stubImageBitmap));
else
imageView.setImageBitmap(stubImageBitmap);
}
}
private void queuePhoto(String url, ImageView imageView) {
PhotoToLoad p = new PhotoToLoad(url, imageView);
executorService.submit(new PhotosLoader(p));
}
private Bitmap getBitmap(String url) {
File f = fileCache.getFile(url);
// from SD cache
Bitmap b = decodeFile(f);
if (b != null)
return b;
// from web
try {
Bitmap bitmap = null;
URL imageUrl = new URL(url);
HttpURLConnection conn = (HttpURLConnection) imageUrl.openConnection();
conn.setConnectTimeout(30000);
conn.setReadTimeout(30000);
conn.setInstanceFollowRedirects(true);
InputStream is = conn.getInputStream();
OutputStream os = new FileOutputStream(f);
ActivityUtils.copyStream(is, os);
os.close();
conn.disconnect();
bitmap = decodeFile(f);
return bitmap;
} catch (Throwable ex) {
ex.printStackTrace();
if (ex instanceof OutOfMemoryError)
memoryCache.clear();
return null;
}
}
// decodes image and scales it to reduce memory consumption
private Bitmap decodeFile(File f) {
try {
// decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
FileInputStream stream1 = new FileInputStream(f);
BitmapFactory.decodeStream(stream1, null, o);
stream1.close();
// Find the correct scale value. It should be the power of 2.
final int REQUIRED_SIZE = 70;
int width_tmp = o.outWidth, height_tmp = o.outHeight;
int scale = 1;
while (true) {
if (width_tmp / 2 < REQUIRED_SIZE || height_tmp / 2 < REQUIRED_SIZE)
break;
width_tmp /= 2;
height_tmp /= 2;
scale *= 2;
}
// decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
FileInputStream stream2 = new FileInputStream(f);
Bitmap bitmap = BitmapFactory.decodeStream(stream2, null, o2);
stream2.close();
return bitmap;
} catch (FileNotFoundException e) {
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
// Task for the queue
private class PhotoToLoad {
public String url;
public ImageView imageView;
public PhotoToLoad(String u, ImageView i) {
url = u;
imageView = i;
}
}
class PhotosLoader implements Runnable {
PhotoToLoad photoToLoad;
PhotosLoader(PhotoToLoad photoToLoad) {
this.photoToLoad = photoToLoad;
}
#Override
public void run() {
try {
if (imageViewReused(photoToLoad))
return;
Bitmap bmp = getBitmap(photoToLoad.url);
memoryCache.put(photoToLoad.url, bmp);
if (imageViewReused(photoToLoad))
return;
BitmapDisplayer bd = new BitmapDisplayer(bmp, photoToLoad);
handler.post(bd);
} catch (Throwable th) {
th.printStackTrace();
}
}
}
boolean imageViewReused(PhotoToLoad photoToLoad) {
String tag = imageViews.get(photoToLoad.imageView);
if (tag == null || !tag.equals(photoToLoad.url))
return true;
return false;
}
// Used to display bitmap in the UI thread
class BitmapDisplayer implements Runnable {
Bitmap bitmap;
PhotoToLoad photoToLoad;
public BitmapDisplayer(Bitmap b, PhotoToLoad p) {
bitmap = b;
photoToLoad = p;
}
public void run() {
if (imageViewReused(photoToLoad))
return;
if (bitmap != null) {
if (imageWithReflection)
photoToLoad.imageView.setImageBitmap(createReflectedImage(bitmap));
else
photoToLoad.imageView.setImageBitmap(bitmap);
} else {
if (imageWithReflection)
photoToLoad.imageView.setImageBitmap(createReflectedImage(stubImageBitmap));
else
photoToLoad.imageView.setImageBitmap(stubImageBitmap);
}
}
}
public void clearCache() {
memoryCache.clear();
fileCache.clear();
}
private Bitmap createReflectedImage(Bitmap originalImage) {
final int reflectionGap = 4;
int width = originalImage.getWidth();
int height = originalImage.getHeight();
// This will not scale but will flip on the Y axis
Matrix matrix = new Matrix();
matrix.preScale(1, -1);
// Create a Bitmap with the flip matrix applied to it.
// We only want the bottom half of the image
Bitmap reflectionImage = Bitmap.createBitmap(originalImage, 0, height / 2, width, height / 2, matrix, false);
// Create a new bitmap with same width but taller to fit reflection
Bitmap bitmapWithReflection = Bitmap.createBitmap(width, (height + height / 2), Config.ARGB_8888);
// Create a new Canvas with the bitmap that's big enough for
// the image plus gap plus reflection
Canvas canvas = new Canvas(bitmapWithReflection);
// Draw in the original image
canvas.drawBitmap(originalImage, 0, 0, null);
// Draw in the gap
Paint deafaultPaint = new Paint();
canvas.drawRect(0, height, width, height + reflectionGap, deafaultPaint);
// Draw in the reflection
canvas.drawBitmap(reflectionImage, 0, height + reflectionGap, null);
// Create a shader that is a linear gradient that covers the reflection
Paint paint = new Paint();
LinearGradient shader = new LinearGradient(0, originalImage.getHeight(), 0, bitmapWithReflection.getHeight() + reflectionGap, 0x70ffffff, 0x00ffffff, TileMode.CLAMP);
// Set the paint to use this shader (linear gradient)
paint.setShader(shader);
// Set the Transfer mode to be porter duff and destination in
paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
// Draw a rectangle using the paint with our linear gradient
canvas.drawRect(0, height, width, bitmapWithReflection.getHeight() + reflectionGap, paint);
return bitmapWithReflection;
}
remove or ignore extra code like createReflectedImage() method.
Use https://github.com/nostra13/Android-Universal-Image-Loader for better performance. This image loader will do what all you needed.

the screenshot of Google Map V1

when I screen shot the map. I cannot success to shot the all screen.it only show the path.
I want to know what my problem is on my code. I hope someone can help me. thank you
It is my result:
// Screen shot
private static Bitmap takeScreenShot(Activity activity) {
// View to shot View
View view = activity.getWindow().getDecorView();
//View view = getPopupViews(getDecorViews())[0];
Log.i("ABC", view.getClass().getName());
view.setDrawingCacheEnabled(true);
view.buildDrawingCache();
Bitmap b1 = view.getDrawingCache();
// the height
Rect frame = new Rect();
view.getWindowVisibleDisplayFrame(frame);
int statusBarHeight = frame.top;
System.out.println(statusBarHeight);
// width and height
int width = activity.getWindowManager().getDefaultDisplay().getWidth();
int height = activity.getWindowManager().getDefaultDisplay().getHeight();
// del the state bar
// Bitmap b = Bitmap.createBitmap(b1, 0, 25, 320, 455);
Bitmap b = Bitmap.createBitmap(b1, 0, statusBarHeight, width, height - statusBarHeight);
view.destroyDrawingCache();
return b;
}
// save image to sdcard
private static void savePic(Bitmap b, String strFileName) {
FileOutputStream fos = null;
try {
fos = new FileOutputStream(strFileName);
if (null != fos) {
b.compress(Bitmap.CompressFormat.JPEG, 90, fos);
fos.flush();
fos.close();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private void shoot() {
shoot(this);
}
// call function
public static void shoot(Activity a) {
savePic(takeScreenShot(a), "data/data/com.example.map/"+number+".png");
}
try this code, and pass mapView in this
public final static Bitmap takeScreenShot(View view) {
Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
view.draw(canvas);
return bitmap;
}
private Bitmap getMapImage() {
MapController mc = mapView.getController();
mc.setCenter(GEO_POINT);
mc.setZoom(ZOOM_LEVEL);
/* Capture drawing cache as bitmap */
mapView.setDrawingCacheEnabled(true);
Bitmap bmp = Bitmap.createBitmap(mapView.getDrawingCache());
mapView.setDrawingCacheEnabled(false);
return bmp;
}
private void saveMapImage() {
String filename = "SCREEN_SHOT.png";
File f = new File(getExternalFilesDir(null), filename);
FileOutputStream out = new FileOutputStream(f);
Bitmap bmp = getMapImage();
bmp.compress(Bitmap.CompressFormat.PNG, 100, out);
out.close();
}

Categories

Resources