1. 程式人生 > >自己寫了一個拍照的頁面,但是儲存的圖片太模糊了。求大神幫忙看看

自己寫了一個拍照的頁面,但是儲存的圖片太模糊了。求大神幫忙看看

 
public class PhotographActivity extends Activity implements
SeekBar.OnSeekBarChangeListener, OnClickListener, Runnable {
private ImageView takePic, back, flash;// 按鈕
private final int FLASH_AUTO = 0;// 自動閃光
private final int FLASH_OFF = 1;// 閃光燈關閉
private final int FLASH_ON = 2; // 閃光燈開啟
private int flashImg[] = { R.drawable.light_auto_confirm,
R.drawable.light_off_confirm, R.drawable.light_on_confirm };// 閃光燈圖示
private boolean preview = false, flashOpen = false;// preview預覽 flashOpen閃光燈
private Camera camera;// 硬體相機
private SurfaceView cameraBG;// 相機預覽
@SuppressWarnings("unused")
private Uri videoFilePath;
// PopupWindow和AlertDialog都是Android對話方塊的內容,不同的是PopupWindow是阻塞式對話方塊
PopupWindow popupWindow;
private Camera.Parameters parameters;// 照相機引數集
private BitmapFactory.Options options = new BitmapFactory.Options();
private int ScreenW, ScreenH;// 螢幕寬高

@Override
public void onCreate(Bundle savedInstanceState) {

// 獲得螢幕寬高
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
ScreenW = metrics.widthPixels;
ScreenH = metrics.heightPixels;
Log.d("螢幕寬高", ScreenW + "," + ScreenH);
if (!Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {// SD卡允許讀寫
Toast.makeText(PhotographActivity.this, "SD卡沒有插入或不能讀寫",
Toast.LENGTH_LONG).show();
}
Window window = getWindow();
// 只要這個視窗是使用者可見的,保持裝置的螢幕開啟及明亮。
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
// 選擇支援半透明模式,在有surfaceview的activity中使用。
window.setFormat(PixelFormat.TRANSLUCENT);
requestWindowFeature(Window.FEATURE_NO_TITLE);// 去掉標題欄
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);// 去掉資訊欄
super.onCreate(savedInstanceState);

setContentView(R.layout.activity_photograph);
init();
}

@SuppressLint("NewApi")
private void init() {
options.inSampleSize = 2;// 圖片寬高都為原來的2分之一,即圖片為原來的4分之一
takePic = (ImageView) findViewById(R.id.btn_picture);// 拍照
back = (ImageView) findViewById(R.id.btn_backcapter);// 返回
flash = (ImageView) findViewById(R.id.btn_flash);// 調整閃光效果
cameraBG = (SurfaceView) findViewById(R.id.camrea);// 相機預覽
// 固定surfaceView的高寬
cameraBG.getHolder().setFixedSize(ScreenW, ScreenH);
// 設定該surfaceView不用自己維護緩衝區
cameraBG.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
// 設定surfaceView的回撥函式
cameraBG.getHolder().addCallback(new SurfaceCallback());
takePic.setOnClickListener(this);
back.setOnClickListener(this);
flash.setOnClickListener(this);
cameraBG.setOnClickListener(this);
}

private final class SurfaceCallback implements SurfaceHolder.Callback {
@Override
public void surfaceCreated(SurfaceHolder holder) {
if (camera != null) {
camera.release();// 相機釋放
}
camera = Camera.open();// 開啟相機
camera.setDisplayOrientation(90);// 旋轉鏡頭

parameters = camera.getParameters();// 獲取相機引數集
if (parameters.getFlashMode() == null) {
flash.setImageResource(flashImg[FLASH_OFF]);
Toast.makeText(PhotographActivity.this, "無閃光燈",
Toast.LENGTH_SHORT).show();
} else {
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO);
List<Size> SupportedPreviewSizes = parameters
.getSupportedPreviewSizes();// 獲取支援預覽照片的尺寸
Size previewSize = SupportedPreviewSizes.get(0);// 從List取出Size
parameters
.setPreviewSize(previewSize.width, previewSize.height);// 設定預覽照片的大小
List<Size> supportedPictureSizes = parameters
.getSupportedPictureSizes();// 獲取支援儲存圖片的尺寸
Size pictureSize = supportedPictureSizes.get(0);// 從List取出Size
parameters
.setPictureSize(pictureSize.width, pictureSize.height);// 設定照片的大小
camera.setParameters(parameters);
}
try {
camera.setPreviewDisplay(cameraBG.getHolder());// 設定相機預覽
} catch (IOException e) {
e.printStackTrace();
}
camera.startPreview();// 開始預覽
preview = true;

}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {

}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (camera != null) {
if (preview) {
camera.stopPreview();
}
camera.release();
}
}

}

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (camera != null && event.getRepeatCount() == 0) {
switch (keyCode) {
case KeyEvent.KEYCODE_CAMERA:
case KeyEvent.KEYCODE_DPAD_CENTER:
takPicture();
break;
case KeyEvent.KEYCODE_BACK:
if (flashOpen) {
popupWindow.dismiss();
} else {
finish();
}
}
}
return true;
}

private final class TakePictureCallback implements PictureCallback {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
String sdStatus = Environment.getExternalStorageState();
if (!sdStatus.equals(Environment.MEDIA_MOUNTED)) {
// 檢測sd是否可用
Toast.makeText(PhotographActivity.this, "沒有SD卡或SD卡不可用!",
Toast.LENGTH_LONG).show();
return;
} else {
Log.d("解碼", "data.length=" + data.length);
// 解碼指定位元組陣列中的一個不變的點陣圖
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0,
data.length, options);
Log.d("解碼", "1*******");
// 旋轉圖片 動作
Matrix matrix = new Matrix();
matrix.postRotate(90);
Log.d("儲存照片", "0");
// 建立新的圖片
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
bitmap.getHeight(), matrix, true);
Uri resource_uri = Uri.parse(MediaStore.Images.Media
.insertImage(getContentResolver(), bitmap, null, null));
Log.d("儲存照片", "1");
BufferedOutputStream bos = null;
try {
bitmap = MediaStore.Images.Media.getBitmap(
getContentResolver(), resource_uri);
String name = getCurrentTime() + ".jpg";
File file = new File(
Environment.getExternalStorageDirectory()
+ "/DCIM/Camera/");
file.mkdirs();// 嘗試建立系統默相簿資料夾
String image_Path = Environment
.getExternalStorageDirectory()
+ "/DCIM/Camera/"
+ name;
bos = new BufferedOutputStream(new FileOutputStream(
image_Path));
Log.d("bos", bos.toString());
// 壓縮點陣圖到指定的輸出流
// 第一個引數:壓縮的格式
// 第二個引數:壓縮的質量,100即為無失真壓縮
// 第三個引數:壓縮到制定的流
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);// 把資料寫入檔案
bitmap.recycle();
scanPhoto(image_Path);// 掃描資料夾
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Bitmap bitmap2 = MediaStore.Images.Media.getBitmap(
getContentResolver(), resource_uri);
Log.d("bitmap2", bitmap2.toString());
if (bitmap2.compress(CompressFormat.JPEG, 100, baos)) {
byte[] code = baos.toByteArray();
Log.d("拍照0", code.toString());
byte[] output = Base64.encode(code, Base64.NO_WRAP);
Log.d("拍照1", output.toString());
String Str = new String(output);
Log.d("長度", Str.length() + "");
JSONObject jsonObject = new JSONObject();
jsonObject.put("imgFileStr", Str);
jsonObject.put("imgPath", image_Path);
bitmap2.recycle();
Xxxplugin.callbackData.success(jsonObject);

}

} catch (Exception e) {
Log.d("異常", e.toString());
} finally {
try {
bos.close();
PhotographActivity.this.finish();
} catch (IOException e) {
e.getMessage();
}
}
}
}
}

public void takPicture() {
camera.autoFocus(null);// 自動對焦
// takePicture有一個過載,分別是三個引數,四個引數
// 三個引數的
// 第一個引數是按下快門觸發
// 第二引數是得到原始影象時候觸發
// 第三個是JPG圖片(系統處理後觸發);

// 四個引數的
// 第一個引數是按下快門觸發
// 第二引數是得到原始影象時候觸發
// 第三個是縮放和壓縮影象時觸發
// 第四個是JPG圖片(系統處理後觸發);
// camera.takePicture(shutter, raw, jpeg)
// camera.takePicture(shutter, raw, postview, jpeg)
camera.takePicture(null, null, null, new TakePictureCallback());
}

@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
camera.setParameters(parameters);
}

@Override
public void onStartTrackingTouch(SeekBar seekBar) {

}

@Override
public void onStopTrackingTouch(SeekBar seekBar) {

}

@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_picture:
takePic.setEnabled(false);
takPicture();
break;
case R.id.btn_backcapter:
if (flashOpen) {
popupWindow.dismiss();
} else {
finish();
}
break;
case R.id.btn_flash:
if (parameters.getFlashMode() == null) {
Toast.makeText(PhotographActivity.this, "無閃光燈",
Toast.LENGTH_SHORT).show();
} else if (parameters.getFlashMode() == Camera.Parameters.FLASH_MODE_AUTO) {
flash.setImageResource(flashImg[FLASH_OFF]);
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
camera.setParameters(parameters);
} else if (parameters.getFlashMode() == Camera.Parameters.FLASH_MODE_OFF) {
flash.setImageResource(flashImg[FLASH_ON]);
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_ON);
camera.setParameters(parameters);
} else if (parameters.getFlashMode() == Camera.Parameters.FLASH_MODE_ON) {
flash.setImageResource(flashImg[FLASH_AUTO]);
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO);
camera.setParameters(parameters);
}
break;
case R.id.camrea:
camera.autoFocus(null);
break;
}
}

@Override
public void run() {
while (true) {
if (camera != null) {
camera.autoFocus(null);
}
try {
Thread.sleep(400);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

}

/**
 * 得到當前系統的時間
 **/
private String getCurrentTime() {
SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd_HHmmss");
String str = format.format(new Date());
return str;

}

/**
 * 對資料夾進行掃描,使相簿可以及時顯示自己儲存的圖片(無需手機重啟)
 */
private void scanPhoto(String path) {
MediaScannerConnection.scanFile(PhotographActivity.this,
new String[] { path }, null, null);



}
 

相關推薦

自己一個拍照頁面但是儲存圖片模糊幫忙看看

  public class PhotographActivity extends Activity implements SeekBar.OnSeekBarChangeListener, OnClickListener, Runnable { private Ima

我是一個新手小白想學習C++程式設計但是不知道該如何入手們給出一個簡單的思路

如題所示,我現在準備學習C++程式語言,因為是0基礎,所以入門也顯的很迷茫,也看過一些視訊,感覺講的很好,但就是聽得雲裡霧裡,看著視訊也會嘗試敲一些程式碼,但是程式碼的意思,也都不懂,不知道該如何入手,所以就想到,如果要

Emergency(只有10分)儲存一下程式碼改正

#include <stdio.h> #include <stdlib.h> typedef struct LinkedNode *List; typedef int DistType; typedef int Vertex; typede

ibd格式的檔案過mysql老是報連線中斷的錯誤mysql新手幫忙!!!!

資料包有380G,一開始連線失敗,報的錯誤程式碼是“ERROR 2003(HY000):can’t connect to mysql server on ‘localhost’(10061) ”。第一次考慮了是mysql8小時自動斷開的問題,查詢相關文章以後,已

求助!!!連線不上本地SQLServer2014資料庫幫忙

附上原始碼: public class MainActivity extends Activity {private Button btn;private TextView showTV;     @Override     protected void onCreate(

vue 初始化專案報錯幫忙看下怎麼解決

執行:vue init webpack vue-demo  報錯: vue-cli · Failed to download repo vuejs-templates/webpack: unable to verify the first certificate

自己一個c++ bitset功能非常齊全!

c++ bitset用途很廣,而理解它的最好方式莫過於自己寫一個,重新造輪子還是非常有樂趣的,廢話不多說了,貼程式碼。 首先是一些必要的函式,封裝在名字空間mystd裡面。/*如果發現有bug,望高手批評指正!相互交流交流! * 轉載本文的註明一下出處,謝謝! */ #

C#.NET 程序員的福利自己一個XML操作類可實現像jquery一樣方便的xml操作且不用專門去處理命名空間

console region ignorecas node 處理 命名空間 void clone 一個 此工具是進入一家新公司之後實現的,主要是工作當中操作 xml 的時間太多,因為公司按任務計“工作量”,領導給我安排的時間遠遠不夠完善此工具【悲哀的

原生JS一個小demo根據輸入的數字生成不同背景顏色的小方塊兒~

top == UNC 定位元素 demo TE tostring eight 地方 昨天練習寫了這個小demo,個人覺得通過設置定位元素left和top的值,來實現換行的功能,這種方法很巧妙~ 另外,如下代碼中的隨機顏色的獲取,還請各位前輩多多指教:需要改進的地方;或者有

一個自己的抓包軟體支援外掛化指令碼分析

市場上的抓包工具已經足夠多,輕量級的,重量級的都有,典型的wireshark,smartsniff等, 各有優缺點,PowerSniff是為程式設計師準備的一款抓包工具,目標是使協議解析外掛編寫更簡單。檔案格式完全相容wiareshark和tcpdump。 原理:捕獲到資料就呼叫預設定的指令碼,將資料的指

maven工程中controller下一個url請求冒404

昨天在controll層寫了一請求,但是訪問該url,冒404,特別古怪的一個問題。大哥給了我一個反編譯class軟體(檢視eclipse的編譯結果) 去eclipse編譯資料夾下找到該class檔案,發現並沒有寫入進去。 首先我做了clean下編譯軟體,但是效果是並沒有

練習python一個四則運算程式支援乘方和“.3"這種格式

#!/usr/bin/python #coding=utf-8 # 本程式由使用者輸入一個表示式字串,然後計算這個表示式的值 # 表示式是一個四則運算表示式,可以包含^操作符# 注意:乘方用^運算子,支援".3"這種表示小數的形式。負數需要用括號擴起來 # 思路:利用棧的方

集合70多種推薦演算法東北大學老師用Java一個開源庫在GitHub上收穫近1500個Star...

 【AI科技大本營導讀】在經過一年多的開發工作之後,LibRec 3.0 版本終於釋出了。LibRec 是一個基於 Java 的開源演算法工具庫,覆蓋了 70 餘個各型別推薦演算法,可以有效解決評分預測和物品推薦兩大關鍵的推薦問題,目前已經在 GitHub 上收穫

一個hello.py執行出錯提示 File "" , line 1

寫了一個hello.py,僅有一句,print 'hello world', 執行 python hello.py 出錯,提示: File "<stdin>" , line 1 python hello.py 解釋: In the shell you

一個慢介面年終妥妥的325

一個專案要想抗住越大的壓力,那麼每個API都得在最短的時間內響應,這樣吞吐量才高。 在很多時候,開發壓根沒有去做過優化,等到某天壓力上來時,系統就扛不住了。 **舉一個最常見的例子:** 大家上班都會做地鐵(土豪可以開車哈)吧,地鐵都有固定的幾個入口,每個入口有幾個固定的閘機可以掃碼進入。 如果每個人

自己程式碼實現郵件傳送再也不用視覺化那麼麻煩

原文地址:https://www.keketec.club/posts/a6c96c4e/ > 學而知不足,長按關注,精彩不錯過 Python自動批量傳送郵件是一種什麼體驗? ![](https://img2020.cnblogs.com/blog/2193560/202101/2193560

一個函數計算參數為n(n很)時的值1-2+3-4+5-6+7……+n(考慮程序執行效率)

參數 color n) col sys class n-1 == code 1 private static void jisuan(int n) { 2 int sum=0; 3 if(n%2==0){ 4 sum=-(n/2)

CS61b lab3 分享一個bug足足找一個多小時希望各位別入坑哈

好的 log http 錯誤代碼 style obj item next slist part1: 寫一個測試程序,比較簡單就不貼代碼啦,運行結果: part2: 改進InserEnd method,我是按照課上講的把原來的singlyList變成doubleList,在

Android Studio 引用自己一個model

找到 gpo bsp mod model nbsp put 目的 body 1. 在以前的項目中,reBuild 項目完後,在具體某一個model下的build—>output—>aar下找到對應的AAR文件,用後綴名為release的aar。 2.把aar文件