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

Side by Side Diff: src/images/SkImageDecoder_libjpeg.cpp

Issue 1893333006: Use libjpeg-turbo for YUV->RGB conversion in jpeg encoder (Closed) Base URL: https://skia.googlesource.com/skia.git@m50
Patch Set: Created 4 years, 8 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2007 The Android Open Source Project 2 * Copyright 2007 The Android Open Source Project
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 8
9 #include "SkImageDecoder.h" 9 #include "SkImageDecoder.h"
10 #include "SkImageEncoder.h" 10 #include "SkImageEncoder.h"
(...skipping 14 matching lines...) Expand all
25 #include <stdio.h> 25 #include <stdio.h>
26 extern "C" { 26 extern "C" {
27 #include "jpeglib.h" 27 #include "jpeglib.h"
28 #include "jerror.h" 28 #include "jerror.h"
29 } 29 }
30 30
31 // These enable timing code that report milliseconds for an encoding/decoding 31 // These enable timing code that report milliseconds for an encoding/decoding
32 //#define TIME_ENCODE 32 //#define TIME_ENCODE
33 //#define TIME_DECODE 33 //#define TIME_DECODE
34 34
35 // this enables our rgb->yuv code, which is faster than libjpeg on ARM
36 #define WE_CONVERT_TO_YUV
37
38 // If ANDROID_RGB is defined by in the jpeg headers it indicates that jpeg offer s 35 // If ANDROID_RGB is defined by in the jpeg headers it indicates that jpeg offer s
39 // support for two additional formats (1) JCS_RGBA_8888 and (2) JCS_RGB_565. 36 // support for two additional formats (1) JCS_RGBA_8888 and (2) JCS_RGB_565.
40 37
41 #define DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_WARNINGS true 38 #define DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_WARNINGS true
42 #define DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_ERRORS true 39 #define DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_ERRORS true
43 SK_CONF_DECLARE(bool, c_suppressJPEGImageDecoderWarnings, 40 SK_CONF_DECLARE(bool, c_suppressJPEGImageDecoderWarnings,
44 "images.jpeg.suppressDecoderWarnings", 41 "images.jpeg.suppressDecoderWarnings",
45 DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_WARNINGS, 42 DEFAULT_FOR_SUPPRESS_JPEG_IMAGE_DECODER_WARNINGS,
46 "Suppress most JPG warnings when calling decode functions."); 43 "Suppress most JPG warnings when calling decode functions.");
47 SK_CONF_DECLARE(bool, c_suppressJPEGImageDecoderErrors, 44 SK_CONF_DECLARE(bool, c_suppressJPEGImageDecoderErrors,
(...skipping 699 matching lines...) Expand 10 before | Expand all | Expand 10 after
747 744
748 if (nullptr != colorSpace) { 745 if (nullptr != colorSpace) {
749 *colorSpace = kJPEG_SkYUVColorSpace; 746 *colorSpace = kJPEG_SkYUVColorSpace;
750 } 747 }
751 748
752 return true; 749 return true;
753 } 750 }
754 751
755 /////////////////////////////////////////////////////////////////////////////// 752 ///////////////////////////////////////////////////////////////////////////////
756 753
757 #include "SkColorPriv.h"
758
759 // taken from jcolor.c in libjpeg
760 #if 0 // 16bit - precise but slow
761 #define CYR 19595 // 0.299
762 #define CYG 38470 // 0.587
763 #define CYB 7471 // 0.114
764
765 #define CUR -11059 // -0.16874
766 #define CUG -21709 // -0.33126
767 #define CUB 32768 // 0.5
768
769 #define CVR 32768 // 0.5
770 #define CVG -27439 // -0.41869
771 #define CVB -5329 // -0.08131
772
773 #define CSHIFT 16
774 #else // 8bit - fast, slightly less precise
775 #define CYR 77 // 0.299
776 #define CYG 150 // 0.587
777 #define CYB 29 // 0.114
778
779 #define CUR -43 // -0.16874
780 #define CUG -85 // -0.33126
781 #define CUB 128 // 0.5
782
783 #define CVR 128 // 0.5
784 #define CVG -107 // -0.41869
785 #define CVB -21 // -0.08131
786
787 #define CSHIFT 8
788 #endif
789
790 static void rgb2yuv_32(uint8_t dst[], SkPMColor c) {
791 int r = SkGetPackedR32(c);
792 int g = SkGetPackedG32(c);
793 int b = SkGetPackedB32(c);
794
795 int y = ( CYR*r + CYG*g + CYB*b ) >> CSHIFT;
796 int u = ( CUR*r + CUG*g + CUB*b ) >> CSHIFT;
797 int v = ( CVR*r + CVG*g + CVB*b ) >> CSHIFT;
798
799 dst[0] = SkToU8(y);
800 dst[1] = SkToU8(u + 128);
801 dst[2] = SkToU8(v + 128);
802 }
803
804 static void rgb2yuv_4444(uint8_t dst[], U16CPU c) {
805 int r = SkGetPackedR4444(c);
806 int g = SkGetPackedG4444(c);
807 int b = SkGetPackedB4444(c);
808
809 int y = ( CYR*r + CYG*g + CYB*b ) >> (CSHIFT - 4);
810 int u = ( CUR*r + CUG*g + CUB*b ) >> (CSHIFT - 4);
811 int v = ( CVR*r + CVG*g + CVB*b ) >> (CSHIFT - 4);
812
813 dst[0] = SkToU8(y);
814 dst[1] = SkToU8(u + 128);
815 dst[2] = SkToU8(v + 128);
816 }
817
818 static void rgb2yuv_16(uint8_t dst[], U16CPU c) {
819 int r = SkGetPackedR16(c);
820 int g = SkGetPackedG16(c);
821 int b = SkGetPackedB16(c);
822
823 int y = ( 2*CYR*r + CYG*g + 2*CYB*b ) >> (CSHIFT - 2);
824 int u = ( 2*CUR*r + CUG*g + 2*CUB*b ) >> (CSHIFT - 2);
825 int v = ( 2*CVR*r + CVG*g + 2*CVB*b ) >> (CSHIFT - 2);
826
827 dst[0] = SkToU8(y);
828 dst[1] = SkToU8(u + 128);
829 dst[2] = SkToU8(v + 128);
830 }
831
832 ///////////////////////////////////////////////////////////////////////////////
833
834 typedef void (*WriteScanline)(uint8_t* SK_RESTRICT dst, 754 typedef void (*WriteScanline)(uint8_t* SK_RESTRICT dst,
835 const void* SK_RESTRICT src, int width, 755 const void* SK_RESTRICT src, int width,
836 const SkPMColor* SK_RESTRICT ctable); 756 const SkPMColor* SK_RESTRICT ctable);
837 757
838 static void Write_32_YUV(uint8_t* SK_RESTRICT dst, 758 static void Write_32_RGB(uint8_t* SK_RESTRICT dst,
839 const void* SK_RESTRICT srcRow, int width, 759 const void* SK_RESTRICT srcRow, int width,
840 const SkPMColor*) { 760 const SkPMColor*) {
841 const uint32_t* SK_RESTRICT src = (const uint32_t*)srcRow; 761 const uint32_t* SK_RESTRICT src = (const uint32_t*)srcRow;
842 while (--width >= 0) { 762 while (--width >= 0) {
843 #ifdef WE_CONVERT_TO_YUV
844 rgb2yuv_32(dst, *src++);
845 #else
846 uint32_t c = *src++; 763 uint32_t c = *src++;
847 dst[0] = SkGetPackedR32(c); 764 dst[0] = SkGetPackedR32(c);
848 dst[1] = SkGetPackedG32(c); 765 dst[1] = SkGetPackedG32(c);
849 dst[2] = SkGetPackedB32(c); 766 dst[2] = SkGetPackedB32(c);
850 #endif
851 dst += 3; 767 dst += 3;
852 } 768 }
853 } 769 }
854 770
855 static void Write_4444_YUV(uint8_t* SK_RESTRICT dst, 771 static void Write_4444_RGB(uint8_t* SK_RESTRICT dst,
856 const void* SK_RESTRICT srcRow, int width, 772 const void* SK_RESTRICT srcRow, int width,
857 const SkPMColor*) { 773 const SkPMColor*) {
858 const SkPMColor16* SK_RESTRICT src = (const SkPMColor16*)srcRow; 774 const SkPMColor16* SK_RESTRICT src = (const SkPMColor16*)srcRow;
859 while (--width >= 0) { 775 while (--width >= 0) {
860 #ifdef WE_CONVERT_TO_YUV
861 rgb2yuv_4444(dst, *src++);
862 #else
863 SkPMColor16 c = *src++; 776 SkPMColor16 c = *src++;
864 dst[0] = SkPacked4444ToR32(c); 777 dst[0] = SkPacked4444ToR32(c);
865 dst[1] = SkPacked4444ToG32(c); 778 dst[1] = SkPacked4444ToG32(c);
866 dst[2] = SkPacked4444ToB32(c); 779 dst[2] = SkPacked4444ToB32(c);
867 #endif
868 dst += 3; 780 dst += 3;
869 } 781 }
870 } 782 }
871 783
872 static void Write_16_YUV(uint8_t* SK_RESTRICT dst, 784 static void Write_16_RGB(uint8_t* SK_RESTRICT dst,
873 const void* SK_RESTRICT srcRow, int width, 785 const void* SK_RESTRICT srcRow, int width,
874 const SkPMColor*) { 786 const SkPMColor*) {
875 const uint16_t* SK_RESTRICT src = (const uint16_t*)srcRow; 787 const uint16_t* SK_RESTRICT src = (const uint16_t*)srcRow;
876 while (--width >= 0) { 788 while (--width >= 0) {
877 #ifdef WE_CONVERT_TO_YUV
878 rgb2yuv_16(dst, *src++);
879 #else
880 uint16_t c = *src++; 789 uint16_t c = *src++;
881 dst[0] = SkPacked16ToR32(c); 790 dst[0] = SkPacked16ToR32(c);
882 dst[1] = SkPacked16ToG32(c); 791 dst[1] = SkPacked16ToG32(c);
883 dst[2] = SkPacked16ToB32(c); 792 dst[2] = SkPacked16ToB32(c);
884 #endif
885 dst += 3; 793 dst += 3;
886 } 794 }
887 } 795 }
888 796
889 static void Write_Index_YUV(uint8_t* SK_RESTRICT dst, 797 static void Write_Index_RGB(uint8_t* SK_RESTRICT dst,
890 const void* SK_RESTRICT srcRow, int width, 798 const void* SK_RESTRICT srcRow, int width,
891 const SkPMColor* SK_RESTRICT ctable) { 799 const SkPMColor* SK_RESTRICT ctable) {
892 const uint8_t* SK_RESTRICT src = (const uint8_t*)srcRow; 800 const uint8_t* SK_RESTRICT src = (const uint8_t*)srcRow;
893 while (--width >= 0) { 801 while (--width >= 0) {
894 #ifdef WE_CONVERT_TO_YUV
895 rgb2yuv_32(dst, ctable[*src++]);
896 #else
897 uint32_t c = ctable[*src++]; 802 uint32_t c = ctable[*src++];
898 dst[0] = SkGetPackedR32(c); 803 dst[0] = SkGetPackedR32(c);
899 dst[1] = SkGetPackedG32(c); 804 dst[1] = SkGetPackedG32(c);
900 dst[2] = SkGetPackedB32(c); 805 dst[2] = SkGetPackedB32(c);
901 #endif
902 dst += 3; 806 dst += 3;
903 } 807 }
904 } 808 }
905 809
906 static WriteScanline ChooseWriter(const SkBitmap& bm) { 810 static WriteScanline ChooseWriter(const SkBitmap& bm) {
907 switch (bm.colorType()) { 811 switch (bm.colorType()) {
908 case kN32_SkColorType: 812 case kN32_SkColorType:
909 return Write_32_YUV; 813 return Write_32_RGB;
910 case kRGB_565_SkColorType: 814 case kRGB_565_SkColorType:
911 return Write_16_YUV; 815 return Write_16_RGB;
912 case kARGB_4444_SkColorType: 816 case kARGB_4444_SkColorType:
913 return Write_4444_YUV; 817 return Write_4444_RGB;
914 case kIndex_8_SkColorType: 818 case kIndex_8_SkColorType:
915 return Write_Index_YUV; 819 return Write_Index_RGB;
916 default: 820 default:
917 return nullptr; 821 return nullptr;
918 } 822 }
919 } 823 }
920 824
921 class SkJPEGImageEncoder : public SkImageEncoder { 825 class SkJPEGImageEncoder : public SkImageEncoder {
922 protected: 826 protected:
923 virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) { 827 virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) {
924 #ifdef TIME_ENCODE 828 #ifdef TIME_ENCODE
925 SkAutoTime atm("JPEG Encode"); 829 SkAutoTime atm("JPEG Encode");
(...skipping 21 matching lines...) Expand all
947 const WriteScanline writer = ChooseWriter(bm); 851 const WriteScanline writer = ChooseWriter(bm);
948 if (nullptr == writer) { 852 if (nullptr == writer) {
949 return false; 853 return false;
950 } 854 }
951 855
952 jpeg_create_compress(&cinfo); 856 jpeg_create_compress(&cinfo);
953 cinfo.dest = &sk_wstream; 857 cinfo.dest = &sk_wstream;
954 cinfo.image_width = bm.width(); 858 cinfo.image_width = bm.width();
955 cinfo.image_height = bm.height(); 859 cinfo.image_height = bm.height();
956 cinfo.input_components = 3; 860 cinfo.input_components = 3;
957 #ifdef WE_CONVERT_TO_YUV 861 // FIXME: Can we take advantage of other in_color_spaces in libjpeg-turb o?
958 cinfo.in_color_space = JCS_YCbCr;
959 #else
960 cinfo.in_color_space = JCS_RGB; 862 cinfo.in_color_space = JCS_RGB;
961 #endif 863
864 // The gamma value is ignored by libjpeg-turbo.
962 cinfo.input_gamma = 1; 865 cinfo.input_gamma = 1;
963 866
964 jpeg_set_defaults(&cinfo); 867 jpeg_set_defaults(&cinfo);
868
869 // Tells libjpeg-turbo to compute optimal Huffman coding tables
870 // for the image. This improves compression at the cost of
871 // slower encode performance.
965 cinfo.optimize_coding = TRUE; 872 cinfo.optimize_coding = TRUE;
966 jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */); 873 jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
967 #ifdef DCT_IFAST_SUPPORTED
968 cinfo.dct_method = JDCT_IFAST;
969 #endif
970 874
971 jpeg_start_compress(&cinfo, TRUE); 875 jpeg_start_compress(&cinfo, TRUE);
972 876
973 const int width = bm.width(); 877 const int width = bm.width();
974 uint8_t* oneRowP = oneRow.reset(width * 3); 878 uint8_t* oneRowP = oneRow.reset(width * 3);
975 879
976 const SkPMColor* colors = bm.getColorTable() ? bm.getColorTable()->readC olors() : nullptr; 880 const SkPMColor* colors = bm.getColorTable() ? bm.getColorTable()->readC olors() : nullptr;
977 const void* srcRow = bm.getPixels(); 881 const void* srcRow = bm.getPixels();
978 882
979 while (cinfo.next_scanline < cinfo.image_height) { 883 while (cinfo.next_scanline < cinfo.image_height) {
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
1028 return SkImageDecoder::kUnknown_Format; 932 return SkImageDecoder::kUnknown_Format;
1029 } 933 }
1030 934
1031 static SkImageEncoder* sk_libjpeg_efactory(SkImageEncoder::Type t) { 935 static SkImageEncoder* sk_libjpeg_efactory(SkImageEncoder::Type t) {
1032 return (SkImageEncoder::kJPEG_Type == t) ? new SkJPEGImageEncoder : nullptr; 936 return (SkImageEncoder::kJPEG_Type == t) ? new SkJPEGImageEncoder : nullptr;
1033 } 937 }
1034 938
1035 static SkImageDecoder_DecodeReg gDReg(sk_libjpeg_dfactory); 939 static SkImageDecoder_DecodeReg gDReg(sk_libjpeg_dfactory);
1036 static SkImageDecoder_FormatReg gFormatReg(get_format_jpeg); 940 static SkImageDecoder_FormatReg gFormatReg(get_format_jpeg);
1037 static SkImageEncoder_EncodeReg gEReg(sk_libjpeg_efactory); 941 static SkImageEncoder_EncodeReg gEReg(sk_libjpeg_efactory);
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698