Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(236)

Side by Side Diff: third_party/libwebp/enc/picture.c

Issue 12942006: libwebp: update snapshot to v0.3.0-rc6 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « third_party/libwebp/enc/histogram.c ('k') | third_party/libwebp/enc/quant.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 Google Inc. All Rights Reserved. 1 // Copyright 2011 Google Inc. All Rights Reserved.
2 // 2 //
3 // This code is licensed under the same terms as WebM: 3 // This code is licensed under the same terms as WebM:
4 // Software License Agreement: http://www.webmproject.org/license/software/ 4 // Software License Agreement: http://www.webmproject.org/license/software/
5 // Additional IP Rights Grant: http://www.webmproject.org/license/additional/ 5 // Additional IP Rights Grant: http://www.webmproject.org/license/additional/
6 // ----------------------------------------------------------------------------- 6 // -----------------------------------------------------------------------------
7 // 7 //
8 // WebPPicture utils: colorspace conversion, crop, ... 8 // WebPPicture utils: colorspace conversion, crop, ...
9 // 9 //
10 // Author: Skal (pascal.massimino@gmail.com) 10 // Author: Skal (pascal.massimino@gmail.com)
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after
283 283
284 if (src != dst) { // beware of aliasing! We don't want to leak 'memory_'. 284 if (src != dst) { // beware of aliasing! We don't want to leak 'memory_'.
285 WebPPictureGrabSpecs(src, dst); 285 WebPPictureGrabSpecs(src, dst);
286 } 286 }
287 dst->width = width; 287 dst->width = width;
288 dst->height = height; 288 dst->height = height;
289 if (!src->use_argb) { 289 if (!src->use_argb) {
290 dst->y = src->y + top * src->y_stride + left; 290 dst->y = src->y + top * src->y_stride + left;
291 dst->u = src->u + (top >> 1) * src->uv_stride + (left >> 1); 291 dst->u = src->u + (top >> 1) * src->uv_stride + (left >> 1);
292 dst->v = src->v + (top >> 1) * src->uv_stride + (left >> 1); 292 dst->v = src->v + (top >> 1) * src->uv_stride + (left >> 1);
293 dst->y_stride = src->y_stride;
294 dst->uv_stride = src->uv_stride;
293 if (src->a != NULL) { 295 if (src->a != NULL) {
294 dst->a = src->a + top * src->a_stride + left; 296 dst->a = src->a + top * src->a_stride + left;
297 dst->a_stride = src->a_stride;
295 } 298 }
296 #ifdef WEBP_EXPERIMENTAL_FEATURES 299 #ifdef WEBP_EXPERIMENTAL_FEATURES
297 if (src->u0 != NULL) { 300 if (src->u0 != NULL) {
298 const int left_pos = 301 const int left_pos =
299 IS_YUV_CSP(dst->colorspace, WEBP_YUV422) ? (left >> 1) : left; 302 IS_YUV_CSP(dst->colorspace, WEBP_YUV422) ? (left >> 1) : left;
300 dst->u0 = src->u0 + top * src->uv0_stride + left_pos; 303 dst->u0 = src->u0 + top * src->uv0_stride + left_pos;
301 dst->v0 = src->v0 + top * src->uv0_stride + left_pos; 304 dst->v0 = src->v0 + top * src->uv0_stride + left_pos;
305 dst->uv0_stride = src->uv0_stride;
302 } 306 }
303 #endif 307 #endif
304 } else { 308 } else {
305 dst->argb = src->argb + top * src->argb_stride + left; 309 dst->argb = src->argb + top * src->argb_stride + left;
310 dst->argb_stride = src->argb_stride;
306 } 311 }
307 return 1; 312 return 1;
308 } 313 }
309 314
310 //------------------------------------------------------------------------------ 315 //------------------------------------------------------------------------------
311 // Picture cropping 316 // Picture cropping
312 317
313 int WebPPictureCrop(WebPPicture* pic, 318 int WebPPictureCrop(WebPPicture* pic,
314 int left, int top, int width, int height) { 319 int left, int top, int width, int height) {
315 WebPPicture tmp; 320 WebPPicture tmp;
(...skipping 478 matching lines...) Expand 10 before | Expand all | Expand 10 after
794 cur_y += 2 * picture->y_stride; 799 cur_y += 2 * picture->y_stride;
795 dst += 2 * argb_stride; 800 dst += 2 * argb_stride;
796 } 801 }
797 // Last row (if needed), with replicated bottom samples. 802 // Last row (if needed), with replicated bottom samples.
798 if (height > 1 && !(height & 1)) { 803 if (height > 1 && !(height & 1)) {
799 upsample(cur_y, NULL, cur_u, cur_v, cur_u, cur_v, dst, NULL, width); 804 upsample(cur_y, NULL, cur_u, cur_v, cur_u, cur_v, dst, NULL, width);
800 } 805 }
801 // Insert alpha values if needed, in replacement for the default 0xff ones. 806 // Insert alpha values if needed, in replacement for the default 0xff ones.
802 if (picture->colorspace & WEBP_CSP_ALPHA_BIT) { 807 if (picture->colorspace & WEBP_CSP_ALPHA_BIT) {
803 for (y = 0; y < height; ++y) { 808 for (y = 0; y < height; ++y) {
804 uint32_t* const dst = picture->argb + y * picture->argb_stride; 809 uint32_t* const argb_dst = picture->argb + y * picture->argb_stride;
805 const uint8_t* const src = picture->a + y * picture->a_stride; 810 const uint8_t* const src = picture->a + y * picture->a_stride;
806 int x; 811 int x;
807 for (x = 0; x < width; ++x) { 812 for (x = 0; x < width; ++x) {
808 dst[x] = (dst[x] & 0x00ffffffu) | (src[x] << 24); 813 argb_dst[x] = (argb_dst[x] & 0x00ffffffu) | (src[x] << 24);
809 } 814 }
810 } 815 }
811 } 816 }
812 } 817 }
813 return 1; 818 return 1;
814 } 819 }
815 820
816 int WebPPictureARGBToYUVA(WebPPicture* picture, WebPEncCSP colorspace) { 821 int WebPPictureARGBToYUVA(WebPPicture* picture, WebPEncCSP colorspace) {
817 if (picture == NULL) return 0; 822 if (picture == NULL) return 0;
818 if (picture->argb == NULL) { 823 if (picture->argb == NULL) {
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
899 need_reset = 1; 904 need_reset = 1;
900 } 905 }
901 } 906 }
902 // ignore the left-overs on right/bottom 907 // ignore the left-overs on right/bottom
903 } 908 }
904 } 909 }
905 910
906 #undef SIZE 911 #undef SIZE
907 #undef SIZE2 912 #undef SIZE2
908 913
914 //------------------------------------------------------------------------------
915 // local-min distortion
916 //
917 // For every pixel in the *reference* picture, we search for the local best
918 // match in the compressed image. This is not a symmetrical measure.
919
920 // search radius. Shouldn't be too large.
921 #define RADIUS 2
922
923 static float AccumulateLSIM(const uint8_t* src, int src_stride,
924 const uint8_t* ref, int ref_stride,
925 int w, int h) {
926 int x, y;
927 double total_sse = 0.;
928 for (y = 0; y < h; ++y) {
929 const int y_0 = (y - RADIUS < 0) ? 0 : y - RADIUS;
930 const int y_1 = (y + RADIUS + 1 >= h) ? h : y + RADIUS + 1;
931 for (x = 0; x < w; ++x) {
932 const int x_0 = (x - RADIUS < 0) ? 0 : x - RADIUS;
933 const int x_1 = (x + RADIUS + 1 >= w) ? w : x + RADIUS + 1;
934 double best_sse = 255. * 255.;
935 const double value = (double)ref[y * ref_stride + x];
936 int i, j;
937 for (j = y_0; j < y_1; ++j) {
938 const uint8_t* s = src + j * src_stride;
939 for (i = x_0; i < x_1; ++i) {
940 const double sse = (double)(s[i] - value) * (s[i] - value);
941 if (sse < best_sse) best_sse = sse;
942 }
943 }
944 total_sse += best_sse;
945 }
946 }
947 return (float)total_sse;
948 }
949 #undef RADIUS
909 950
910 //------------------------------------------------------------------------------ 951 //------------------------------------------------------------------------------
911 // Distortion 952 // Distortion
912 953
913 // Max value returned in case of exact similarity. 954 // Max value returned in case of exact similarity.
914 static const double kMinDistortion_dB = 99.; 955 static const double kMinDistortion_dB = 99.;
956 static float GetPSNR(const double v) {
957 return (float)((v > 0.) ? -4.3429448 * log(v / (255 * 255.))
958 : kMinDistortion_dB);
959 }
915 960
916 int WebPPictureDistortion(const WebPPicture* pic1, const WebPPicture* pic2, 961 int WebPPictureDistortion(const WebPPicture* src, const WebPPicture* ref,
917 int type, float result[5]) { 962 int type, float result[5]) {
918 int c;
919 DistoStats stats[5]; 963 DistoStats stats[5];
920 int has_alpha; 964 int has_alpha;
965 int uv_w, uv_h;
921 966
922 if (pic1 == NULL || pic2 == NULL || 967 if (src == NULL || ref == NULL ||
923 pic1->width != pic2->width || pic1->height != pic2->height || 968 src->width != ref->width || src->height != ref->height ||
924 pic1->y == NULL || pic2->y == NULL || 969 src->y == NULL || ref->y == NULL ||
925 pic1->u == NULL || pic2->u == NULL || 970 src->u == NULL || ref->u == NULL ||
926 pic1->v == NULL || pic2->v == NULL || 971 src->v == NULL || ref->v == NULL ||
927 result == NULL) { 972 result == NULL) {
928 return 0; 973 return 0;
929 } 974 }
930 // TODO(skal): provide distortion for ARGB too. 975 // TODO(skal): provide distortion for ARGB too.
931 if (pic1->use_argb == 1 || pic1->use_argb != pic2->use_argb) { 976 if (src->use_argb == 1 || src->use_argb != ref->use_argb) {
932 return 0; 977 return 0;
933 } 978 }
934 979
935 has_alpha = !!(pic1->colorspace & WEBP_CSP_ALPHA_BIT); 980 has_alpha = !!(src->colorspace & WEBP_CSP_ALPHA_BIT);
936 if (has_alpha != !!(pic2->colorspace & WEBP_CSP_ALPHA_BIT) || 981 if (has_alpha != !!(ref->colorspace & WEBP_CSP_ALPHA_BIT) ||
937 (has_alpha && (pic1->a == NULL || pic2->a == NULL))) { 982 (has_alpha && (src->a == NULL || ref->a == NULL))) {
938 return 0; 983 return 0;
939 } 984 }
940 985
941 memset(stats, 0, sizeof(stats)); 986 memset(stats, 0, sizeof(stats));
942 VP8SSIMAccumulatePlane(pic1->y, pic1->y_stride, 987
943 pic2->y, pic2->y_stride, 988 uv_w = HALVE(src->width);
944 pic1->width, pic1->height, &stats[0]); 989 uv_h = HALVE(src->height);
945 VP8SSIMAccumulatePlane(pic1->u, pic1->uv_stride, 990 if (type >= 2) {
946 pic2->u, pic2->uv_stride, 991 float sse[4];
947 (pic1->width + 1) >> 1, (pic1->height + 1) >> 1, 992 sse[0] = AccumulateLSIM(src->y, src->y_stride,
948 &stats[1]); 993 ref->y, ref->y_stride, src->width, src->height);
949 VP8SSIMAccumulatePlane(pic1->v, pic1->uv_stride, 994 sse[1] = AccumulateLSIM(src->u, src->uv_stride,
950 pic2->v, pic2->uv_stride, 995 ref->u, ref->uv_stride, uv_w, uv_h);
951 (pic1->width + 1) >> 1, (pic1->height + 1) >> 1, 996 sse[2] = AccumulateLSIM(src->v, src->uv_stride,
952 &stats[2]); 997 ref->v, ref->uv_stride, uv_w, uv_h);
953 if (has_alpha) { 998 sse[3] = has_alpha ? AccumulateLSIM(src->a, src->a_stride,
954 VP8SSIMAccumulatePlane(pic1->a, pic1->a_stride, 999 ref->a, ref->a_stride,
955 pic2->a, pic2->a_stride, 1000 src->width, src->height)
956 pic1->width, pic1->height, &stats[3]); 1001 : 0.f;
957 } 1002 result[0] = GetPSNR(sse[0] / (src->width * src->height));
958 for (c = 0; c <= 4; ++c) { 1003 result[1] = GetPSNR(sse[1] / (uv_w * uv_h));
959 if (type == 1) { 1004 result[2] = GetPSNR(sse[2] / (uv_w * uv_h));
960 const double v = VP8SSIMGet(&stats[c]); 1005 result[3] = GetPSNR(sse[3] / (src->width * src->height));
961 result[c] = (float)((v < 1.) ? -10.0 * log10(1. - v) 1006 {
962 : kMinDistortion_dB); 1007 double total_sse = sse[0] + sse[1] + sse[2];
963 } else { 1008 int total_pixels = src->width * src->height + 2 * uv_w * uv_h;
964 const double v = VP8SSIMGetSquaredError(&stats[c]); 1009 if (has_alpha) {
965 result[c] = (float)((v > 0.) ? -4.3429448 * log(v / (255 * 255.)) 1010 total_pixels += src->width * src->height;
966 : kMinDistortion_dB); 1011 total_sse += sse[3];
1012 }
1013 result[4] = GetPSNR(total_sse / total_pixels);
967 } 1014 }
968 // Accumulate forward 1015 } else {
969 if (c < 4) VP8SSIMAddStats(&stats[c], &stats[4]); 1016 int c;
1017 VP8SSIMAccumulatePlane(src->y, src->y_stride,
1018 ref->y, ref->y_stride,
1019 src->width, src->height, &stats[0]);
1020 VP8SSIMAccumulatePlane(src->u, src->uv_stride,
1021 ref->u, ref->uv_stride,
1022 uv_w, uv_h, &stats[1]);
1023 VP8SSIMAccumulatePlane(src->v, src->uv_stride,
1024 ref->v, ref->uv_stride,
1025 uv_w, uv_h, &stats[2]);
1026 if (has_alpha) {
1027 VP8SSIMAccumulatePlane(src->a, src->a_stride,
1028 ref->a, ref->a_stride,
1029 src->width, src->height, &stats[3]);
1030 }
1031 for (c = 0; c <= 4; ++c) {
1032 if (type == 1) {
1033 const double v = VP8SSIMGet(&stats[c]);
1034 result[c] = (float)((v < 1.) ? -10.0 * log10(1. - v)
1035 : kMinDistortion_dB);
1036 } else {
1037 const double v = VP8SSIMGetSquaredError(&stats[c]);
1038 result[c] = GetPSNR(v);
1039 }
1040 // Accumulate forward
1041 if (c < 4) VP8SSIMAddStats(&stats[c], &stats[4]);
1042 }
970 } 1043 }
971 return 1; 1044 return 1;
972 } 1045 }
973 1046
974 //------------------------------------------------------------------------------ 1047 //------------------------------------------------------------------------------
975 // Simplest high-level calls: 1048 // Simplest high-level calls:
976 1049
977 typedef int (*Importer)(WebPPicture* const, const uint8_t* const, int); 1050 typedef int (*Importer)(WebPPicture* const, const uint8_t* const, int);
978 1051
979 static size_t Encode(const uint8_t* rgba, int width, int height, int stride, 1052 static size_t Encode(const uint8_t* rgba, int width, int height, int stride,
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
1032 LOSSLESS_ENCODE_FUNC(WebPEncodeLosslessRGBA, WebPPictureImportRGBA); 1105 LOSSLESS_ENCODE_FUNC(WebPEncodeLosslessRGBA, WebPPictureImportRGBA);
1033 LOSSLESS_ENCODE_FUNC(WebPEncodeLosslessBGRA, WebPPictureImportBGRA); 1106 LOSSLESS_ENCODE_FUNC(WebPEncodeLosslessBGRA, WebPPictureImportBGRA);
1034 1107
1035 #undef LOSSLESS_ENCODE_FUNC 1108 #undef LOSSLESS_ENCODE_FUNC
1036 1109
1037 //------------------------------------------------------------------------------ 1110 //------------------------------------------------------------------------------
1038 1111
1039 #if defined(__cplusplus) || defined(c_plusplus) 1112 #if defined(__cplusplus) || defined(c_plusplus)
1040 } // extern "C" 1113 } // extern "C"
1041 #endif 1114 #endif
OLDNEW
« no previous file with comments | « third_party/libwebp/enc/histogram.c ('k') | third_party/libwebp/enc/quant.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698