我想在相机拍摄的所有图像中添加水印。问题是前后摄像头的图像尺寸不同。因此,水印的大小不同。就像在后置摄像头一样,水印变得更小,在前置摄像头,因为图像尺寸小于后置摄像头,水印会变得更大。如何在所有图片中将水印设置为相同大小。
这是我的代码:
public class CameraActivity extends Activity implements Callback,
OnClickListener {
private SurfaceView surfaceView;
private SurfaceHolder surfaceHolder;
private Camera camera;
private Button flipCamera;
private Button flashCameraButton;
private Button captureImage;
private int cameraId;
private boolean flashmode = false;
private int rotation;
public static int i=0;
ArrayList<File> captured_image;
List<Camera.Size> mSupportedPreviewSizes;
public static Camera.Size mPreviewSize;
MeasureSize measureSize;
public static Camera.Size size;
public static int state=0;
@Override
protected void onResume() {
super.onResume();
i=0;
captured_image.clear();
captureImage.setVisibility(View.VISIBLE);
}
@Override
protected void onPause() {
super.onPause();
releaseCamera();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.camera);
// camera surface view created
cameraId = CameraInfo.CAMERA_FACING_BACK;
flipCamera = (Button) findViewById(R.id.flipCamera);
flashCameraButton = (Button) findViewById(R.id.flash);
captureImage = (Button) findViewById(R.id.captureImage);
surfaceView = (SurfaceView) findViewById(R.id.surfaceView);
captured_image = new ArrayList<>();
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
flipCamera.setOnClickListener(this);
captureImage.setOnClickListener(this);
flashCameraButton.setOnClickListener(this);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
if (Camera.getNumberOfCameras() > 1) {
flipCamera.setVisibility(View.VISIBLE);
}
if (!getBaseContext().getPackageManager().hasSystemFeature(
PackageManager.FEATURE_CAMERA_FLASH)) {
flashCameraButton.setVisibility(View.GONE);
}
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
if (!openCamera(CameraInfo.CAMERA_FACING_BACK)) {
alertCameraDialog();
}
}
private boolean openCamera(int id) {
boolean result = false;
cameraId = id;
releaseCamera();
try {
camera = Camera.open(cameraId);
} catch (Exception e) {
e.printStackTrace();
}
if (camera != null) {
try {
setUpCamera(camera);
camera.setErrorCallback(new ErrorCallback() {
@Override
public void onError(int error, Camera camera) {
}
});
camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
result = true;
} catch (IOException e) {
e.printStackTrace();
result = false;
releaseCamera();
}
}
return result;
}
private void setUpCamera(Camera c)
{
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(cameraId, info);
rotation = getWindowManager().getDefaultDisplay().getRotation();
int degree = 0;
switch (rotation)
{
case Surface.ROTATION_0:
degree = 0;
break;
case Surface.ROTATION_90:
degree = 90;
break;
case Surface.ROTATION_180:
degree = 180;
break;
case Surface.ROTATION_270:
degree = 270;
break;
default:
break;
}
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT)
{
// frontFacing
rotation = (info.orientation + degree) % 330;
rotation = (360 - rotation) % 360;
}
else
{
// Back-facing
rotation = (info.orientation - degree + 360) % 360;
}
c.setDisplayOrientation(rotation);
mSupportedPreviewSizes = c.getParameters().getSupportedPreviewSizes();
Camera.Parameters parameters = c.getParameters();
measureSize = new MeasureSize(this);
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
if (parameters.getSupportedFocusModes().contains(
Parameters.FOCUS_MODE_CONTINUOUS_PICTURE))
{
parameters.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
}
List<Camera.Size> sizes = parameters.getSupportedPictureSizes();
size = sizes.get(0);
for (int i = 0; i < sizes.size(); i++) {
if (sizes.get(i).width > size.width) {
size = sizes.get(i);
}
}
parameters.setPictureSize(size.width, size.height);
}
c.setParameters(parameters);
Parameters params = c.getParameters();
showFlashButton(params);
List<String> focusModes = params.getSupportedFlashModes();
if (focusModes != null)
{
if (focusModes
.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
params.setFlashMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
}
}
params.setRotation(rotation);
}
private void showFlashButton(Parameters params) {
boolean showFlash = (getPackageManager().hasSystemFeature(
PackageManager.FEATURE_CAMERA_FLASH) && params.getFlashMode() != null)
&& params.getSupportedFlashModes() != null
&& params.getSupportedFocusModes().size() > 1;
flashCameraButton.setVisibility(showFlash ? View.VISIBLE
: View.INVISIBLE);
}
private void releaseCamera() {
try {
if (camera != null) {
camera.setPreviewCallback(null);
camera.setErrorCallback(null);
camera.stopPreview();
camera.release();
camera = null;
}
} catch (Exception e) {
e.printStackTrace();
Log.e("error", e.toString());
camera = null;
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height)
{
if (surfaceHolder.getSurface() == null){
// preview surface does not exist
return;
}
// stop preview before making changes
try {
camera.stopPreview();
} catch (Exception e){
// ignore: tried to stop a non-existent preview
}
// set preview size and make any resize, rotate or reformatting changes here
// start preview with new settings
try {
Camera.Parameters parameters = camera.getParameters();
camera.setDisplayOrientation(90);
camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
} catch (Exception e){
Log.d("Activity", "Error starting camera preview: " + e.getMessage());
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.flash:
flashOnButton();
break;
case R.id.flipCamera:
flipCamera();
break;
case R.id.captureImage:
takeImage();
break;
default:
break;
}
}
private void takeImage() {
camera.takePicture(null, null, new PictureCallback() {
private File imageFile;
@Override
public void onPictureTaken(byte[] data, Camera camera) {
try {
// convert byte array into bitmap
Bitmap loadedImage = null;
Bitmap rotatedBitmap = null;
loadedImage = BitmapFactory.decodeByteArray(data, 0,
data.length);
Log.e("Activity", "IMAGE " + data.length);
// rotate Image
Matrix rotateMatrix = new Matrix();
rotateMatrix.postRotate(rotation);
rotatedBitmap = Bitmap.createBitmap(loadedImage, 0, 0,
loadedImage.getWidth(), loadedImage.getHeight(),
rotateMatrix, false);
int w = rotatedBitmap.getWidth();
int h = rotatedBitmap.getHeight();
//cropped bitmap
Bitmap result = Bitmap.createBitmap(w, h, rotatedBitmap.getConfig());
Canvas canvas = new Canvas(result);
canvas.drawBitmap(rotatedBitmap, 0, 0, null);
Bitmap waterMark = BitmapFactory.decodeResource(getResources(), R.drawable.watermark2);
float hh = waterMark.getHeight();
float ww = waterMark.getWidth();
canvas.drawBitmap(waterMark, w - ww, h - hh, null);
String state = Environment.getExternalStorageState();
File folder = null;
if (state.contains(Environment.MEDIA_MOUNTED)) {
folder = new File(Environment
.getExternalStorageDirectory() + "/Pictures");
} else {
folder = new File(Environment
.getExternalStorageDirectory() + "/Pictures");
}
boolean success = true;
if (!folder.exists()) {
success = folder.mkdirs();
}
if (success) {
java.util.Date date = new java.util.Date();
imageFile = new File(folder.getAbsolutePath()
+ File.separator
+ new Timestamp(date.getTime()).toString()
+ "Image.jpg");
imageFile.createNewFile();
} else {
Toast.makeText(getBaseContext(), "Image Not saved",
Toast.LENGTH_SHORT).show();
return;
}
ByteArrayOutputStream ostream = new ByteArrayOutputStream();
// save image into gallery
result.compress(CompressFormat.JPEG, 100, ostream);
FileOutputStream fout = new FileOutputStream(imageFile);
fout.write(ostream.toByteArray());
fout.close();
captured_image.add(imageFile);
ContentValues values = new ContentValues();
values.put(Images.Media.DATE_TAKEN,
System.currentTimeMillis());
values.put(Images.Media.MIME_TYPE, "image/jpeg");
values.put(MediaStore.MediaColumns.DATA,
imageFile.getAbsolutePath());
CameraActivity.this.getContentResolver().insert(
Images.Media.EXTERNAL_CONTENT_URI, values);
} catch (Exception e) {
e.printStackTrace();
}
finally {
i++;
if(i<5) {
if(i>2) {
camera.startPreview();
creategif.setVisibility(View.VISIBLE);
}
else
{
camera.startPreview();
}
}
else
{
captureImage.setVisibility(View.INVISIBLE);
Toast.makeText(CameraActivity.this,"You can't take more than 5 pictures", Toast.LENGTH_LONG).show();
}
}
}
});
}
private void flipCamera() {
int id = (cameraId == CameraInfo.CAMERA_FACING_BACK ? CameraInfo.CAMERA_FACING_FRONT
: CameraInfo.CAMERA_FACING_BACK);
if (!openCamera(id)) {
alertCameraDialog();
}
}
private void alertCameraDialog() {
AlertDialog.Builder dialog = createAlert(CameraActivity.this,
"Camera info", "error to open camera");
dialog.setNegativeButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
dialog.show();
}
private Builder createAlert(Context context, String title, String message) {
AlertDialog.Builder dialog = new AlertDialog.Builder(
new ContextThemeWrapper(context,
android.R.style.Theme_Holo_Light_Dialog));
// dialog.setIcon(R.drawable.ic_launcher);
if (title != null)
dialog.setTitle(title);
else
dialog.setTitle("Information");
dialog.setMessage(message);
dialog.setCancelable(false);
return dialog;
}
private void flashOnButton() {
if (camera != null) {
try {
Parameters param = camera.getParameters();
param.setFlashMode(!flashmode ? Parameters.FLASH_MODE_TORCH
: Parameters.FLASH_MODE_OFF);
camera.setParameters(param);
flashmode = !flashmode;
} catch (Exception e) {
// TODO: handle exception
}
}
}
public void gallery(View v)
{
Intent i = new Intent(CameraActivity.this, GIFGallery.class);
i.putExtra("arraylist", captured_image);
startActivity(i);
}
public void reset_gallery(View v)
{
i=0;
captured_image.clear();
captureImage.setVisibility(View.VISIBLE);
camera.startPreview();
}
public class MeasureSize extends View {
public MeasureSize(Context context) {
super(context);
measure(surfaceView.getWidth(), surfaceView.getHeight());
}
@Override
protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) {
if (mSupportedPreviewSizes != null) {
mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, surfaceView.getWidth(), surfaceView.getHeight());
}
}
}
private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.1;
double targetRatio=(double)h / w;
if (sizes == null) return null;
Camera.Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
for (Camera.Size size : sizes) {
double ratio = (double) size.width / size.height;
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Camera.Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
Log.e("Activity", "OPTIMAL SIZE " + optimalSize);
return optimalSize;
}
}
我尝试通过将参数设置为previewSize来使前后摄像头的图像尺寸相同。但由于大小无效,它会给出运行时异常:
parameters.setPictureSize(mPreviewSize.width, mPreviewSize.height);
答案 0 :(得分:1)
基本上,实现这一目标的最佳方法是创建某种缩放算法。例如,您说您希望水印代表宽度的20%和高度的20%。好吧,如果图像是1000x1000那么你会知道水印将是200x200。这将适用于所有不同的图像尺寸。只需获取图像的宽度和高度,并设置希望水印表示的宽度和高度的百分比。