Android WebP 그림 압축 및 전송

9820 단어 AndroidWebP
1.프로필
4g 시대 까지 유 동량 은 여전히 귀중 한 것 이 었 다.한편,모 바 일 네트워크 전송 에서 가장 많은 데 이 터 를 차지 하 는 캐리어:그림 은 우리 모 바 일 개발 자 들 이 주목 해 야 할 문제 가 되 었 다.
우리 가 주목 하 는 문 제 는 그림 의 부피 와 품질 이 어떻게 비교적 조화 로 운 균형 에 이 르 는 지,품질 이 좋 은 그림 을 얻 는 동시에 부피 가 너무 크 지 않 기 를 바 라 는 것 이다.
시 대 를 앞서 가 는 구 글 은 웹 P 라 는 좋 은 답 을 내 놓 았 다.
WebP 는 그림 파일 형식 으로 같은 압축 기준 에서 webp 의 손실 압축 은 jpg 보다 25-34%작다.내 테스트 에 서 는 50%가 작 을 때 도 있다.
2.대기업 배 서
WebP 는 2010 년 첫 번 째 버 전 을 발표 한 지 6 년 이 되 었 다.구 글 산하 각종 사이트 G+와 대표 적 인 유 튜브,그의 동 영상 파일 형식 인 WebM 은 WebP 구 조 를 바탕 으로 한 것 이다.
텐 센트,타 오 바 오,미 단도 일부 활용 된다 고 한다.
3.안 드 로 이 드 엔 드 JPG 변환 WebP
RxJava 스 레 드 변환:

 String[] imgs = new String[]{"1.jpg", "2.jpg", "3.jpg", "4.jpg", "5.jpg"};
 String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Pictures/test/";
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
// test = Api.getBuilder().create(Test.class);
 String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE
 , Manifest.permission.READ_PHONE_STATE
 , Manifest.permission.CAMERA};
 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
 requestPermissions(permissions, 0);
 }
 compress();
 }
 private void compress() {
 Observable.from(imgs)
 .subscribeOn(Schedulers.io())
 .doOnNext(new Action1<String>() {
  @Override
  public void call(String imgName) {
  compress(imgName);
  }
 })
 .subscribe();
 }
 private void compress(String imgName) {
 try {
 File file = new File(path, imgName);
 Log.i("compress", "jpg start");
 byte[] bytes = BitmapUtil.compressBitmapToBytes(file.getPath(), 600, 0, 60, Bitmap.CompressFormat.JPEG);
 File jpg = new File(path, imgName + "compress.jpg");
 FileUtils.writeByteArrayToFile(jpg, bytes);
 Log.i("compress", "jpg finish");
 Log.i("compress", "----------------------------------------------------");
 Log.i("compress", "webp start");
 byte[] bytes1 = BitmapUtil.compressBitmapToBytes(file.getPath(), 600, 0, 60, Bitmap.CompressFormat.WEBP);//       ,    ,  ,     ,     。
 File webp = new File(path, imgName + "compress.webp");
 FileUtils.writeByteArrayToFile(webp, bytes1);
 Log.i("compress", "webp finish");
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
내 테스트 기기 도 원 플러스 1,CM 13 이기 때문에 그 에 상응하는 권한 을 가 져 야 한다.
RxJava 를 이용 하여 스 레 드 작업 을 하고 io 스 레 드 에서 시간 소모 작업 을 했 습 니 다.

public static byte[] compressBitmapToBytes(String filePath, int reqWidth, int reqHeight, int quality, Bitmap.CompressFormat format) {
 Bitmap bitmap = getSmallBitmap(filePath, reqWidth, reqHeight);
 ByteArrayOutputStream baos = new ByteArrayOutputStream();
 bitmap.compress(format, quality, baos);
 byte[] bytes = baos.toByteArray();
 bitmap.recycle();
 Log.i(TAG, "Bitmap compressed success, size: " + bytes.length);
 return bytes;
 }
 public static Bitmap getSmallBitmap(String filePath, int reqWidth, int reqHeight) {
 BitmapFactory.Options options = new BitmapFactory.Options();
 options.inJustDecodeBounds = true;
 BitmapFactory.decodeFile(filePath, options);
 options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
 options.inJustDecodeBounds = false;
// options.inPreferQualityOverSpeed = true;
 return BitmapFactory.decodeFile(filePath, options);
 }
 public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
 int h = options.outHeight;
 int w = options.outWidth;
 int inSampleSize = 0;
 if (h > reqHeight || w > reqWidth) {
 float ratioW = (float) w / reqWidth;
 float ratioH = (float) h / reqHeight;
 inSampleSize = (int) Math.min(ratioH, ratioW);
 }
 inSampleSize = Math.max(1, inSampleSize);
 return inSampleSize;
 }
입력 한 너비 와 높 은 값 에 따라 해상도 의 축소 비율 을 계산 한 다음 에 입력 한 압축 품질 수치 에 따라 그림 을 압축 하여 압축 된 bitmap 를 얻 은 다음 에 원가 파일 을 저장 합 니 다.
이것 은 매우 흔히 볼 수 있 는 그림 압축 수단 이다.
4.WebP 대비
저 는 일상생활 에서 찍 은 사진 으로 간단 한 비교 테스트 를 합 니 다.엄밀 하지 않 고 간단 한 참고 만 제공 합 니 다.
사진 촬영 장 비 는 CM 13 을 칠 한 1 더하기 1 이다.사진 촬영 장면 은 모두 일상생활 에서 특히 흔히 볼 수 있 는 것 이다.
다음은 원본 미리 보기 입 니 다.하나씩 놓 지 않 겠 습 니 다.너무 큽 니 다.

해상 도 를 줄 이 고 동시에 품질 을 압축 하 다.
파일 이름
사진
압축 후 jpg
압축 후 webp
압축 비
1.jpg
5760 kb
98 kb
74 kb
24.49%
2.jpg
4534 kb
64 kb
35 kb
45.31%
3.jpg
4751 kb
93 kb
68 kb
26.88%
4.jpg
7002 kb
121 kb
95 kb
21.49%
5.jpg
5493 kb
111 kb
91 kb
18.02%
평균 압축 비 는 27.24%
원 그림 의 크기 에 따라 해상 도 를 줄 이지 않 고 품질 만 압축 합 니 다.
파일 이름
사진
압축 후 jpg
압축 후 webp
압축 비
3.jpg
4751 kb
796 kb
426 kb
46.48%
이로써 우 리 는 웹 p 를 편리 하 게 사용 하여 그림 을 더욱 극 대화 압축 하고 그림 의 부피 와 품질 을 동시에 고려 했다.
어,csdn 은 웹 p 의 사진 을 올 리 는 것 을 지원 하지 않 습 니 다.너 희 는 압축 가방 을 볼 수 있다.
제 가 귀찮아 서 압축 가방 을 안 넘 길 것 같 아 요.........................................................
눈 을 크게 뜨 고 어떤 차이 가 있 는 지 비교 해 보 세 요.해상 도 를 줄 이지 않 고 품질 만 압축 합 니 다.이 3.jpg 는 46.48%의 압축 비 입 니 다.
이 장면 은 밤 에 조명 이 충분 한 실내 에서 밥 을 먹고 찍 은 것 이다.


5.Gzip 으로 압축
방금 로 컬 그림 에 대한 압축 이 었 습 니 다.다음은 서버 에 그림 을 전송 해 야 합 니 다.이 과정 은 여전히 최적화 공간 이 있 는데 바로 Gzip 을 이용 하 는 것 이다.
Gzip 의 역할 대상 은 전체 요청 체 이 며,구체 적 으로 는 요청 체 의 내용 을 역 압축 하여 pc 상의 zip 와 유사 합 니 다.
Gzip 압축 요청 체 는 header:"Content-Encoding:gzip"을 추가 해 야 합 니 다.
이 일 은 Retrofit 가 너 를 도와 잘 할 것 이다.
백 엔 드 서버 가 이 유형의 요청 을 받 으 면 요청 체 에 대한 압축 을 풀 수 있 기 때문에 백 엔 드 지원 이 필요 합 니 다.
또한,Gzip 은 비교적 큰 요청 체 압축 효과 가 좋 으 며,특히 압축 되 지 않 은 일반 텍스트 형식 에 대해 서도 주의해 야 합 니 다.
요청 이 원래 작 으 면 gzip 압축 을 사용 하지 마 세 요.압축 가방 의 메타 데 이 터 는 요청 체 보다 더 크 고 얻 는 것 보다 잃 는 것 이 많 을 수 있 습 니 다.너 는 스스로 테스트 해 볼 수 있다.나 는 zip 와 gzip 의 압축 사전 이 비교적 유사 하 다 고 생각한다.직접 pc 에서 테스트 할 수 있다.
6.Retrofit 요청 Gzip 압축
네트워크 요청 에 있어 서 제 프로젝트 에 서 는 Retrofit(OKHttp)+RxJava 를 사용 합 니 다.
Retrofit 의 Gzip 압축 은 본질 적 으로 OKHttp 의 차단 기 를 통 해 이 루어 진다.
0 차단 요청
1 헤더 추가
2 압축 요청
3 발송
해결 하 다
https://github.com/square/okhttp/wiki/Interceptors

/** This interceptor compresses the HTTP request body. Many webservers can't handle this! */
final class GzipRequestInterceptor implements Interceptor {
 @Override public Response intercept(Interceptor.Chain chain) throws IOException {
 Request originalRequest = chain.request();
 if (originalRequest.body() == null || originalRequest.header("Content-Encoding") != null) {
 return chain.proceed(originalRequest);
 }
 Request compressedRequest = originalRequest.newBuilder()
 .header("Content-Encoding", "gzip")
 .method(originalRequest.method(), gzip(originalRequest.body()))
 .build();
 return chain.proceed(compressedRequest);
 }
 private RequestBody gzip(final RequestBody body) {
 return new RequestBody() {
 @Override public MediaType contentType() {
 return body.contentType();
 }
 @Override public long contentLength() {
 return -1; // We don't know the compressed length in advance!
 }
 @Override public void writeTo(BufferedSink sink) throws IOException {
 BufferedSink gzipSink = Okio.buffer(new GzipSink(sink));
 body.writeTo(gzipSink);
 gzipSink.close();
 }
 };
 }
}
7.패키지 비교 요청
나 는 우리 가 실제 얼마나 큰 데 이 터 를 전 송 했 는 지 알 수 있 도록 Fiddler 4 로 전체 요청 과정 을 모니터링 할 것 이다.
올 린 구체 적 인 코드 는 보 내지 않 습 니 다.이것 은 중요 한 것 이 아 닙 니 다.
나 는 가방 을 잡 은 후에 request 이것 을 저장 했다.

두 장의 사진 을 동시에 올 리 는 크기 입 니 다.
파일 이름
요청 체 크기
WebP+Gzip
169kb
WebP
222kb
Gzip 으로 압축 하 는 것 이 Gzip 을 넣 지 않 는 것 보다 23%작 습 니 다!jpg 는 보 내지 않 겠 습 니 다.앞에서 계산 해 보 세 요~
WebP 는 Jpg 보다 27%작 고 gzip+webp 는 단순 한 webp 보다 23%작 으 며 절 약 된 데이터 가 얼마나 많은 가!
8.마지막
WebP 는 기본적으로 안 드 로 이 드 4.0 이상 만 지원 하 며,현재 프로젝트 의 최저 지원 버 전 은 16 이기 때문에 문제 가 없습니다.만약 당신 의 프로젝트 가 최소 2.0 까지 지원 해 야 한다 면 제3자 의 지원 도 있 는 것 같 지만,나 는 당신 이 제품 을 잡 아 나 가서 한 대 때 리 는 것 을 건의 합 니 다.
우리 프로젝트 에서 iOS 는 이 기술 을 사용 하지 않 았 다.
아래 의 참고 링크 의 데이터 와 제 가 테스트 한 데 이 터 를 보면 WebP 는 사용자 의 데 이 터 를 크게 절약 할 뿐만 아니 라 이미지 전송 속도 도 가속 화 할 수 있 습 니 다.사진 전송의 측면 에서 볼 때 매우 유리 하 다.
"IOS 못 해,안 해.""백 스테이지 XXX 는 안 해 요."
나 는 네가 제품 을 잡 고 나 가서 한 대 때 릴 것 을 건의 한다.
관련 참고:
http://isux.tencent.com/introduction-of-webp.html(제품 매니저 이거 봐 요)
http://blog.csdn.net/GeekLei/article/details/41147479(백 스테이지 에서 이것 을 봐 야 한다)
https://developers.google.com/speed/webp/
http://www.infoq.com/cn/articles/sdk-optimazation?utm_campaign=infoq_content&utm_source=infoq&utm_medium=feed&utm_term.
http://blog.csdn.net/mingchunhu/article/details/8155742(안 드 로 이 드 는 모두 봐 야 합 니 다)

좋은 웹페이지 즐겨찾기