summaryrefslogtreecommitdiff
path: root/src/lib/eet
diff options
context:
space:
mode:
authorCedric BAIL <cedric@osg.samsung.com>2015-03-17 08:50:18 +0100
committerCedric BAIL <cedric@osg.samsung.com>2015-03-17 09:58:18 +0100
commitf9125499f9743a3ed551f1f1f2144b331d7e2056 (patch)
tree64dddb6bf77fb0b725510eb74457d925a2468aa3 /src/lib/eet
parenta865d41181c13c9f1ebeb0eaa0520f57a9fa7a02 (diff)
eet: use Emile to decode TGV image section.
Diffstat (limited to 'src/lib/eet')
-rw-r--r--src/lib/eet/Eet.h19
-rw-r--r--src/lib/eet/eet_image.c318
2 files changed, 56 insertions, 281 deletions
diff --git a/src/lib/eet/Eet.h b/src/lib/eet/Eet.h
index 59560a5f07..2a100ae93c 100644
--- a/src/lib/eet/Eet.h
+++ b/src/lib/eet/Eet.h
@@ -96,8 +96,9 @@
96 96
97#include <stdlib.h> 97#include <stdlib.h>
98#include <stdio.h> 98#include <stdio.h>
99#include <Eina.h>
100#include <Efl_Config.h> 99#include <Efl_Config.h>
100#include <Eina.h>
101#include <Emile.h>
101 102
102#ifdef EAPI 103#ifdef EAPI
103# undef EAPI 104# undef EAPI
@@ -491,15 +492,13 @@ typedef enum _Eet_Image_Encoding
491 EET_IMAGE_ETC1_ALPHA = 5, 492 EET_IMAGE_ETC1_ALPHA = 5,
492} Eet_Image_Encoding; 493} Eet_Image_Encoding;
493 494
494typedef enum _Eet_Colorspace 495typedef Emile_Colorspace Eet_Colorspace;
495{ 496
496 EET_COLORSPACE_ARGB8888 = 0, 497#define EET_COLORSPACE_ARGB8888 EMILE_COLORSPACE_ARGB8888
497 /* The number between are reserved to preserve compatibility with evas */ 498#define EET_COLORSPACE_ETC1 EMILE_COLORSPACE_ETC1
498 EET_COLORSPACE_ETC1 = 9, 499#define EET_COLORSPACE_RGB8_ETC2 EMILE_COLORSPACE_RGB8_ETC2
499 EET_COLORSPACE_RGB8_ETC2 = 10, 500#define EET_COLORSPACE_RGBA8_ETC2_EAC EMILE_COLORSPACE_RGBA8_ETC2_EAC
500 EET_COLORSPACE_RGBA8_ETC2_EAC = 11, 501#define EET_COLORSPACE_ETC1_ALPHA EMILE_COLORSPACE_ETC1_ALPHA
501 EET_COLORSPACE_ETC1_ALPHA = 12
502} Eet_Colorspace;
503 502
504/** 503/**
505 * @typedef Eet_File 504 * @typedef Eet_File
diff --git a/src/lib/eet/eet_image.c b/src/lib/eet/eet_image.c
index ff77fe1b6b..f6aee861d9 100644
--- a/src/lib/eet/eet_image.c
+++ b/src/lib/eet/eet_image.c
@@ -775,36 +775,6 @@ _eet_argb_unpremul(unsigned int *data, unsigned int len)
775 } 775 }
776} 776}
777 777
778static inline unsigned int
779_tgv_length_get(const char *m, unsigned int length, unsigned int *offset)
780{
781 unsigned int r = 0;
782 unsigned int shift = 0;
783
784 while (*offset < length && ((*m) & 0x80))
785 {
786 r = r | (((*m) & 0x7F) << shift);
787 shift += 7;
788 m++;
789 (*offset)++;
790 }
791 if (*offset < length)
792 {
793 r = r | (((*m) & 0x7F) << shift);
794 (*offset)++;
795 }
796
797 return r;
798}
799
800static int
801roundup(int val, int rup)
802{
803 if (val >= 0 && rup > 0)
804 return (val + rup - 1) - ((val + rup - 1) % rup);
805 return 0;
806}
807
808static int 778static int
809eet_data_image_etc2_decode(const void *data, 779eet_data_image_etc2_decode(const void *data,
810 unsigned int length, 780 unsigned int length,
@@ -817,266 +787,71 @@ eet_data_image_etc2_decode(const void *data,
817 Eet_Colorspace cspace, 787 Eet_Colorspace cspace,
818 Eet_Image_Encoding lossy) 788 Eet_Image_Encoding lossy)
819{ 789{
820 const char *m = NULL; 790 Emile_Image_Load_Opts opts;
821 unsigned int bwidth, bheight; 791 Emile_Image_Property prop;
822 unsigned char *p_etc; 792 Emile_Image *image;
823 Eina_Binbuf *buffer = NULL; 793 Eina_Binbuf *bin;
824 Eina_Rectangle master; 794 Emile_Image_Load_Error error;
825 unsigned int block_length; 795 int i;
826 unsigned int offset;
827 unsigned int x, y, w, h;
828 unsigned int block_count;
829 unsigned int etc_width = 0;
830 unsigned int etc_block_size;
831 unsigned int num_planes = 1, plane, alpha_offset = 0;
832 Eet_Colorspace file_cspace;
833 Eina_Bool compress, blockless, unpremul;
834
835 m = data;
836 796
837 // Fix for ABI incompatibility between 1.10 and 1.11 797 // Fix for ABI incompatibility between 1.10 and 1.11
838 if (cspace == 8) cspace = 9; 798 if (cspace == 8) cspace = 9;
839 799
840 if (strncmp(m, "TGV1", 4) != 0) 800 bin = eina_binbuf_manage_read_only_new_length(data, length);
841 return 0; 801 if (!bin) return 0;
842 802
843 compress = m[OFFSET_OPTIONS] & 0x1; 803 opts.region.x = dst_x;
844 blockless = (m[OFFSET_OPTIONS] & 0x2) != 0; 804 opts.region.y = dst_y;
845 unpremul = (m[OFFSET_OPTIONS] & 0x4) != 0; 805 opts.region.w = dst_w;
846 w = ntohl(*((unsigned int*) &(m[OFFSET_WIDTH]))); 806 opts.region.h = dst_h;
847 h = ntohl(*((unsigned int*) &(m[OFFSET_HEIGHT])));
848 807
849 switch (m[OFFSET_ALGORITHM] & 0xFF) 808 image = emile_image_tgv_memory_open(bin, &opts, NULL, &error);
850 { 809 if (!image) return 0;
851 case 0:
852 if (lossy != EET_IMAGE_ETC1) return 0;
853 file_cspace = EET_COLORSPACE_ETC1;
854 if (alpha != EINA_FALSE) return 0;
855 etc_block_size = 8;
856 break;
857 case 1:
858 if (lossy != EET_IMAGE_ETC2_RGB) return 0;
859 file_cspace = EET_COLORSPACE_RGB8_ETC2;
860 if (alpha != EINA_FALSE) return 0;
861 etc_block_size = 8;
862 break;
863 case 2:
864 if (lossy != EET_IMAGE_ETC2_RGBA) return 0;
865 file_cspace = EET_COLORSPACE_RGBA8_ETC2_EAC;
866 if (alpha != EINA_TRUE) return 0;
867 etc_block_size = 16;
868 break;
869 case 3:
870 if (lossy != EET_IMAGE_ETC1_ALPHA) return 0;
871 file_cspace = EET_COLORSPACE_ETC1_ALPHA;
872 if (alpha != EINA_TRUE) return 0;
873 etc_block_size = 8;
874 num_planes = 2;
875 alpha_offset = ((w + 2 + 3) / 4) * ((h + 2 + 3) / 4) * 8 / sizeof(*p_etc);
876 break;
877 default:
878 return 0;
879 }
880 etc_width = ((w + 2 + 3) / 4) * etc_block_size;
881 810
882 if (cspace != EET_COLORSPACE_ARGB8888 && cspace != file_cspace) 811 memset(&prop, sizeof (prop), 0);
883 {
884 if (!((cspace == EET_COLORSPACE_RGB8_ETC2) && (file_cspace == EET_COLORSPACE_ETC1)))
885 return 0;
886 // else: ETC2 is compatible with ETC1 and is preferred
887 }
888 812
889 if (blockless) 813 if (!emile_image_head(image, &prop, sizeof (Emile_Image_Load_Opts), &error))
890 { 814 return 0;
891 bwidth = roundup(w + 2, 4); 815
892 bheight = roundup(h + 2, 4); 816 for (i = 0; prop.cspaces[i] != EMILE_COLORSPACE_ARGB8888; i++)
893 }
894 else
895 { 817 {
896 bwidth = 4 << (m[OFFSET_BLOCK_SIZE] & 0x0f); 818 if (prop.cspaces[i] == cspace) break;
897 bheight = 4 << ((m[OFFSET_BLOCK_SIZE] & 0xf0) >> 4);
898 } 819 }
899 820
900 EINA_RECTANGLE_SET(&master, dst_x, dst_y, dst_w, dst_h);
901
902 switch (cspace) 821 switch (cspace)
903 { 822 {
904 case EET_COLORSPACE_ETC1: 823 case EMILE_COLORSPACE_ETC1:
905 case EET_COLORSPACE_RGB8_ETC2: 824 if (lossy != EET_IMAGE_ETC1) return 0;
906 case EET_COLORSPACE_RGBA8_ETC2_EAC: 825 if (alpha != EINA_FALSE) return 0;
907 case EET_COLORSPACE_ETC1_ALPHA: 826 break;
908 if (master.x % 4 || master.y % 4) 827 case EMILE_COLORSPACE_RGB8_ETC2:
909 abort(); 828 if (lossy != EET_IMAGE_ETC2_RGB) return 0;
910 break; 829 if (alpha != EINA_FALSE) return 0;
830 break;
831 case EMILE_COLORSPACE_RGBA8_ETC2_EAC:
832 if (lossy != EET_IMAGE_ETC2_RGBA) return 0;
833 if (alpha != EINA_TRUE) return 0;
834 break;
835 case EMILE_COLORSPACE_ETC1_ALPHA:
836 if (lossy != EET_IMAGE_ETC1_ALPHA) return 0;
837 if (alpha != EINA_TRUE) return 0;
838 break;
911 case EET_COLORSPACE_ARGB8888: 839 case EET_COLORSPACE_ARGB8888:
912 // Offset to take duplicated pixels into account 840 break;
913 master.x += 1; 841 default:
914 master.y += 1; 842 return 0;
915 break;
916 default: abort();
917 } 843 }
918 844
919 p_etc = (unsigned char*) p; 845 prop.cspace = cspace;
920 offset = OFFSET_BLOCKS; 846
921 847 if (!emile_image_data(image, &prop, sizeof (Emile_Image_Load_Opts), p, &error))
922 // Allocate space for each ETC block (8 or 16 bytes per 4 * 4 pixels group) 848 return 0;
923 block_count = bwidth * bheight / (4 * 4);
924 if (compress)
925 buffer = eina_binbuf_manage_read_only_new_length(alloca(etc_block_size * block_count), etc_block_size * block_count);
926
927 for (plane = 0; plane < num_planes; plane++)
928 for (y = 0; y < h + 2; y += bheight)
929 for (x = 0; x < w + 2; x += bwidth)
930 {
931 Eina_Rectangle current;
932 Eina_Binbuf *data_start;
933 const char *it;
934 unsigned int expand_length;
935 unsigned int i, j;
936
937 block_length = _tgv_length_get(m + offset, length, &offset);
938
939 if (block_length == 0) goto on_error;
940
941 data_start = eina_binbuf_manage_read_only_new_length(m + offset, block_length);
942 offset += block_length;
943
944 EINA_RECTANGLE_SET(&current, x, y,
945 bwidth, bheight);
946
947 if (!eina_rectangle_intersection(&current, &master))
948 continue;
949
950 if (compress)
951 {
952 if (!emile_binbuf_expand(data_start, buffer, EMILE_LZ4HC))
953 goto on_error;
954 }
955 else
956 {
957 buffer = data_start;
958 if (block_count * etc_block_size != block_length)
959 goto on_error;
960 }
961 it = eina_binbuf_string_get(buffer);
962
963 for (i = 0; i < bheight; i += 4)
964 for (j = 0; j < bwidth; j += 4, it += etc_block_size)
965 {
966 Eina_Rectangle current_etc;
967 unsigned int temporary[4 * 4];
968 unsigned int offset_x, offset_y;
969 int k, l;
970
971 EINA_RECTANGLE_SET(&current_etc, x + j, y + i, 4, 4);
972
973 if (!eina_rectangle_intersection(&current_etc, &current))
974 continue;
975
976 switch (cspace)
977 {
978 case EET_COLORSPACE_ARGB8888:
979 switch (file_cspace)
980 {
981 case EET_COLORSPACE_ETC1:
982 case EET_COLORSPACE_ETC1_ALPHA:
983 if (!rg_etc1_unpack_block(it, temporary, 0))
984 {
985 // TODO: Should we decode as RGB8_ETC2?
986 fprintf(stderr, "ETC1: Block starting at {%i, %i} is corrupted!\n", x + j, y + i);
987 continue;
988 }
989 break;
990 case EET_COLORSPACE_RGB8_ETC2:
991 rg_etc2_rgb8_decode_block((uint8_t *) it, temporary);
992 break;
993 case EET_COLORSPACE_RGBA8_ETC2_EAC:
994 rg_etc2_rgba8_decode_block((uint8_t *) it, temporary);
995 break;
996 default: abort();
997 }
998
999 offset_x = current_etc.x - x - j;
1000 offset_y = current_etc.y - y - i;
1001
1002 if (!plane)
1003 {
1004#ifdef BUILD_NEON
1005 if (eina_cpu_features_get() & EINA_CPU_NEON)
1006 {
1007 uint32_t *dst = &p[current_etc.x - 1 + (current_etc.y - 1) * master.w];
1008 uint32_t *src = &temporary[offset_x + offset_y * 4];
1009 for (k = 0; k < current_etc.h; k++)
1010 {
1011 if (current_etc.w == 4)
1012 vst1q_u32(dst, vld1q_u32(src));
1013 else if (current_etc.w == 3)
1014 {
1015 vst1_u32(dst, vld1_u32(src));
1016 *(dst + 2) = *(src + 2);
1017 }
1018 else if (current_etc.w == 2)
1019 vst1_u32(dst, vld1_u32(src));
1020 else
1021 *dst = *src;
1022 dst += master.w;
1023 src += 4;
1024 }
1025 }
1026 else
1027#endif
1028 for (k = 0; k < current_etc.h; k++)
1029 {
1030 memcpy(&p[current_etc.x - 1 + (current_etc.y - 1 + k) * master.w],
1031 &temporary[offset_x + (offset_y + k) * 4],
1032 current_etc.w * sizeof (unsigned int));
1033 }
1034 }
1035 else
1036 {
1037 for (k = 0; k < current_etc.h; k++)
1038 for (l = 0; l < current_etc.w; l++)
1039 {
1040 unsigned int *rgbdata =
1041 &p[current_etc.x - 1 + (current_etc.y - 1 + k) * master.w + l];
1042 unsigned int *adata =
1043 &temporary[offset_x + (offset_y + k) * 4 + l];
1044 A_VAL(rgbdata) = G_VAL(adata);
1045 }
1046 }
1047 break;
1048 case EET_COLORSPACE_ETC1:
1049 case EET_COLORSPACE_RGB8_ETC2:
1050 case EET_COLORSPACE_RGBA8_ETC2_EAC:
1051 memcpy(&p_etc[(current_etc.x / 4) * etc_block_size +
1052 (current_etc.y / 4) * etc_width],
1053 it, etc_block_size);
1054 break;
1055 case EET_COLORSPACE_ETC1_ALPHA:
1056 memcpy(&p_etc[(current_etc.x / 4) * etc_block_size +
1057 (current_etc.y / 4) * etc_width +
1058 plane * alpha_offset],
1059 it, etc_block_size);
1060 break;
1061 default:
1062 abort();
1063 }
1064 } // bx,by inside blocks
1065
1066 eina_binbuf_free(data_start);
1067 } // x,y macroblocks
1068
1069 if (compress) eina_binbuf_free(buffer);
1070 849
1071 // TODO: Add support for more unpremultiplied modes (ETC2) 850 // TODO: Add support for more unpremultiplied modes (ETC2)
1072 if ((cspace == EET_COLORSPACE_ARGB8888) && unpremul) 851 if ((cspace == EET_COLORSPACE_ARGB8888) && !prop.premul)
1073 _eet_argb_premul(p, w * h); 852 _eet_argb_premul(p, prop.w * prop.h);
1074 853
1075 return 1; 854 return 1;
1076
1077on_error:
1078 ERR("ETC image data is corrupted in this EET file");
1079 return 0;
1080} 855}
1081 856
1082static void * 857static void *
@@ -2145,6 +1920,7 @@ eet_data_image_header_decode_cipher(const void *data,
2145 { 1920 {
2146 const char *m = data; 1921 const char *m = data;
2147 1922
1923 // We only use Emile for decoding the actual data, seems simpler this way.
2148 if (w) *w = ntohl(*((unsigned int*) &(m[OFFSET_WIDTH]))); 1924 if (w) *w = ntohl(*((unsigned int*) &(m[OFFSET_WIDTH])));
2149 if (h) *h = ntohl(*((unsigned int*) &(m[OFFSET_HEIGHT]))); 1925 if (h) *h = ntohl(*((unsigned int*) &(m[OFFSET_HEIGHT])));
2150 if (comp) *comp = m[OFFSET_OPTIONS] & 0x1; 1926 if (comp) *comp = m[OFFSET_OPTIONS] & 0x1;
@@ -2306,7 +2082,7 @@ _eet_data_image_decode_inside(const void *data,
2306 unsigned int src_x, 2082 unsigned int src_x,
2307 unsigned int src_y, 2083 unsigned int src_y,
2308 unsigned int src_w, 2084 unsigned int src_w,
2309 EINA_UNUSED unsigned int src_h, /* useful for fast path detection */ 2085 unsigned int src_h, /* useful for fast path detection */
2310 unsigned int *d, 2086 unsigned int *d,
2311 unsigned int w, 2087 unsigned int w,
2312 unsigned int h, 2088 unsigned int h,