OLD | NEW |
1 // Copyright 2012 Google Inc. All Rights Reserved. | 1 // Copyright 2012 Google Inc. All Rights Reserved. |
2 // | 2 // |
3 // This code is licensed under the same terms as WebM: | 3 // Use of this source code is governed by a BSD-style license |
4 // Software License Agreement: http://www.webmproject.org/license/software/ | 4 // that can be found in the COPYING file in the root of the source |
5 // Additional IP Rights Grant: http://www.webmproject.org/license/additional/ | 5 // tree. An additional intellectual property rights grant can be found |
| 6 // in the file PATENTS. All contributing project authors may |
| 7 // be found in the AUTHORS file in the root of the source tree. |
6 // ----------------------------------------------------------------------------- | 8 // ----------------------------------------------------------------------------- |
7 // | 9 // |
8 // Image transforms and color space conversion methods for lossless decoder. | 10 // Image transforms and color space conversion methods for lossless decoder. |
9 // | 11 // |
10 // Authors: Vikas Arora (vikaas.arora@gmail.com) | 12 // Authors: Vikas Arora (vikaas.arora@gmail.com) |
11 // Jyrki Alakuijala (jyrki@google.com) | 13 // Jyrki Alakuijala (jyrki@google.com) |
12 // Urvang Joshi (urvang@google.com) | 14 // Urvang Joshi (urvang@google.com) |
13 | 15 |
14 #include "./dsp.h" | 16 #include "./dsp.h" |
15 | 17 |
(...skipping 1070 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1086 if ((x & mask) == 0) ColorCodeToMultipliers(*pred++, &m); | 1088 if ((x & mask) == 0) ColorCodeToMultipliers(*pred++, &m); |
1087 data[x] = TransformColor(&m, data[x], 1); | 1089 data[x] = TransformColor(&m, data[x], 1); |
1088 } | 1090 } |
1089 data += width; | 1091 data += width; |
1090 ++y; | 1092 ++y; |
1091 if ((y & mask) == 0) pred_row += tiles_per_row;; | 1093 if ((y & mask) == 0) pred_row += tiles_per_row;; |
1092 } | 1094 } |
1093 } | 1095 } |
1094 | 1096 |
1095 // Separate out pixels packed together using pixel-bundling. | 1097 // Separate out pixels packed together using pixel-bundling. |
1096 static void ColorIndexInverseTransform( | 1098 // We define two methods for ARGB data (uint32_t) and alpha-only data (uint8_t). |
1097 const VP8LTransform* const transform, | 1099 #define COLOR_INDEX_INVERSE(FUNC_NAME, TYPE, GET_INDEX, GET_VALUE) \ |
1098 int y_start, int y_end, const uint32_t* src, uint32_t* dst) { | 1100 void FUNC_NAME(const VP8LTransform* const transform, \ |
1099 int y; | 1101 int y_start, int y_end, const TYPE* src, TYPE* dst) { \ |
1100 const int bits_per_pixel = 8 >> transform->bits_; | 1102 int y; \ |
1101 const int width = transform->xsize_; | 1103 const int bits_per_pixel = 8 >> transform->bits_; \ |
1102 const uint32_t* const color_map = transform->data_; | 1104 const int width = transform->xsize_; \ |
1103 if (bits_per_pixel < 8) { | 1105 const uint32_t* const color_map = transform->data_; \ |
1104 const int pixels_per_byte = 1 << transform->bits_; | 1106 if (bits_per_pixel < 8) { \ |
1105 const int count_mask = pixels_per_byte - 1; | 1107 const int pixels_per_byte = 1 << transform->bits_; \ |
1106 const uint32_t bit_mask = (1 << bits_per_pixel) - 1; | 1108 const int count_mask = pixels_per_byte - 1; \ |
1107 for (y = y_start; y < y_end; ++y) { | 1109 const uint32_t bit_mask = (1 << bits_per_pixel) - 1; \ |
1108 uint32_t packed_pixels = 0; | 1110 for (y = y_start; y < y_end; ++y) { \ |
1109 int x; | 1111 uint32_t packed_pixels = 0; \ |
1110 for (x = 0; x < width; ++x) { | 1112 int x; \ |
1111 // We need to load fresh 'packed_pixels' once every 'pixels_per_byte' | 1113 for (x = 0; x < width; ++x) { \ |
1112 // increments of x. Fortunately, pixels_per_byte is a power of 2, so | 1114 /* We need to load fresh 'packed_pixels' once every */ \ |
1113 // can just use a mask for that, instead of decrementing a counter. | 1115 /* 'pixels_per_byte' increments of x. Fortunately, pixels_per_byte */ \ |
1114 if ((x & count_mask) == 0) packed_pixels = ((*src++) >> 8) & 0xff; | 1116 /* is a power of 2, so can just use a mask for that, instead of */ \ |
1115 *dst++ = color_map[packed_pixels & bit_mask]; | 1117 /* decrementing a counter. */ \ |
1116 packed_pixels >>= bits_per_pixel; | 1118 if ((x & count_mask) == 0) packed_pixels = GET_INDEX(*src++); \ |
1117 } | 1119 *dst++ = GET_VALUE(color_map[packed_pixels & bit_mask]); \ |
1118 } | 1120 packed_pixels >>= bits_per_pixel; \ |
1119 } else { | 1121 } \ |
1120 for (y = y_start; y < y_end; ++y) { | 1122 } \ |
1121 int x; | 1123 } else { \ |
1122 for (x = 0; x < width; ++x) { | 1124 for (y = y_start; y < y_end; ++y) { \ |
1123 *dst++ = color_map[((*src++) >> 8) & 0xff]; | 1125 int x; \ |
1124 } | 1126 for (x = 0; x < width; ++x) { \ |
1125 } | 1127 *dst++ = GET_VALUE(color_map[GET_INDEX(*src++)]); \ |
1126 } | 1128 } \ |
| 1129 } \ |
| 1130 } \ |
1127 } | 1131 } |
1128 | 1132 |
| 1133 static WEBP_INLINE uint32_t GetARGBIndex(uint32_t idx) { |
| 1134 return (idx >> 8) & 0xff; |
| 1135 } |
| 1136 |
| 1137 static WEBP_INLINE uint8_t GetAlphaIndex(uint8_t idx) { |
| 1138 return idx; |
| 1139 } |
| 1140 |
| 1141 static WEBP_INLINE uint32_t GetARGBValue(uint32_t val) { |
| 1142 return val; |
| 1143 } |
| 1144 |
| 1145 static WEBP_INLINE uint8_t GetAlphaValue(uint32_t val) { |
| 1146 return (val >> 8) & 0xff; |
| 1147 } |
| 1148 |
| 1149 static COLOR_INDEX_INVERSE(ColorIndexInverseTransform, uint32_t, GetARGBIndex, |
| 1150 GetARGBValue) |
| 1151 COLOR_INDEX_INVERSE(VP8LColorIndexInverseTransformAlpha, uint8_t, GetAlphaIndex, |
| 1152 GetAlphaValue) |
| 1153 |
| 1154 #undef COLOR_INDEX_INVERSE |
| 1155 |
1129 void VP8LInverseTransform(const VP8LTransform* const transform, | 1156 void VP8LInverseTransform(const VP8LTransform* const transform, |
1130 int row_start, int row_end, | 1157 int row_start, int row_end, |
1131 const uint32_t* const in, uint32_t* const out) { | 1158 const uint32_t* const in, uint32_t* const out) { |
1132 assert(row_start < row_end); | 1159 assert(row_start < row_end); |
1133 assert(row_end <= transform->ysize_); | 1160 assert(row_end <= transform->ysize_); |
1134 switch (transform->type_) { | 1161 switch (transform->type_) { |
1135 case SUBTRACT_GREEN: | 1162 case SUBTRACT_GREEN: |
1136 AddGreenToBlueAndRed(transform, row_start, row_end, out); | 1163 AddGreenToBlueAndRed(transform, row_start, row_end, out); |
1137 break; | 1164 break; |
1138 case PREDICTOR_TRANSFORM: | 1165 case PREDICTOR_TRANSFORM: |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1247 } | 1274 } |
1248 } | 1275 } |
1249 | 1276 |
1250 static void CopyOrSwap(const uint32_t* src, int num_pixels, uint8_t* dst, | 1277 static void CopyOrSwap(const uint32_t* src, int num_pixels, uint8_t* dst, |
1251 int swap_on_big_endian) { | 1278 int swap_on_big_endian) { |
1252 if (is_big_endian() == swap_on_big_endian) { | 1279 if (is_big_endian() == swap_on_big_endian) { |
1253 const uint32_t* const src_end = src + num_pixels; | 1280 const uint32_t* const src_end = src + num_pixels; |
1254 while (src < src_end) { | 1281 while (src < src_end) { |
1255 uint32_t argb = *src++; | 1282 uint32_t argb = *src++; |
1256 | 1283 |
| 1284 #if !defined(__BIG_ENDIAN__) |
1257 #if !defined(WEBP_REFERENCE_IMPLEMENTATION) | 1285 #if !defined(WEBP_REFERENCE_IMPLEMENTATION) |
1258 #if !defined(__BIG_ENDIAN__) && (defined(__i386__) || defined(__x86_64__)) | 1286 #if defined(__i386__) || defined(__x86_64__) |
1259 __asm__ volatile("bswap %0" : "=r"(argb) : "0"(argb)); | 1287 __asm__ volatile("bswap %0" : "=r"(argb) : "0"(argb)); |
1260 *(uint32_t*)dst = argb; | 1288 *(uint32_t*)dst = argb; |
1261 #elif !defined(__BIG_ENDIAN__) && defined(_MSC_VER) | 1289 #elif defined(_MSC_VER) |
1262 argb = _byteswap_ulong(argb); | 1290 argb = _byteswap_ulong(argb); |
1263 *(uint32_t*)dst = argb; | 1291 *(uint32_t*)dst = argb; |
1264 #else | 1292 #else |
1265 dst[0] = (argb >> 24) & 0xff; | 1293 dst[0] = (argb >> 24) & 0xff; |
1266 dst[1] = (argb >> 16) & 0xff; | 1294 dst[1] = (argb >> 16) & 0xff; |
1267 dst[2] = (argb >> 8) & 0xff; | 1295 dst[2] = (argb >> 8) & 0xff; |
1268 dst[3] = (argb >> 0) & 0xff; | 1296 dst[3] = (argb >> 0) & 0xff; |
1269 #endif | 1297 #endif |
1270 #else // WEBP_REFERENCE_IMPLEMENTATION | 1298 #else // WEBP_REFERENCE_IMPLEMENTATION |
1271 dst[0] = (argb >> 24) & 0xff; | 1299 dst[0] = (argb >> 24) & 0xff; |
1272 dst[1] = (argb >> 16) & 0xff; | 1300 dst[1] = (argb >> 16) & 0xff; |
1273 dst[2] = (argb >> 8) & 0xff; | 1301 dst[2] = (argb >> 8) & 0xff; |
1274 dst[3] = (argb >> 0) & 0xff; | 1302 dst[3] = (argb >> 0) & 0xff; |
1275 #endif | 1303 #endif |
| 1304 #else // __BIG_ENDIAN__ |
| 1305 dst[0] = (argb >> 0) & 0xff; |
| 1306 dst[1] = (argb >> 8) & 0xff; |
| 1307 dst[2] = (argb >> 16) & 0xff; |
| 1308 dst[3] = (argb >> 24) & 0xff; |
| 1309 #endif |
1276 dst += sizeof(argb); | 1310 dst += sizeof(argb); |
1277 } | 1311 } |
1278 } else { | 1312 } else { |
1279 memcpy(dst, src, num_pixels * sizeof(*src)); | 1313 memcpy(dst, src, num_pixels * sizeof(*src)); |
1280 } | 1314 } |
1281 } | 1315 } |
1282 | 1316 |
1283 void VP8LConvertFromBGRA(const uint32_t* const in_data, int num_pixels, | 1317 void VP8LConvertFromBGRA(const uint32_t* const in_data, int num_pixels, |
1284 WEBP_CSP_MODE out_colorspace, uint8_t* const rgba) { | 1318 WEBP_CSP_MODE out_colorspace, uint8_t* const rgba) { |
1285 switch (out_colorspace) { | 1319 switch (out_colorspace) { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1318 WebPApplyAlphaMultiply4444(rgba, num_pixels, 1, 0); | 1352 WebPApplyAlphaMultiply4444(rgba, num_pixels, 1, 0); |
1319 break; | 1353 break; |
1320 case MODE_RGB_565: | 1354 case MODE_RGB_565: |
1321 ConvertBGRAToRGB565(in_data, num_pixels, rgba); | 1355 ConvertBGRAToRGB565(in_data, num_pixels, rgba); |
1322 break; | 1356 break; |
1323 default: | 1357 default: |
1324 assert(0); // Code flow should not reach here. | 1358 assert(0); // Code flow should not reach here. |
1325 } | 1359 } |
1326 } | 1360 } |
1327 | 1361 |
| 1362 // Bundles multiple (1, 2, 4 or 8) pixels into a single pixel. |
| 1363 void VP8LBundleColorMap(const uint8_t* const row, int width, |
| 1364 int xbits, uint32_t* const dst) { |
| 1365 int x; |
| 1366 if (xbits > 0) { |
| 1367 const int bit_depth = 1 << (3 - xbits); |
| 1368 const int mask = (1 << xbits) - 1; |
| 1369 uint32_t code = 0xff000000; |
| 1370 for (x = 0; x < width; ++x) { |
| 1371 const int xsub = x & mask; |
| 1372 if (xsub == 0) { |
| 1373 code = 0xff000000; |
| 1374 } |
| 1375 code |= row[x] << (8 + bit_depth * xsub); |
| 1376 dst[x >> xbits] = code; |
| 1377 } |
| 1378 } else { |
| 1379 for (x = 0; x < width; ++x) dst[x] = 0xff000000 | (row[x] << 8); |
| 1380 } |
| 1381 } |
| 1382 |
1328 //------------------------------------------------------------------------------ | 1383 //------------------------------------------------------------------------------ |
1329 | 1384 |
1330 #if defined(__cplusplus) || defined(c_plusplus) | 1385 #if defined(__cplusplus) || defined(c_plusplus) |
1331 } // extern "C" | 1386 } // extern "C" |
1332 #endif | 1387 #endif |
OLD | NEW |