| 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 |