I would like to change position of bitmap inside Canvas from Activity class. My solution from below only draws first value of x (left) as zero, later on does not change x value. But my Logcat shows that x value changes everytime when I call it from Activity. I would like to know where is my mistake ? onDraw method does not change position of bitmap.
Custome view:
public class TheCustomView extends View {
Bitmap scaledRollerBottom;
Bitmap backgroundMask;
Bitmap rollerBottom;
Bitmap overlayBitmap;
float x;
public TheCustomView(Context context) {
super(context);
}
public TheCustomView(Context context, AttributeSet attr) {
super(context, attr);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
backgroundMask = BitmapFactory.decodeResource(getResources(), R.drawable.background_new, options);
rollerBottom = BitmapFactory.decodeResource(getResources(), R.drawable.roller_bottom, options);
Bitmap scaledBackgroundMask = Bitmap.createScaledBitmap(backgroundMask, 1000, 1000, true);
scaledRollerBottom = Bitmap.createScaledBitmap(rollerBottom, 120, 31, false);
// int bitmap1Width = scaledBackgroundMask.getWidth();
// int bitmap1Height = scaledBackgroundMask.getHeight();
// overlayBitmap = Bitmap.createBitmap(bitmap1Width, bitmap1Height, scaledBackgroundMask.getConfig());
}
#Override
protected void onDraw(Canvas canvas) {
Log.v("X ", "is " + x);
canvas.drawBitmap(scaledRollerBottom, (float) x, (float) 915, new Paint());
super.onDraw(canvas);
}
}
Calling from activity class
if (callback2 > 0 && callback2 <= 0.1) {
customView.x = 468;
customView.draw(canvas);
// customView.invalidate();
} else if (callback2 < 0) {
customView.x = 650;
customView.draw(canvas);
// customView.invalidate();
} else if (callback2 > 0.1) {
customView.x = 270;
customView.draw(canvas);
//customView.invalidate();
}
I have GridView widget which is populated by 40 images taken from ArrayList, problem is when widget is trying to load more positions than 40 and it makes about few hundreds of blank cells with "loading" text. This wouldn't happen if number of items was fixed by 40, but how to do that?
This is my RemoteViewsFactory class:
public class WidgetRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory {
private Context ctx;
private Cursor cursor;
private ArrayList<Bitmap> photos = new ArrayList<>(40);
public WidgetRemoteViewsFactory(Context applicationContext, Intent intent) {
ctx = applicationContext;
}
#Override
public void onCreate() {
}
#Override
public void onDataSetChanged() {
String[] projection = new String[]{
MediaStore.Images.ImageColumns._ID,
MediaStore.Images.ImageColumns.DATA,
MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME,
MediaStore.Images.ImageColumns.DATE_TAKEN,
MediaStore.Images.ImageColumns.MIME_TYPE
};
cursor = ctx.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection, null,
null, MediaStore.Images.ImageColumns.DATE_TAKEN + " DESC");
cursor.moveToFirst();
for (int i = 1; i <= 39; i++) {
Bitmap bmp = BitmapFactory.decodeFile(cursor.getString(1));
photos.add(bmp);
cursor.moveToNext();
Log.d(TAG, "loop iteration" + i );
}
}
#Override
public void onDestroy() {
if (cursor != null) {
cursor.close();
}
}
#Override
public int getCount() {
return cursor == null ? 0 : cursor.getCount();
}
#Override
public RemoteViews getViewAt(int position) {
if (position == AdapterView.INVALID_POSITION ||
cursor == null || !cursor.moveToPosition(position) || photos == null || photos.size() == 0 || position >= photos.size()) {
return null;
}
RemoteViews views = new RemoteViews(ctx.getPackageName(), R.layout.widget_item);
Bitmap img = resizeBitmapFitXY(250, 150, photos.get(position));
views.setImageViewBitmap(R.id.imageView, img);
return views;
}
#Override
public RemoteViews getLoadingView() {
return null;
}
#Override
public int getViewTypeCount() {
return 1;
}
#Override
public long getItemId(int position) {
return cursor.moveToPosition(position) ? cursor.getLong(0) : position;
}
#Override
public boolean hasStableIds() {
return true;
}
public Bitmap resizeBitmapFitXY(int width, int height, Bitmap bitmap){
Bitmap background = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
float originalWidth = bitmap.getWidth(), originalHeight = bitmap.getHeight();
Canvas canvas = new Canvas(background);
float scale, xTranslation = 0.0f, yTranslation = 0.0f;
if (originalWidth > originalHeight) {
scale = height/originalHeight;
xTranslation = (width - originalWidth * scale)/2.0f;
}
else {
scale = width / originalWidth;
yTranslation = (height - originalHeight * scale)/2.0f;
}
Matrix transformation = new Matrix();
transformation.postTranslate(xTranslation, yTranslation);
transformation.preScale(scale, scale);
Paint paint = new Paint();
paint.setFilterBitmap(true);
canvas.drawBitmap(bitmap, transformation, paint);
return background;
}
}
you need to replace this code
cursor.moveToFirst();
for (int i = 1; i <= 39; i++) {
Bitmap bmp = BitmapFactory.decodeFile(cursor.getString(1));
photos.add(bmp);
cursor.moveToNext();
Log.d(TAG, "loop iteration" + i );
}
and put this instead
if (cursor!=null && cursor.getCount()>0) {
while (cursor.moveToNext()) {
Bitmap bmp = BitmapFactory.decodeFile(cursor.getString(1));
photos.add(bmp);
Log.d(TAG, "loop iteration" + i );
}
}
the problem that you used a fixed size in the for loop for (int i = 1; i <= 39; i++)
and the solution is to use while() loop to get all the item from the cursor and add it to your list
update answer after the comment :
Q: if you decide in the loop to load only 40 and not to load the blank text
you must to do this
#Override
public int getCount() {
return 40;
}
I am making a custom camera with face detection, which works successfully.
But I want to add stickers like to the recorded/previewed face.
The location of the eyes is used to properly size and place a hat, glasses, and tie etc. on the Preview.
The Face Detection with the FaceOverlayView
public class FaceOverlayView extends View {
private Paint mPaint;
private Paint mTextPaint;
private int mDisplayOrientation;
private int mOrientation;
private Face[] mFaces;
public FaceOverlayView(Context context) {
super(context);
initialize();
}
private void initialize() {
// We want a green box around the face:
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(Color.GREEN);
mPaint.setAlpha(128);
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mTextPaint = new Paint();
mTextPaint.setAntiAlias(true);
mTextPaint.setDither(true);
mTextPaint.setTextSize(20);
mTextPaint.setColor(Color.GREEN);
mTextPaint.setStyle(Paint.Style.FILL);
}
public void setFaces(Face[] faces) {
mFaces = faces;
invalidate();
}
public void setOrientation(int orientation) {
mOrientation = orientation;
}
public void setDisplayOrientation(int displayOrientation) {
mDisplayOrientation = displayOrientation;
invalidate();
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mFaces != null && mFaces.length > 0) {
Matrix matrix = new Matrix();
Util.prepareMatrix(matrix, false, mDisplayOrientation, getWidth(), getHeight());
canvas.save();
matrix.postRotate(mOrientation);
canvas.rotate(-mOrientation);
RectF rectF = new RectF();
for (Face face : mFaces) {
rectF.set(face.rect);
matrix.mapRect(rectF);
canvas.drawRect(rectF, mPaint);
canvas.drawText("Score " + face.score, rectF.right, rectF.top, mTextPaint);
}
canvas.restore();
}
}
}
I want to add the hat and sunglasses on the preview like a similar in the Play Store, Face 28:
More Info.
I am using for MoodMeSDK to detect the eyes and mouth
The result is 66 Points:
I want put sunglasses, caps, lips, etc. on the face. In the Face28 APK using the SVG file for the face stickers.
I have done something almost similar to this before. So here's how you need to do this: first you need to locate the points relative to the View's Rectangle, for example if you want to place a hat, first pin-point head and relative rectangle of hat based on the CameraView, then place the hat on that coordinate. This is the easy part. The hard part is saving the image. for this you need to save width and length of CameraView and stickers on it and their locations on CameraView. Then you capture the image and get a Bitmap/Drawable. You will most likely get different sizes for produced bitmap than CameraView so you need to re-calculate the coordinate of stickers on this bitmap based on it's w/h to the CameraView and merge stickers on new coordinates and then save it. It is not easy but it is possible as I did it.
Here's my code(in my case sticker was being placed in center of picture):
/**
* Created by Mohammad Erfan Molaei on 9/26/16.
*/
public class CaptureActivity extends AppCompatActivity implements
ActivityCompat.OnRequestPermissionsResultCallback {
private static final String TAG = "CaptureActivity";
private FloatingActionButton takePicture;
private int mCurrentFlash;
private CameraView mCameraView;
private int cameraWidth;
private int cameraHeight;
private int drawableWidth;
private int drawableHeight;
private Handler mBackgroundHandler;
private boolean selectedBrand;
#Override
public void setTheme(int resId) {
selectedBrand = getSharedPreferences(getString(R.string.brand_pref), MODE_PRIVATE)
.getBoolean(getString(R.string.selected_brand), true);
super.setTheme(selectedBrand ? R.style.AppTheme_CaptureTheme : R.style.AppTheme_CaptureTheme2);
}
private String itemID = null;
private View.OnClickListener mOnClickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.take_picture:
if (mCameraView != null) {
mCameraView.takePicture();
takePicture.setEnabled(false);
}
break;
case R.id.scale_up_btn:
scaleUpImage();
break;
case R.id.scale_down_btn:
scaleDownImage();
break;
}
}
};
private void scaleUpImage() {
if (mCameraView != null) {
SizeAwareImageView imageView = (SizeAwareImageView) mCameraView.findViewById(R.id.mImageView);
/*Log.e(TAG, "scaleDownImage: oldWidth: " + imageView.getLayoutParams().width +
", oldHeight: " + imageView.getLayoutParams().height);
Log.e(TAG, "scaleDownImage: newWidth2B: " + (imageView.getLayoutParams().width * 1.1f) +
", newHeight2B: " + ((1.1f * imageView.getLayoutParams().width) *
imageView.getLayoutParams().height /
imageView.getLayoutParams().width));
Log.e(TAG, "cameraWidth: " + mCameraView.getLayoutParams().width );
sdasd*/
if (imageView.getWidth() * 1.1f > mCameraView.getWidth() ||
((1.1f * imageView.getWidth()) *
imageView.getHeight() /
imageView.getWidth()) > mCameraView.getHeight())
return;
imageView.getLayoutParams().height = (int) ((1.1f * imageView.getWidth()) *
imageView.getHeight() /
imageView.getWidth());
imageView.getLayoutParams().width = (int) (imageView.getWidth() * 1.1f);
imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
imageView.requestLayout();
/*drawableWidth = dp2px(imageView.getWidth());
drawableHeight = dp2px(imageView.getHeight());*/
}
}
private void scaleDownImage() {
if (mCameraView != null) {
SizeAwareImageView imageView = (SizeAwareImageView) mCameraView.findViewById(R.id.mImageView);
if (imageView.getWidth() * 0.9f > mCameraView.getWidth() ||
((0.9f * imageView.getWidth()) *
imageView.getHeight() /
imageView.getWidth()) > mCameraView.getHeight())
return;
imageView.getLayoutParams().height = (int) ((0.9f * imageView.getWidth()) *
imageView.getHeight() /
imageView.getWidth());
imageView.getLayoutParams().width = (int) (imageView.getWidth() * 0.9f);
imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
imageView.requestLayout();
/*drawableWidth = dp2px(imageView.getWidth());
drawableHeight = dp2px(imageView.getHeight());*/
}
}
private void rotateImage() {
if (mCameraView != null) {
SizeAwareImageView imageView = (SizeAwareImageView) mCameraView.findViewById(R.id.mImageView);
/*Drawable mDrawable = imageView.getDrawable();
int mDrawableWidth = mDrawable.getBounds().width();
int mDrawableHeight = mDrawable.getBounds().height();*/
int newWidth = imageView.getHeight();
int newHeight = imageView.getWidth();
float scaleFactor = 1;
/*Log.e(TAG, "rotateImage: prevWidth: " + newHeight + ", prevHeight: " + newWidth);
Log.e(TAG, "rotateImage: cameraWidth: " + mCameraView.getWidth() );*/
if (newWidth > mCameraView.getWidth() ) {
scaleFactor = (float)newWidth / (float)mCameraView.getWidth();
newWidth = mCameraView.getWidth();
newHeight *= scaleFactor;
} else if (newHeight > mCameraView.getHeight() ) {
scaleFactor = (float)newHeight / (float)mCameraView.getHeight();
newHeight = mCameraView.getHeight();
newWidth *= scaleFactor;
}
Log.e(TAG, "rotateImage: scaleFactor: " + scaleFactor);
imageView.setRotation(imageView.getRotation() + 90);
imageView.getLayoutParams().height = newHeight;
imageView.getLayoutParams().width = newWidth;
imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
imageView.requestLayout();
/*drawableWidth = dp2px(imageView.getWidth());
drawableHeight = dp2px(imageView.getHeight());*/
//imageView.setImageDrawable(getRotatedDrawable(imageView));
/*Bitmap bitmapOrg = drawableToBitmap(imageView.getDrawable());
// createa matrix for the manipulation
Matrix matrix = imageView.getImageMatrix();
int width = bitmapOrg.getWidth();
int height = bitmapOrg.getHeight();
// rotate the Bitmap
matrix.postRotate(90);
// recreate the new Bitmap
Bitmap resizedBitmap = Bitmap.createBitmap(bitmapOrg, 0, 0,
width, height, matrix, true);
// make a Drawable from Bitmap to allow to set the BitMap
// to the ImageView, ImageButton or what ever
BitmapDrawable bmd = new BitmapDrawable(getResources(), resizedBitmap);
// set the Drawable on the ImageView
imageView.setImageDrawable(bmd);*/
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_capture);
mCameraView = (CameraView) findViewById(R.id.camera);
if (mCameraView != null) {
mCameraView.addCallback(mCallback);
}
takePicture = (FloatingActionButton) findViewById(R.id.take_picture);
if (takePicture != null) {
takePicture.setOnClickListener(mOnClickListener);
}
/*if (selectedBrand) {
assert takePicture != null;
takePicture.setBackgroundColor(ContextCompat.getColor(getBaseContext(),R.color.colorAccent));
findViewById(R.id.control).setBackgroundColor(ContextCompat.getColor(getBaseContext(),R.color.colorPrimary));
} else {
assert takePicture != null;
takePicture.setBackgroundColor(ContextCompat.getColor(getBaseContext(),R.color.colorAccent2));
findViewById(R.id.control).setBackgroundColor(ContextCompat.getColor(getBaseContext(),R.color.colorPrimary2));
}*/
findViewById(R.id.scale_up_btn).setOnClickListener(mOnClickListener);
findViewById(R.id.scale_down_btn).setOnClickListener(mOnClickListener);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayShowTitleEnabled(false);
}
if (savedInstanceState == null) {
Bundle extras = getIntent().getExtras();
if(extras != null) {
itemID = extras.getString("id", null);
}
} else {
itemID = (String) savedInstanceState.getSerializable("id");
}
if( itemID != null ) {
new AsyncImageLoader().execute(itemID);
} else {
this.finish();
return;
}
ViewTreeObserver viewTreeObserver = mCameraView.getViewTreeObserver();
if (viewTreeObserver.isAlive()) {
viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
/*if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
mCameraView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
} else {
mCameraView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}*/
cameraWidth = dp2px(mCameraView.getWidth());
cameraHeight = dp2px(mCameraView.getHeight());
Log.e("camB4Action", "" + cameraWidth + ", " + cameraHeight);
}
});
}
}
#Override
protected void onResume() {
super.onResume();
mCameraView.start();
}
#Override
protected void onPause() {
mCameraView.stop();
super.onPause();
}
#Override
protected void onDestroy() {
super.onDestroy();
if (mBackgroundHandler != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
mBackgroundHandler.getLooper().quitSafely();
} else {
mBackgroundHandler.getLooper().quit();
}
mBackgroundHandler = null;
}
}
private Drawable getFlippedDrawable(final Drawable d) {
final Drawable[] arD = { d };
return new LayerDrawable(arD) {
#Override
public void draw(final Canvas canvas) {
canvas.save();
canvas.scale(-1, 1, d.getBounds().width() / 2, d.getBounds().height() / 2);
super.draw(canvas);
canvas.restore();
}
};
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.camera, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.switch_flash:
if (mCameraView != null) {
mCurrentFlash = (mCurrentFlash + 1) % FLASH_OPTIONS.length;
item.setTitle(FLASH_TITLES[mCurrentFlash]);
item.setIcon(FLASH_ICONS[mCurrentFlash]);
mCameraView.setFlash(FLASH_OPTIONS[mCurrentFlash]);
}
break;
case R.id.switch_camera:
if (mCameraView != null) {
int facing = mCameraView.getFacing();
mCameraView.setFacing(facing == CameraView.FACING_FRONT ?
CameraView.FACING_BACK : CameraView.FACING_FRONT);
}
break;
case R.id.mirror_image:
if (mCameraView != null) {
SizeAwareImageView imageView = (SizeAwareImageView) mCameraView.findViewById(R.id.mImageView);
imageView.setImageDrawable(getFlippedDrawable(imageView.getDrawable()));
imageView.requestLayout();
}
break;
case R.id.rotate_image:
if (mCameraView != null) {
rotateImage();
}
break;
}
return false;
}
private Handler getBackgroundHandler() {
if (mBackgroundHandler == null) {
HandlerThread thread = new HandlerThread("background");
thread.setPriority(Thread.MAX_PRIORITY);
thread.start();
mBackgroundHandler = new Handler(thread.getLooper());
}
return mBackgroundHandler;
}
public static Bitmap scaleBitmap(Bitmap bitmap, int wantedWidth, int wantedHeight, float rotation) {
Log.e(TAG, "scaleBitmap: bitmapWidth: " + bitmap.getWidth() + ", bitmapHeight: " + bitmap.getHeight() );
Log.e(TAG, "scaleBitmap: wantedWidth: " +
((rotation % 180 == 90) ? wantedHeight : wantedWidth) +
", wantedHeight: " + ((rotation % 180 == 90) ? wantedWidth : wantedHeight) );
Bitmap output = Bitmap.createBitmap(
(rotation % 180 == 90) ? wantedHeight : wantedWidth,
(rotation % 180 == 90) ? wantedWidth : wantedHeight, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(output);
Matrix m = new Matrix();
m.setScale((float)
((rotation % 180 == 90) ? wantedHeight : wantedWidth) / bitmap.getWidth(),
(float) ((rotation % 180 == 90) ? wantedWidth : wantedHeight) / bitmap.getHeight());
canvas.drawBitmap(bitmap, m, new Paint());
return output;
/*Matrix m = new Matrix();
m.setRectToRect(new RectF(0, 0, b.getWidth(), b.getHeight()),
new RectF(0, 0, (rotation % 180 == 90) ? wantedHeight : wantedWidth,
(rotation % 180 == 90) ? wantedWidth : wantedHeight), Matrix.ScaleToFit.CENTER);
return Bitmap.createBitmap(b, 0, 0, b.getWidth(), b.getHeight(), m, true);*/
}
private CameraView.Callback mCallback
= new CameraView.Callback() {
ProgressiveToast progressiveToast;
#Override
public void onCameraOpened(CameraView cameraView) {
Log.d(TAG, "onCameraOpened");
}
#Override
public void onCameraClosed(CameraView cameraView) {
Log.d(TAG, "onCameraClosed");
}
#Override
public void onPictureTaken(CameraView cameraView, final byte[] data) {
Log.d(TAG, "onPictureTaken " + data.length);
/*TastyToast.makeText(cameraView.getContext(), getString(R.string.pic_being_saved),
TastyToast.LENGTH_LONG, TastyToast.INFO);*/
progressiveToast = ProgressiveToast.getInstance();
progressiveToast.show(CaptureActivity.this, getString(R.string.in_action_be_patient), -1);
getBackgroundHandler().post(new Runnable() {
#Override
public void run() {
mCameraView.stop();
// This demo app saves the taken picture to a constant file.
// $ adb pull /sdcard/Android/data/com.google.android.cameraview.demo/files/Pictures/picture.jpg
SizeAwareImageView imageView = ((SizeAwareImageView) mCameraView.findViewById(R.id.mImageView));
Bitmap imageBitmap =
drawableToBitmap(imageView.getDrawable());
Matrix matrix = new Matrix();
float rotation = mCameraView.findViewById(R.id.mImageView).getRotation();
matrix.postRotate(rotation);
//matrix.postScale(drawableWidth, drawableHeight);
/*
matrix.setScale((float)
((rotation% 180 == 90) ? drawableWidth : drawableHeight) / imageBitmap.getWidth(),
(float) ((rotation% 180 == 90) ? drawableWidth : drawableHeight) / imageBitmap.getHeight());*/
Log.e(TAG, "rotation: " + rotation);
imageBitmap = Bitmap.createBitmap(imageBitmap , 0, 0,
imageBitmap.getWidth(), imageBitmap.getHeight(), matrix, true);
imageBitmap = scaleBitmap(imageBitmap, drawableWidth, drawableHeight, rotation);
Bitmap cameraBmp = BitmapFactory.decodeByteArray(data, 0, data.length);
cameraBmp = fixOrientation(cameraBmp);
File dir = new File (Environment.getExternalStorageDirectory().getAbsolutePath()
+ File.separator + getString(R.string.gallery_folder_name) +
(selectedBrand ? getString(R.string.ibr_eng) :
getString(R.string.tiyaco_eng)));
dir.mkdirs();
File file = new File(dir.getAbsolutePath() ,
Long.toString(Calendar.getInstance().getTimeInMillis()) + ".jpg");
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
OutputStream os = null;
InputStream is = overlayBitmapToCenter(cameraBmp, imageBitmap, rotation);
byte[] buffer = new byte[10 * 1024];
int n = 0;
try {
os = new FileOutputStream(file);
while (-1 != (n = is.read(buffer))) {
os.write(buffer, 0, n);
}
} catch (IOException e) {
Log.w(TAG, "Cannot write to " + file, e);
} finally {
if (os != null) {
try {
os.close();
} catch (IOException e) {
// Ignore
}
runOnUiThread(new Runnable() {
#Override
public void run() {
if (mCameraView != null)
try {
mCameraView.start();
} catch (Exception ignored){}
if (takePicture != null) {
takePicture.setEnabled(true);
}
progressiveToast.dismiss();
TastyToast.makeText(getApplicationContext(), getString(R.string.picture_taken),
TastyToast.LENGTH_LONG, TastyToast.SUCCESS);
}
});
}
}
}
});
}
};
public Bitmap fixOrientation(Bitmap mBitmap) {
if (mBitmap.getWidth() > mBitmap.getHeight()) {
Matrix matrix = new Matrix();
matrix.postRotate(90);
return Bitmap.createBitmap(mBitmap , 0, 0, mBitmap.getWidth(), mBitmap.getHeight(), matrix, true);
}
return mBitmap;
}
private int dp2px(int dp) {
return (int)((dp * getResources().getDisplayMetrics().density) + 0.5);
}
public static Bitmap drawableToBitmap (Drawable drawable) {
Bitmap bitmap = null;
if (drawable instanceof BitmapDrawable) {
BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
if(bitmapDrawable.getBitmap() != null) {
return bitmapDrawable.getBitmap();
}
}
if(drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) {
bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); // Single color bitmap will be created of 1x1 pixel
} else {
bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
}
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
}
public ByteArrayInputStream overlayBitmapToCenter(Bitmap bitmap1, Bitmap bitmap2, float rotation) {
float alpha = (float)cameraWidth / (float)((rotation % 180 == 90) ? drawableHeight : drawableWidth);
float beta = (float)((rotation % 180 == 90) ? drawableHeight : drawableWidth) /
(float)((rotation % 180 == 90) ? drawableWidth : drawableHeight);
int bitmap1Width = bitmap1.getWidth();
int bitmap1Height = bitmap1.getHeight();
Bitmap scaledImg = Bitmap.createScaledBitmap(bitmap2, (int)((float)bitmap1Width / alpha),
(int)(((float)bitmap1Width / alpha) / beta), false);
int bitmap2Width = scaledImg.getWidth();
int bitmap2Height = scaledImg.getHeight();
/*Log.e("cam", "" + bitmap1Width + ", " + bitmap1Height );
Log.e("img", "" + bitmap2Width + ", " + bitmap2Height );
Log.e("alpha", "" + alpha );
Log.e("beta", "" + beta );*/
float marginLeft = (float) (bitmap1Width * 0.5 - bitmap2Width * 0.5);
float marginTop = (float) (bitmap1Height * 0.5 - bitmap2Height * 0.5);
Bitmap overlayBitmap = Bitmap.createBitmap(bitmap1Width, bitmap1Height, bitmap1.getConfig());
Canvas canvas = new Canvas(overlayBitmap);
canvas.drawBitmap(bitmap1, new Matrix(), null);
canvas.drawBitmap(scaledImg, marginLeft, marginTop, null);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
overlayBitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
return new ByteArrayInputStream(stream.toByteArray());
}
private class AsyncImageLoader extends AsyncTask<String, Void, BitmapDrawable>{
private Realm realm;
private ProductModel product;
#Override
protected BitmapDrawable doInBackground(String... itemIds) {
realm = Realm.getDefaultInstance();
product = realm.where(ProductModel.class)
.equalTo("isIbr", selectedBrand)
.equalTo("id", itemIds[0])
.findFirst();
byte[] image = product.getImage();
product = null;
realm.close();
BitmapDrawable mDrawable = new BitmapDrawable(getResources(), BitmapFactory
.decodeByteArray(image, 0, image.length));
int mDrawableHeight = mDrawable.getIntrinsicHeight();
int mDrawableWidth = mDrawable.getIntrinsicWidth();
int valueInPixels = (int) getResources().getDimension(R.dimen.video_view_dimen);
mDrawable.setBounds(0, 0, valueInPixels, valueInPixels * mDrawableHeight / mDrawableWidth);
return mDrawable;
}
#Override
protected void onPostExecute(BitmapDrawable drawable) {
super.onPostExecute(drawable);
LayoutInflater vi = (LayoutInflater) getApplicationContext()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final View v = vi.inflate(R.layout.imageview_product, null);
((SizeAwareImageView)v).setImageDrawable(drawable);
ViewTreeObserver viewTreeObserver = v.getViewTreeObserver();
if (viewTreeObserver.isAlive()) {
viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
Log.e(TAG, "onGlobalLayout: updating sizes for drawable");
float[] sizez = ((SizeAwareImageView) v).getImageWidthAndHeight();
/*if (v.getRotation() == 90 || v.getRotation() == 270) {
drawableWidth = dp2px(sizez[1]);
drawableHeight = dp2px(sizez[0]);
} else {
drawableWidth = dp2px(sizez[0]);
drawableHeight = dp2px(sizez[1]);
}*/
drawableWidth = dp2px((int) sizez[0]);
drawableHeight = dp2px((int) sizez[1]);
/*Log.e("picB4Action", "" + drawableWidth + ", " + drawableHeight);*/
}
});
}
int px = (int) (getResources().getDimension(R.dimen.video_view_dimen)/* /
getResources().getDisplayMetrics().density*/);
mCameraView.addView(v, new FrameLayout.LayoutParams(px, px, Gravity.CENTER));
}
}
}
SizeAwareImageView.java :
public class SizeAwareImageView extends ImageView {
public SizeAwareImageView(Context context) {
super(context);
}
public SizeAwareImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SizeAwareImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public SizeAwareImageView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// Get image matrix values and place them in an array
float[] f = new float[9];
getImageMatrix().getValues(f);
// Extract the scale values using the constants (if aspect ratio maintained, scaleX == scaleY)
final float scaleX = f[Matrix.MSCALE_X];
final float scaleY = f[Matrix.MSCALE_Y];
// Get the drawable (could also get the bitmap behind the drawable and getWidth/getHeight)
final Drawable d = getDrawable();
final int origW = d.getIntrinsicWidth();
final int origH = d.getIntrinsicHeight();
// Calculate the actual dimensions
final int actW = Math.round(origW * scaleX);
final int actH = Math.round(origH * scaleY);
Log.e("DBG", "["+origW+","+origH+"] -> ["+actW+","+actH+"] & scales: x="+scaleX+" y="+scaleY);
}
public float[] getMatrixValues() {
float[] f = new float[9];
getImageMatrix().getValues(f);
return f;
}
public float[] getImageWidthAndHeight() {
// Get image matrix values and place them in an array
float[] f = new float[9];
getImageMatrix().getValues(f);
// Extract the scale values using the constants (if aspect ratio maintained, scaleX == scaleY)
final float scaleX = f[Matrix.MSCALE_X];
final float scaleY = f[Matrix.MSCALE_Y];
// Get the drawable (could also get the bitmap behind the drawable and getWidth/getHeight)
final Drawable d = getDrawable();
final int origW = d.getIntrinsicWidth();
final int origH = d.getIntrinsicHeight();
// Calculate the actual dimensions
final int actW = Math.round(origW * scaleX);
final int actH = Math.round(origH * scaleY);
//Log.e("DBG", "["+origW+","+origH+"] -> ["+actW+","+actH+"] & scales: x="+scaleX+" y="+scaleY);
return new float[] {actW, actH, scaleX, scaleY};
}
}
My question is that I will take an image from camera and it will be sent to an image view in an activity. After that I need to draw a circle or rectangle on the image.it should be a free hand. I mean I want to draw at any size. Then that image should be saved. I tried to put the image to the view but I am unable to draw on it. I am new to android. Can anyone help me out of this?
//This is camera Intent
camera =(Button)findViewById(R.id.camera_button);
camera.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
rl_main.setVisibility(View.GONE);
rl_image.setVisibility(View.VISIBLE);
Intent intent =new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
fileUri = getOutputMediaFileUri(REQUEST_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
// start the image capture Intent
startActivityForResult(intent, REQUEST_IMAGE_CAPTURE);
}
});
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case SPEECH_RECOGNITION_CODE: {
if (resultCode == RESULT_OK && null != data) {
ArrayList<String> result = data
.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
String text = result.get(0);
description.setText(text);
}
break;
}
case REQUEST_IMAGE_CAPTURE:
{
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
loadimage();
}
}
}
}
private void loadimage() {
if (fileUri!=null){
Bitmap myImg = BitmapFactory.decodeFile(fileUri.getPath());
File file = new File(fileUri.getPath());
BitmapFactory.Options bounds =new BitmapFactory.Options();
bounds.inSampleSize = 4;
bounds.inJustDecodeBounds = true;
String path = file.getPath();
BitmapFactory.decodeFile(path,bounds);
BitmapFactory.Options opts =new BitmapFactory.Options();
opts.inSampleSize = 4;
Bitmap bm = BitmapFactory.decodeFile(path,opts);
ExifInterface exif =null;
try {
exif =new ExifInterface(path);
} catch (IOException e) {
e.printStackTrace();
}
String orientString = exif.getAttribute(ExifInterface.TAG_ORIENTATION);
int orientation = orientString != null ? Integer.parseInt(orientString) : ExifInterface.ORIENTATION_NORMAL;
int rotationAngle = 0;
if (orientation == ExifInterface.ORIENTATION_ROTATE_90){
rotationAngle = 90;
}
if (orientation == ExifInterface.ORIENTATION_ROTATE_180){
rotationAngle = 180;
}
if (orientation == ExifInterface.ORIENTATION_ROTATE_270){
rotationAngle = 270;
}
final Matrix matrix = new Matrix();
matrix.setRotate(rotationAngle, (float) bm.getWidth() / 2, (float) bm.getHeight() / 2);
Bitmap rotatedBitmap = Bitmap.createBitmap(bm, 0, 0, bounds.outWidth,bounds.outHeight, matrix, true);
/* Matrix matrix = new Matrix();
matrix.postRotate(90);
Bitmap rotated = Bitmap.createBitmap(myImg, 0, 0, myImg.getWidth(), myImg.getHeight(),
matrix, true);*/
Bitmap mutableBitmap = rotatedBitmap.copy(Bitmap.Config.ARGB_8888, true);
camera_IV.setImageBitmap(mutableBitmap);
DisplayMetrics displaymetrics =new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
int height1 = displaymetrics.heightPixels;
int width1 = displaymetrics.widthPixels;
Log.e("MA", "Height= " + height1 + " " + width1);
paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.GREEN);
paint.setStrokeWidth(3);
// paint.setTextSize(25);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeCap(Paint.Cap.ROUND);
originalBitmap =Bitmap.createScaledBitmap(rotatedBitmap, camera_IV.getWidth(), camera_IV.getHeight(), false);
imageBitmap = originalBitmap.copy(Bitmap.Config.RGB_565, true);
camera_IV.setOnDragListener(new View.OnDragListener() {
#Override
public boolean onDrag(View view, DragEvent dragEvent) {
return false;
}
});
camera_IV.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View arg0, MotionEvent event) {
});
BitmapFactory.Options myOptions = new BitmapFactory.Options();
myOptions.inDither = true;
myOptions.inScaled = false;
myOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;// important
myOptions.inPurgeable = true;
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(0xFFFF0000);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
// mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(10);
}
}
`
I have an activity which contains a gridview which is used to display the images by camera or gallery, however I found that it may cause OutOfMemory exception sometimes, this is the code codes, I am not sure what's the problem?
public class WaterPointSubmitActivity extends Activity {
private final int DIALOG_TYPE_IMAGE = 11;
private final int Result_Code_Camera = 11;
private final int Result_Code_Local = 12;
private final int Dialog_Source_Value_TakePhoto = 0; // the index in the array.xml
private final int Dialog_Source_value_Local = 1;
private ArrayList<String> mGridViewImages = new ArrayList<String>();
private GridView mGridView;
private ImageAdapter mGridViewAdapter;
private ImageView mImageAddButton;
private Uri mPhotoToBeUploadURI;
private AsyncHttpClient mAsyncHttpClient = Helper.getAsyncHttpClient();
private RequestHandle mCurrentRequset;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_point_submit);
this.setupViews();
}
private void setupViews() {
mGridView = (GridView) findViewById(R.id.images_grid_view);
mGridViewAdapter = new ImageAdapter(this, R.layout.common_expose_image_item, mGridViewImages);
mGridView.setAdapter(mGridViewAdapter);
//trigger the image choose dialog
mImageAddButton = (ImageView) findViewById(R.id.pollution_add_image);
mImageAddButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
showDialog(DIALOG_TYPE_IMAGE);
}
});
}
#Override
protected Dialog onCreateDialog(int id) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
switch (id) {
case DIALOG_TYPE_IMAGE:
builder.setTitle(getString(R.string.dialog_choose_photo)).setItems(R.array.point_image_source, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case Dialog_Source_Value_TakePhoto:
//get image by camera
mPhotoToBeUploadURI = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, new ContentValues());
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, mPhotoToBeUploadURI);
startActivityForResult(cameraIntent, Result_Code_Camera);
break;
case Dialog_Source_value_Local:
//from gallery
Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
photoPickerIntent.setType("image/*");
startActivityForResult(photoPickerIntent, Result_Code_Local);
break;
}
}
});
Dialog target = builder.create();
target.setCanceledOnTouchOutside(false);
return target;
}
return null;
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent) {
if (resultCode == RESULT_OK) {
String imageFile = null;
switch (requestCode) {
case Result_Code_Camera:
String[] projection = {
MediaStore.MediaColumns._ID,
MediaStore.Images.ImageColumns.ORIENTATION,
MediaStore.Images.Media.DATA
};
Cursor c = getContentResolver().query(mPhotoToBeUploadURI, projection, null, null, null);
c.moveToFirst();
imageFile = c.getString(c.getColumnIndexOrThrow(MediaStore.Images.Media.DATA));
break;
case Result_Code_Local:
Uri selectedImage = imageReturnedIntent.getData();
String[] filePathColumn = {MediaStore.Images.Media.DATA};
Cursor cursor = getContentResolver().query(selectedImage, filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
imageFile = cursor.getString(columnIndex);
cursor.close();
break;
}
mGridViewImages.add(imageFile);
mGridViewAdapter.notifyDataSetChanged();
}
}
class ImageAdapter extends ArrayAdapter<String> {
private int mResourceId;
public ImageAdapter(Context context, int resource, List<String> items) {
super(context, resource, items);
mResourceId = resource;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null || convertView.getTag() == null) {
convertView = getLayoutInflater().inflate(mResourceId, parent, false);
holder = new ViewHolder();
holder.pointImage = (ImageView) convertView.findViewById(R.id.pollution_image);
holder.pointDeleteImage = convertView.findViewById(R.id.pollution_image_delete);
convertView.setTag(holder);
holder.pointDeleteImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
deleteImage(position);
}
});
} else {
holder = (ViewHolder) convertView.getTag();
}
String filePath = getItem(position);
if (filePath != null) {
Bitmap bitmap = BitmapFactory.decodeFile(filePath);
holder.pointImage.setImageBitmap(bitmap);
}
return convertView;
}
}
private void deleteImage(int position) {
mGridViewImages.remove(position);
mGridViewAdapter.notifyDataSetChanged();
}
static class ViewHolder {
ImageView pointImage;
View pointDeleteImage;
}
}
What's the problem?
your view is loading full sized bitmaps causing OOM use BitmapFactory options to scale the bitmap before it is loaded into memory
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(selectedImagePath, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
String imageType = options.outMimeType;
options.inSampleSize = calculateInSampleSize(options,320,480);
options.inJustDecodeBounds = false;
Bitmap photo = BitmapFactory.decodeFile(selectedImagePath,options);
Helper Method
public int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
// Calculate ratios of height and width to requested height and width
final int heightRatio = Math.round((float) height / (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
// Choose the smallest ratio as inSampleSize value, this will guarantee
// a final image with both dimensions larger than or equal to the
// requested height and width.
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
return inSampleSize;
}
You just need to add this line to your manifest file....It will allocate the large memory for your application..
android:largeHeap="true"