안 드 로 이 드 사진 압축 의 튜 닝 을 한 번 기억 해 주세요.
4601 단어 작업 기록 (Android)
머리말 에서 이번 변조 의 배경 이다. 그리고 인터넷 에서 사진 압축 을 검색 하여 품질 압축 과 사이즈 압축 으로 나 누 었 다. 품질 압축 과 사이즈 압축 의 차 이 는 다음 과 같다.
질량 압축
알고리즘 을 통 해 그림 의 특정한 점 근처에 있 는 픽 셀 을 잠 그 고 품질 을 낮 추어 파일 크기 를 줄 이 는 목적 을 달성 했다.여기 서 주의해 야 할 것 은 이렇게 압축 된 그림 자체 의 픽 셀 너비 와 높이 는 변 하지 않 지만 그림 파일 의 크기 는 확실히 작 아 지기 때문에 Base 64 길이 도 짧 아 집 니 다. 그러면 원칙적으로 품질 압축 으로 제 요 구 를 만족 시 킬 수 있 습 니 다.그러나 만약 에 제 가 원래 이 그림 을 사용 해 야 한다 면 똑 같은 메모 리 를 사용 할 것 입 니 다. 원생 이 사용 하면 bitmap 형식 으로 표시 할 것 입 니 다. bitmap 가 메모리 에 대한 점용 은 그림 픽 셀 에 따라 계 산 됩 니 다.
사이즈 압축
이 압축 은 그림 의 픽 셀 값 을 실질 적 으로 줄 이 는 것 이다.
상기 두 가 지 를 결합 하면 나 는 최종 적 으로 두 가 지 를 결합 하 는 방식 으로 이 수 요 를 실현 하기 로 결정 했다.먼저 사이즈 압축 을 하고 목표 크기 로 압축 한 다음 에 품질 압축 을 해서 Base 64 길 이 를 줄 입 니 다.
최종 적 으로 저 는 사이즈 에 따라 1M 정도 이하 로 압축 하고 품질 은 100 K 이하 로 압축 합 니 다. 코드 는 다음 과 같 습 니 다.
/**
* + ( , )
*
* @param ref KB ref1 KB
*/
private String dimensionCompress(File file, long ref,int ref1) {
long length = file.length() / 1024;
String result = "";
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;// true , , bitmap null
BitmapFactory.decodeFile(file.getAbsolutePath(), options);
int inSampleSize = 2;// , 。
if (length > ref) { // px
float ratio = (float) length / ref; //
inSampleSize = (int) ratio;
}
options.inJustDecodeBounds = false; // ,
options.inSampleSize = inSampleSize;
Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath(), options); //
BufferedOutputStream bos = null;
ByteArrayOutputStream byteArrayOutputStream = null;
int quality = 100;
try {
if (bitmap != null) {
byteArrayOutputStream = new ByteArrayOutputStream();
bos = new BufferedOutputStream(byteArrayOutputStream);
bitmap.compress(Bitmap.CompressFormat.JPEG, quality, bos);
if(byteArrayOutputStream.toByteArray().length/1024>ref1){
quality = 100*ref1/(byteArrayOutputStream.toByteArray().length/1024);
byteArrayOutputStream.reset();
bitmap.compress(Bitmap.CompressFormat.JPEG, quality, bos);
}
bos.flush();
bos.close();
byteArrayOutputStream.flush();
byteArrayOutputStream.close();
byte[] bitmapBytes = byteArrayOutputStream.toByteArray();
result = Base64.encodeToString(bitmapBytes, Base64.NO_WRAP);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (bos != null) {
bos.flush();
bos.close();
}
if (byteArrayOutputStream != null) {
byteArrayOutputStream.flush();
byteArrayOutputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return result;
}
이 방법 을 쓸 때 나 는 BitmapFactory. decodeFile 방법 을 한 번 호출 하 는 데 200 ms 정도 의 시간 이 필요 하 다 는 것 을 알 게 되 었 다. 느낌 이 좀 길 었 다. 더 좋 은 방법 이 있다 면 누군가가 나 에 게 알려 주 기 를 바란다.업무 장면 이 복잡 하기 때문에 시간 을 최대한 줄 이 는 취지 에 따라 저 는 먼저 목표 의 크기 에 따라 제 가 몇 배 정도 압축 해 야 하 는 지 계산 한 다음 에 한 번 만 압축 하 는 것 입 니 다. 인터넷 의 목표 픽 셀 너비 에 따라 여러 번 압축 하 는 것 이 아 닙 니 다.또한, 여기 서 주의해 야 할 것 은 options. inSampleSize 라 는 값 은 영원히 2 의 배수 로 계산 하 는 것 입 니 다. 예 를 들 어 9 를 설정 하면 그 는 8 (2 의 3 차원) 에 따라 계산 할 것 입 니 다.품질 압축 의 목표 치 에 대해 제 가 설정 한 100 K 는 다음 과 같은 고려 를 바탕 으로 합 니 다. 사이즈 압축 을 한 후의 그림 크기 는 1M 보다 크 지 않 을 것 입 니 다. 그러면 품질 압축 률 은 90% 보다 크 지 않 을 것 입 니 다. 마지막 으로 바닥 을 남 겨 서 일 그 러 짐 률 을 확보 하 세 요.
이로써 이번 조정 은 끝 났 습 니 다. 한 번 호출 하 는 방법 은 800 ms 가 되 지 않 았 습 니 다. 이것 은 나중에 방법 을 찾 아 최적화 할 수 있 습 니 다. 다음 에 다시 오 겠 습 니 다.
2019018 수정 테스트 를 통 해 그 내용 이 비교적 많은 사진, 예 를 들 어 찍 은 엑셀 의 사진 (안에 모두 문자 데이터 정보), 한도 값 을 1M, 100 K 로 설정 하면 심각 한 일 그 러 짐 을 초래 할 수 있다. 나중에 3000 K, 1000 K 로 설정 할 때 이런 그림 이 든 다른 그림 이 든 모두 정상적으로 표 시 될 수 있다.그래서 현 재 는 한도 값 을 바 꾸 었 기 때문에 계속 연구 하고 개선 할 수 밖 에 없다.