如何使用实时贴纸制作自定义相机
Posted
技术标签:
【中文标题】如何使用实时贴纸制作自定义相机【英文标题】:How to make a custom Camera with live Stickers 【发布时间】:2017-03-20 10:20:01 【问题描述】:我正在制作一个带有人脸检测功能的自定义相机,效果很好。
但我想在录制/预览的面孔上添加贴纸。 眼睛的位置用于在预览中正确调整和放置帽子、眼镜和领带等。
使用 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();
我想在预览中添加帽子和太阳镜,就像在 Play 商店中一样,Face 28:
更多信息。
我正在使用MoodMeSDK to detect the eyes and mouth
结果是 66 分:
我想在脸上戴上太阳镜、帽子、嘴唇等。在 Face28 APK 中使用 SVG 文件制作面部贴纸。
【问题讨论】:
多么酷的应用程序!没有简单的方法可以在这样的级别上完成这项任务。我相信这个团队使用了比内置的更先进的人脸检测库。 @AlexCohn 谢谢你看那个......我正在搜索那个图书馆或其他一些,但这项任务对我来说并不容易。 显而易见的起点是 OpenCV 项目。 是的@AlexCohn 我正在做这样的事情...... SDK 提供者有官方论坛支持,one related topic already posted。检测到的“地标”点已编号(SDK 为您提供了一个浮点数组)。创建一个顶点(使用 3d 的)覆盖地标的网格,对其应用纹理并将其渲染为 openGL 纹理是微不足道的。 【参考方案1】:我以前做过类似的事情。所以你需要这样做:首先你需要定位相对于View的Rectangle的点,例如如果你想放置一个帽子,首先根据CameraView定位帽子的头部和相对矩形,然后放置那个坐标上的帽子。这是简单的部分。困难的部分是保存图像。为此,您需要保存 CameraView 的宽度和长度以及其上的贴纸及其在 CameraView 上的位置。然后你捕捉图像并获得一个位图/绘图。对于生成的位图,您很可能会得到与 CameraView 不同的大小,因此您需要根据它与 CameraView 的 w/h 重新计算该位图上贴纸的坐标,并在新坐标上合并贴纸,然后保存。这并不容易,但我做到了。
这是我的代码(在我的例子中,贴纸被放置在图片的中心):
/**
* 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;
【讨论】:
你能分享你的工作吗? 你能提供这些类吗simport bronteel.ir.dcatalogue.widgets.SizeAwareImageView;导入 io.realm.Realm;还有 ProductModel @Arjunsaini 我已经添加了 SizeAwareImageView,但 Realm 只是库:realm.io 和 ProductModel 是我的领域数据库模型,这不会是你的问题。 您在 cameraView 中拍摄了什么? 它也是一个图书馆,你搜索一下很容易找到以上是关于如何使用实时贴纸制作自定义相机的主要内容,如果未能解决你的问题,请参考以下文章