]> granicus.if.org Git - libvpx/blob - third_party/libyuv/source/convert_argb.cc
update libyuv to r1456
[libvpx] / third_party / libyuv / source / convert_argb.cc
1 /*
2  *  Copyright 2011 The LibYuv Project Authors. All rights reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS. All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10
11 #include "libyuv/convert_argb.h"
12
13 #include "libyuv/cpu_id.h"
14 #ifdef HAVE_JPEG
15 #include "libyuv/mjpeg_decoder.h"
16 #endif
17 #include "libyuv/rotate_argb.h"
18 #include "libyuv/row.h"
19 #include "libyuv/video_common.h"
20
21 #ifdef __cplusplus
22 namespace libyuv {
23 extern "C" {
24 #endif
25
26 // Copy ARGB with optional flipping
27 LIBYUV_API
28 int ARGBCopy(const uint8* src_argb, int src_stride_argb,
29              uint8* dst_argb, int dst_stride_argb,
30              int width, int height) {
31   if (!src_argb || !dst_argb ||
32       width <= 0 || height == 0) {
33     return -1;
34   }
35   // Negative height means invert the image.
36   if (height < 0) {
37     height = -height;
38     src_argb = src_argb + (height - 1) * src_stride_argb;
39     src_stride_argb = -src_stride_argb;
40   }
41
42   CopyPlane(src_argb, src_stride_argb, dst_argb, dst_stride_argb,
43             width * 4, height);
44   return 0;
45 }
46
47 // Convert I444 to ARGB.
48 LIBYUV_API
49 int I444ToARGB(const uint8* src_y, int src_stride_y,
50                const uint8* src_u, int src_stride_u,
51                const uint8* src_v, int src_stride_v,
52                uint8* dst_argb, int dst_stride_argb,
53                int width, int height) {
54   int y;
55   void (*I444ToARGBRow)(const uint8* y_buf,
56                         const uint8* u_buf,
57                         const uint8* v_buf,
58                         uint8* rgb_buf,
59                         int width) = I444ToARGBRow_C;
60   if (!src_y || !src_u || !src_v ||
61       !dst_argb ||
62       width <= 0 || height == 0) {
63     return -1;
64   }
65   // Negative height means invert the image.
66   if (height < 0) {
67     height = -height;
68     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
69     dst_stride_argb = -dst_stride_argb;
70   }
71   // Coalesce rows.
72   if (src_stride_y == width &&
73       src_stride_u == width &&
74       src_stride_v == width &&
75       dst_stride_argb == width * 4) {
76     width *= height;
77     height = 1;
78     src_stride_y = src_stride_u = src_stride_v = dst_stride_argb = 0;
79   }
80 #if defined(HAS_I444TOARGBROW_SSSE3)
81   if (TestCpuFlag(kCpuHasSSSE3)) {
82     I444ToARGBRow = I444ToARGBRow_Any_SSSE3;
83     if (IS_ALIGNED(width, 8)) {
84       I444ToARGBRow = I444ToARGBRow_SSSE3;
85     }
86   }
87 #endif
88 #if defined(HAS_I444TOARGBROW_AVX2)
89   if (TestCpuFlag(kCpuHasAVX2)) {
90     I444ToARGBRow = I444ToARGBRow_Any_AVX2;
91     if (IS_ALIGNED(width, 16)) {
92       I444ToARGBRow = I444ToARGBRow_AVX2;
93     }
94   }
95 #endif
96 #if defined(HAS_I444TOARGBROW_NEON)
97   if (TestCpuFlag(kCpuHasNEON)) {
98     I444ToARGBRow = I444ToARGBRow_Any_NEON;
99     if (IS_ALIGNED(width, 8)) {
100       I444ToARGBRow = I444ToARGBRow_NEON;
101     }
102   }
103 #endif
104
105   for (y = 0; y < height; ++y) {
106     I444ToARGBRow(src_y, src_u, src_v, dst_argb, width);
107     dst_argb += dst_stride_argb;
108     src_y += src_stride_y;
109     src_u += src_stride_u;
110     src_v += src_stride_v;
111   }
112   return 0;
113 }
114
115 // Convert I422 to ARGB.
116 LIBYUV_API
117 int I422ToARGB(const uint8* src_y, int src_stride_y,
118                const uint8* src_u, int src_stride_u,
119                const uint8* src_v, int src_stride_v,
120                uint8* dst_argb, int dst_stride_argb,
121                int width, int height) {
122   int y;
123   void (*I422ToARGBRow)(const uint8* y_buf,
124                         const uint8* u_buf,
125                         const uint8* v_buf,
126                         uint8* rgb_buf,
127                         int width) = I422ToARGBRow_C;
128   if (!src_y || !src_u || !src_v ||
129       !dst_argb ||
130       width <= 0 || height == 0) {
131     return -1;
132   }
133   // Negative height means invert the image.
134   if (height < 0) {
135     height = -height;
136     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
137     dst_stride_argb = -dst_stride_argb;
138   }
139   // Coalesce rows.
140   if (src_stride_y == width &&
141       src_stride_u * 2 == width &&
142       src_stride_v * 2 == width &&
143       dst_stride_argb == width * 4) {
144     width *= height;
145     height = 1;
146     src_stride_y = src_stride_u = src_stride_v = dst_stride_argb = 0;
147   }
148 #if defined(HAS_I422TOARGBROW_SSSE3)
149   if (TestCpuFlag(kCpuHasSSSE3)) {
150     I422ToARGBRow = I422ToARGBRow_Any_SSSE3;
151     if (IS_ALIGNED(width, 8)) {
152       I422ToARGBRow = I422ToARGBRow_SSSE3;
153     }
154   }
155 #endif
156 #if defined(HAS_I422TOARGBROW_AVX2)
157   if (TestCpuFlag(kCpuHasAVX2)) {
158     I422ToARGBRow = I422ToARGBRow_Any_AVX2;
159     if (IS_ALIGNED(width, 16)) {
160       I422ToARGBRow = I422ToARGBRow_AVX2;
161     }
162   }
163 #endif
164 #if defined(HAS_I422TOARGBROW_NEON)
165   if (TestCpuFlag(kCpuHasNEON)) {
166     I422ToARGBRow = I422ToARGBRow_Any_NEON;
167     if (IS_ALIGNED(width, 8)) {
168       I422ToARGBRow = I422ToARGBRow_NEON;
169     }
170   }
171 #endif
172 #if defined(HAS_I422TOARGBROW_MIPS_DSPR2)
173   if (TestCpuFlag(kCpuHasMIPS_DSPR2) && IS_ALIGNED(width, 4) &&
174       IS_ALIGNED(src_y, 4) && IS_ALIGNED(src_stride_y, 4) &&
175       IS_ALIGNED(src_u, 2) && IS_ALIGNED(src_stride_u, 2) &&
176       IS_ALIGNED(src_v, 2) && IS_ALIGNED(src_stride_v, 2) &&
177       IS_ALIGNED(dst_argb, 4) && IS_ALIGNED(dst_stride_argb, 4)) {
178     I422ToARGBRow = I422ToARGBRow_MIPS_DSPR2;
179   }
180 #endif
181
182   for (y = 0; y < height; ++y) {
183     I422ToARGBRow(src_y, src_u, src_v, dst_argb, width);
184     dst_argb += dst_stride_argb;
185     src_y += src_stride_y;
186     src_u += src_stride_u;
187     src_v += src_stride_v;
188   }
189   return 0;
190 }
191
192 // Convert I411 to ARGB.
193 LIBYUV_API
194 int I411ToARGB(const uint8* src_y, int src_stride_y,
195                const uint8* src_u, int src_stride_u,
196                const uint8* src_v, int src_stride_v,
197                uint8* dst_argb, int dst_stride_argb,
198                int width, int height) {
199   int y;
200   void (*I411ToARGBRow)(const uint8* y_buf,
201                         const uint8* u_buf,
202                         const uint8* v_buf,
203                         uint8* rgb_buf,
204                         int width) = I411ToARGBRow_C;
205   if (!src_y || !src_u || !src_v ||
206       !dst_argb ||
207       width <= 0 || height == 0) {
208     return -1;
209   }
210   // Negative height means invert the image.
211   if (height < 0) {
212     height = -height;
213     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
214     dst_stride_argb = -dst_stride_argb;
215   }
216   // Coalesce rows.
217   if (src_stride_y == width &&
218       src_stride_u * 4 == width &&
219       src_stride_v * 4 == width &&
220       dst_stride_argb == width * 4) {
221     width *= height;
222     height = 1;
223     src_stride_y = src_stride_u = src_stride_v = dst_stride_argb = 0;
224   }
225 #if defined(HAS_I411TOARGBROW_SSSE3)
226   if (TestCpuFlag(kCpuHasSSSE3)) {
227     I411ToARGBRow = I411ToARGBRow_Any_SSSE3;
228     if (IS_ALIGNED(width, 8)) {
229       I411ToARGBRow = I411ToARGBRow_SSSE3;
230     }
231   }
232 #endif
233 #if defined(HAS_I411TOARGBROW_AVX2)
234   if (TestCpuFlag(kCpuHasAVX2)) {
235     I411ToARGBRow = I411ToARGBRow_Any_AVX2;
236     if (IS_ALIGNED(width, 16)) {
237       I411ToARGBRow = I411ToARGBRow_AVX2;
238     }
239   }
240 #endif
241 #if defined(HAS_I411TOARGBROW_NEON)
242   if (TestCpuFlag(kCpuHasNEON)) {
243     I411ToARGBRow = I411ToARGBRow_Any_NEON;
244     if (IS_ALIGNED(width, 8)) {
245       I411ToARGBRow = I411ToARGBRow_NEON;
246     }
247   }
248 #endif
249
250   for (y = 0; y < height; ++y) {
251     I411ToARGBRow(src_y, src_u, src_v, dst_argb, width);
252     dst_argb += dst_stride_argb;
253     src_y += src_stride_y;
254     src_u += src_stride_u;
255     src_v += src_stride_v;
256   }
257   return 0;
258 }
259
260 // Convert I400 to ARGB.
261 LIBYUV_API
262 int I400ToARGB(const uint8* src_y, int src_stride_y,
263                uint8* dst_argb, int dst_stride_argb,
264                int width, int height) {
265   int y;
266   void (*I400ToARGBRow)(const uint8* y_buf,
267                      uint8* rgb_buf,
268                      int width) = I400ToARGBRow_C;
269   if (!src_y || !dst_argb ||
270       width <= 0 || height == 0) {
271     return -1;
272   }
273   // Negative height means invert the image.
274   if (height < 0) {
275     height = -height;
276     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
277     dst_stride_argb = -dst_stride_argb;
278   }
279   // Coalesce rows.
280   if (src_stride_y == width &&
281       dst_stride_argb == width * 4) {
282     width *= height;
283     height = 1;
284     src_stride_y = dst_stride_argb = 0;
285   }
286 #if defined(HAS_I400TOARGBROW_SSE2)
287   if (TestCpuFlag(kCpuHasSSE2)) {
288     I400ToARGBRow = I400ToARGBRow_Any_SSE2;
289     if (IS_ALIGNED(width, 8)) {
290       I400ToARGBRow = I400ToARGBRow_SSE2;
291     }
292   }
293 #endif
294 #if defined(HAS_I400TOARGBROW_AVX2)
295   if (TestCpuFlag(kCpuHasAVX2)) {
296     I400ToARGBRow = I400ToARGBRow_Any_AVX2;
297     if (IS_ALIGNED(width, 16)) {
298       I400ToARGBRow = I400ToARGBRow_AVX2;
299     }
300   }
301 #endif
302 #if defined(HAS_I400TOARGBROW_NEON)
303   if (TestCpuFlag(kCpuHasNEON)) {
304     I400ToARGBRow = I400ToARGBRow_Any_NEON;
305     if (IS_ALIGNED(width, 8)) {
306       I400ToARGBRow = I400ToARGBRow_NEON;
307     }
308   }
309 #endif
310
311   for (y = 0; y < height; ++y) {
312     I400ToARGBRow(src_y, dst_argb, width);
313     dst_argb += dst_stride_argb;
314     src_y += src_stride_y;
315   }
316   return 0;
317 }
318
319 // Convert J400 to ARGB.
320 LIBYUV_API
321 int J400ToARGB(const uint8* src_y, int src_stride_y,
322                uint8* dst_argb, int dst_stride_argb,
323                int width, int height) {
324   int y;
325   void (*J400ToARGBRow)(const uint8* src_y, uint8* dst_argb, int pix) =
326       J400ToARGBRow_C;
327   if (!src_y || !dst_argb ||
328       width <= 0 || height == 0) {
329     return -1;
330   }
331   // Negative height means invert the image.
332   if (height < 0) {
333     height = -height;
334     src_y = src_y + (height - 1) * src_stride_y;
335     src_stride_y = -src_stride_y;
336   }
337   // Coalesce rows.
338   if (src_stride_y == width &&
339       dst_stride_argb == width * 4) {
340     width *= height;
341     height = 1;
342     src_stride_y = dst_stride_argb = 0;
343   }
344 #if defined(HAS_J400TOARGBROW_SSE2)
345   if (TestCpuFlag(kCpuHasSSE2)) {
346     J400ToARGBRow = J400ToARGBRow_Any_SSE2;
347     if (IS_ALIGNED(width, 8)) {
348       J400ToARGBRow = J400ToARGBRow_SSE2;
349     }
350   }
351 #endif
352 #if defined(HAS_J400TOARGBROW_AVX2)
353   if (TestCpuFlag(kCpuHasAVX2)) {
354     J400ToARGBRow = J400ToARGBRow_Any_AVX2;
355     if (IS_ALIGNED(width, 16)) {
356       J400ToARGBRow = J400ToARGBRow_AVX2;
357     }
358   }
359 #endif
360 #if defined(HAS_J400TOARGBROW_NEON)
361   if (TestCpuFlag(kCpuHasNEON)) {
362     J400ToARGBRow = J400ToARGBRow_Any_NEON;
363     if (IS_ALIGNED(width, 8)) {
364       J400ToARGBRow = J400ToARGBRow_NEON;
365     }
366   }
367 #endif
368   for (y = 0; y < height; ++y) {
369     J400ToARGBRow(src_y, dst_argb, width);
370     src_y += src_stride_y;
371     dst_argb += dst_stride_argb;
372   }
373   return 0;
374 }
375
376 // Shuffle table for converting BGRA to ARGB.
377 static uvec8 kShuffleMaskBGRAToARGB = {
378   3u, 2u, 1u, 0u, 7u, 6u, 5u, 4u, 11u, 10u, 9u, 8u, 15u, 14u, 13u, 12u
379 };
380
381 // Shuffle table for converting ABGR to ARGB.
382 static uvec8 kShuffleMaskABGRToARGB = {
383   2u, 1u, 0u, 3u, 6u, 5u, 4u, 7u, 10u, 9u, 8u, 11u, 14u, 13u, 12u, 15u
384 };
385
386 // Shuffle table for converting RGBA to ARGB.
387 static uvec8 kShuffleMaskRGBAToARGB = {
388   1u, 2u, 3u, 0u, 5u, 6u, 7u, 4u, 9u, 10u, 11u, 8u, 13u, 14u, 15u, 12u
389 };
390
391 // Convert BGRA to ARGB.
392 LIBYUV_API
393 int BGRAToARGB(const uint8* src_bgra, int src_stride_bgra,
394                uint8* dst_argb, int dst_stride_argb,
395                int width, int height) {
396   return ARGBShuffle(src_bgra, src_stride_bgra,
397                      dst_argb, dst_stride_argb,
398                      (const uint8*)(&kShuffleMaskBGRAToARGB),
399                      width, height);
400 }
401
402 // Convert ARGB to BGRA (same as BGRAToARGB).
403 LIBYUV_API
404 int ARGBToBGRA(const uint8* src_bgra, int src_stride_bgra,
405                uint8* dst_argb, int dst_stride_argb,
406                int width, int height) {
407   return ARGBShuffle(src_bgra, src_stride_bgra,
408                      dst_argb, dst_stride_argb,
409                      (const uint8*)(&kShuffleMaskBGRAToARGB),
410                      width, height);
411 }
412
413 // Convert ABGR to ARGB.
414 LIBYUV_API
415 int ABGRToARGB(const uint8* src_abgr, int src_stride_abgr,
416                uint8* dst_argb, int dst_stride_argb,
417                int width, int height) {
418   return ARGBShuffle(src_abgr, src_stride_abgr,
419                      dst_argb, dst_stride_argb,
420                      (const uint8*)(&kShuffleMaskABGRToARGB),
421                      width, height);
422 }
423
424 // Convert ARGB to ABGR to (same as ABGRToARGB).
425 LIBYUV_API
426 int ARGBToABGR(const uint8* src_abgr, int src_stride_abgr,
427                uint8* dst_argb, int dst_stride_argb,
428                int width, int height) {
429   return ARGBShuffle(src_abgr, src_stride_abgr,
430                      dst_argb, dst_stride_argb,
431                      (const uint8*)(&kShuffleMaskABGRToARGB),
432                      width, height);
433 }
434
435 // Convert RGBA to ARGB.
436 LIBYUV_API
437 int RGBAToARGB(const uint8* src_rgba, int src_stride_rgba,
438                uint8* dst_argb, int dst_stride_argb,
439                int width, int height) {
440   return ARGBShuffle(src_rgba, src_stride_rgba,
441                      dst_argb, dst_stride_argb,
442                      (const uint8*)(&kShuffleMaskRGBAToARGB),
443                      width, height);
444 }
445
446 // Convert RGB24 to ARGB.
447 LIBYUV_API
448 int RGB24ToARGB(const uint8* src_rgb24, int src_stride_rgb24,
449                 uint8* dst_argb, int dst_stride_argb,
450                 int width, int height) {
451   int y;
452   void (*RGB24ToARGBRow)(const uint8* src_rgb, uint8* dst_argb, int pix) =
453       RGB24ToARGBRow_C;
454   if (!src_rgb24 || !dst_argb ||
455       width <= 0 || height == 0) {
456     return -1;
457   }
458   // Negative height means invert the image.
459   if (height < 0) {
460     height = -height;
461     src_rgb24 = src_rgb24 + (height - 1) * src_stride_rgb24;
462     src_stride_rgb24 = -src_stride_rgb24;
463   }
464   // Coalesce rows.
465   if (src_stride_rgb24 == width * 3 &&
466       dst_stride_argb == width * 4) {
467     width *= height;
468     height = 1;
469     src_stride_rgb24 = dst_stride_argb = 0;
470   }
471 #if defined(HAS_RGB24TOARGBROW_SSSE3)
472   if (TestCpuFlag(kCpuHasSSSE3)) {
473     RGB24ToARGBRow = RGB24ToARGBRow_Any_SSSE3;
474     if (IS_ALIGNED(width, 16)) {
475       RGB24ToARGBRow = RGB24ToARGBRow_SSSE3;
476     }
477   }
478 #endif
479 #if defined(HAS_RGB24TOARGBROW_NEON)
480   if (TestCpuFlag(kCpuHasNEON)) {
481     RGB24ToARGBRow = RGB24ToARGBRow_Any_NEON;
482     if (IS_ALIGNED(width, 8)) {
483       RGB24ToARGBRow = RGB24ToARGBRow_NEON;
484     }
485   }
486 #endif
487
488   for (y = 0; y < height; ++y) {
489     RGB24ToARGBRow(src_rgb24, dst_argb, width);
490     src_rgb24 += src_stride_rgb24;
491     dst_argb += dst_stride_argb;
492   }
493   return 0;
494 }
495
496 // Convert RAW to ARGB.
497 LIBYUV_API
498 int RAWToARGB(const uint8* src_raw, int src_stride_raw,
499               uint8* dst_argb, int dst_stride_argb,
500               int width, int height) {
501   int y;
502   void (*RAWToARGBRow)(const uint8* src_rgb, uint8* dst_argb, int pix) =
503       RAWToARGBRow_C;
504   if (!src_raw || !dst_argb ||
505       width <= 0 || height == 0) {
506     return -1;
507   }
508   // Negative height means invert the image.
509   if (height < 0) {
510     height = -height;
511     src_raw = src_raw + (height - 1) * src_stride_raw;
512     src_stride_raw = -src_stride_raw;
513   }
514   // Coalesce rows.
515   if (src_stride_raw == width * 3 &&
516       dst_stride_argb == width * 4) {
517     width *= height;
518     height = 1;
519     src_stride_raw = dst_stride_argb = 0;
520   }
521 #if defined(HAS_RAWTOARGBROW_SSSE3)
522   if (TestCpuFlag(kCpuHasSSSE3)) {
523     RAWToARGBRow = RAWToARGBRow_Any_SSSE3;
524     if (IS_ALIGNED(width, 16)) {
525       RAWToARGBRow = RAWToARGBRow_SSSE3;
526     }
527   }
528 #endif
529 #if defined(HAS_RAWTOARGBROW_NEON)
530   if (TestCpuFlag(kCpuHasNEON)) {
531     RAWToARGBRow = RAWToARGBRow_Any_NEON;
532     if (IS_ALIGNED(width, 8)) {
533       RAWToARGBRow = RAWToARGBRow_NEON;
534     }
535   }
536 #endif
537
538   for (y = 0; y < height; ++y) {
539     RAWToARGBRow(src_raw, dst_argb, width);
540     src_raw += src_stride_raw;
541     dst_argb += dst_stride_argb;
542   }
543   return 0;
544 }
545
546 // Convert RGB565 to ARGB.
547 LIBYUV_API
548 int RGB565ToARGB(const uint8* src_rgb565, int src_stride_rgb565,
549                  uint8* dst_argb, int dst_stride_argb,
550                  int width, int height) {
551   int y;
552   void (*RGB565ToARGBRow)(const uint8* src_rgb565, uint8* dst_argb, int pix) =
553       RGB565ToARGBRow_C;
554   if (!src_rgb565 || !dst_argb ||
555       width <= 0 || height == 0) {
556     return -1;
557   }
558   // Negative height means invert the image.
559   if (height < 0) {
560     height = -height;
561     src_rgb565 = src_rgb565 + (height - 1) * src_stride_rgb565;
562     src_stride_rgb565 = -src_stride_rgb565;
563   }
564   // Coalesce rows.
565   if (src_stride_rgb565 == width * 2 &&
566       dst_stride_argb == width * 4) {
567     width *= height;
568     height = 1;
569     src_stride_rgb565 = dst_stride_argb = 0;
570   }
571 #if defined(HAS_RGB565TOARGBROW_SSE2)
572   if (TestCpuFlag(kCpuHasSSE2)) {
573     RGB565ToARGBRow = RGB565ToARGBRow_Any_SSE2;
574     if (IS_ALIGNED(width, 8)) {
575       RGB565ToARGBRow = RGB565ToARGBRow_SSE2;
576     }
577   }
578 #endif
579 #if defined(HAS_RGB565TOARGBROW_AVX2)
580   if (TestCpuFlag(kCpuHasAVX2)) {
581     RGB565ToARGBRow = RGB565ToARGBRow_Any_AVX2;
582     if (IS_ALIGNED(width, 16)) {
583       RGB565ToARGBRow = RGB565ToARGBRow_AVX2;
584     }
585   }
586 #endif
587 #if defined(HAS_RGB565TOARGBROW_NEON)
588   if (TestCpuFlag(kCpuHasNEON)) {
589     RGB565ToARGBRow = RGB565ToARGBRow_Any_NEON;
590     if (IS_ALIGNED(width, 8)) {
591       RGB565ToARGBRow = RGB565ToARGBRow_NEON;
592     }
593   }
594 #endif
595
596   for (y = 0; y < height; ++y) {
597     RGB565ToARGBRow(src_rgb565, dst_argb, width);
598     src_rgb565 += src_stride_rgb565;
599     dst_argb += dst_stride_argb;
600   }
601   return 0;
602 }
603
604 // Convert ARGB1555 to ARGB.
605 LIBYUV_API
606 int ARGB1555ToARGB(const uint8* src_argb1555, int src_stride_argb1555,
607                    uint8* dst_argb, int dst_stride_argb,
608                    int width, int height) {
609   int y;
610   void (*ARGB1555ToARGBRow)(const uint8* src_argb1555, uint8* dst_argb,
611       int pix) = ARGB1555ToARGBRow_C;
612   if (!src_argb1555 || !dst_argb ||
613       width <= 0 || height == 0) {
614     return -1;
615   }
616   // Negative height means invert the image.
617   if (height < 0) {
618     height = -height;
619     src_argb1555 = src_argb1555 + (height - 1) * src_stride_argb1555;
620     src_stride_argb1555 = -src_stride_argb1555;
621   }
622   // Coalesce rows.
623   if (src_stride_argb1555 == width * 2 &&
624       dst_stride_argb == width * 4) {
625     width *= height;
626     height = 1;
627     src_stride_argb1555 = dst_stride_argb = 0;
628   }
629 #if defined(HAS_ARGB1555TOARGBROW_SSE2)
630   if (TestCpuFlag(kCpuHasSSE2)) {
631     ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_SSE2;
632     if (IS_ALIGNED(width, 8)) {
633       ARGB1555ToARGBRow = ARGB1555ToARGBRow_SSE2;
634     }
635   }
636 #endif
637 #if defined(HAS_ARGB1555TOARGBROW_AVX2)
638   if (TestCpuFlag(kCpuHasAVX2)) {
639     ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_AVX2;
640     if (IS_ALIGNED(width, 16)) {
641       ARGB1555ToARGBRow = ARGB1555ToARGBRow_AVX2;
642     }
643   }
644 #endif
645 #if defined(HAS_ARGB1555TOARGBROW_NEON)
646   if (TestCpuFlag(kCpuHasNEON)) {
647     ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_NEON;
648     if (IS_ALIGNED(width, 8)) {
649       ARGB1555ToARGBRow = ARGB1555ToARGBRow_NEON;
650     }
651   }
652 #endif
653
654   for (y = 0; y < height; ++y) {
655     ARGB1555ToARGBRow(src_argb1555, dst_argb, width);
656     src_argb1555 += src_stride_argb1555;
657     dst_argb += dst_stride_argb;
658   }
659   return 0;
660 }
661
662 // Convert ARGB4444 to ARGB.
663 LIBYUV_API
664 int ARGB4444ToARGB(const uint8* src_argb4444, int src_stride_argb4444,
665                    uint8* dst_argb, int dst_stride_argb,
666                    int width, int height) {
667   int y;
668   void (*ARGB4444ToARGBRow)(const uint8* src_argb4444, uint8* dst_argb,
669       int pix) = ARGB4444ToARGBRow_C;
670   if (!src_argb4444 || !dst_argb ||
671       width <= 0 || height == 0) {
672     return -1;
673   }
674   // Negative height means invert the image.
675   if (height < 0) {
676     height = -height;
677     src_argb4444 = src_argb4444 + (height - 1) * src_stride_argb4444;
678     src_stride_argb4444 = -src_stride_argb4444;
679   }
680   // Coalesce rows.
681   if (src_stride_argb4444 == width * 2 &&
682       dst_stride_argb == width * 4) {
683     width *= height;
684     height = 1;
685     src_stride_argb4444 = dst_stride_argb = 0;
686   }
687 #if defined(HAS_ARGB4444TOARGBROW_SSE2)
688   if (TestCpuFlag(kCpuHasSSE2)) {
689     ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_SSE2;
690     if (IS_ALIGNED(width, 8)) {
691       ARGB4444ToARGBRow = ARGB4444ToARGBRow_SSE2;
692     }
693   }
694 #endif
695 #if defined(HAS_ARGB4444TOARGBROW_AVX2)
696   if (TestCpuFlag(kCpuHasAVX2)) {
697     ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_AVX2;
698     if (IS_ALIGNED(width, 16)) {
699       ARGB4444ToARGBRow = ARGB4444ToARGBRow_AVX2;
700     }
701   }
702 #endif
703 #if defined(HAS_ARGB4444TOARGBROW_NEON)
704   if (TestCpuFlag(kCpuHasNEON)) {
705     ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_NEON;
706     if (IS_ALIGNED(width, 8)) {
707       ARGB4444ToARGBRow = ARGB4444ToARGBRow_NEON;
708     }
709   }
710 #endif
711
712   for (y = 0; y < height; ++y) {
713     ARGB4444ToARGBRow(src_argb4444, dst_argb, width);
714     src_argb4444 += src_stride_argb4444;
715     dst_argb += dst_stride_argb;
716   }
717   return 0;
718 }
719
720 // Convert NV12 to ARGB.
721 LIBYUV_API
722 int NV12ToARGB(const uint8* src_y, int src_stride_y,
723                const uint8* src_uv, int src_stride_uv,
724                uint8* dst_argb, int dst_stride_argb,
725                int width, int height) {
726   int y;
727   void (*NV12ToARGBRow)(const uint8* y_buf,
728                         const uint8* uv_buf,
729                         uint8* rgb_buf,
730                         int width) = NV12ToARGBRow_C;
731   if (!src_y || !src_uv || !dst_argb ||
732       width <= 0 || height == 0) {
733     return -1;
734   }
735   // Negative height means invert the image.
736   if (height < 0) {
737     height = -height;
738     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
739     dst_stride_argb = -dst_stride_argb;
740   }
741 #if defined(HAS_NV12TOARGBROW_SSSE3)
742   if (TestCpuFlag(kCpuHasSSSE3)) {
743     NV12ToARGBRow = NV12ToARGBRow_Any_SSSE3;
744     if (IS_ALIGNED(width, 8)) {
745       NV12ToARGBRow = NV12ToARGBRow_SSSE3;
746     }
747   }
748 #endif
749 #if defined(HAS_NV12TOARGBROW_AVX2)
750   if (TestCpuFlag(kCpuHasAVX2)) {
751     NV12ToARGBRow = NV12ToARGBRow_Any_AVX2;
752     if (IS_ALIGNED(width, 16)) {
753       NV12ToARGBRow = NV12ToARGBRow_AVX2;
754     }
755   }
756 #endif
757 #if defined(HAS_NV12TOARGBROW_NEON)
758   if (TestCpuFlag(kCpuHasNEON)) {
759     NV12ToARGBRow = NV12ToARGBRow_Any_NEON;
760     if (IS_ALIGNED(width, 8)) {
761       NV12ToARGBRow = NV12ToARGBRow_NEON;
762     }
763   }
764 #endif
765
766   for (y = 0; y < height; ++y) {
767     NV12ToARGBRow(src_y, src_uv, dst_argb, width);
768     dst_argb += dst_stride_argb;
769     src_y += src_stride_y;
770     if (y & 1) {
771       src_uv += src_stride_uv;
772     }
773   }
774   return 0;
775 }
776
777 // Convert NV21 to ARGB.
778 LIBYUV_API
779 int NV21ToARGB(const uint8* src_y, int src_stride_y,
780                const uint8* src_uv, int src_stride_uv,
781                uint8* dst_argb, int dst_stride_argb,
782                int width, int height) {
783   int y;
784   void (*NV21ToARGBRow)(const uint8* y_buf,
785                         const uint8* uv_buf,
786                         uint8* rgb_buf,
787                         int width) = NV21ToARGBRow_C;
788   if (!src_y || !src_uv || !dst_argb ||
789       width <= 0 || height == 0) {
790     return -1;
791   }
792   // Negative height means invert the image.
793   if (height < 0) {
794     height = -height;
795     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
796     dst_stride_argb = -dst_stride_argb;
797   }
798 #if defined(HAS_NV21TOARGBROW_SSSE3)
799   if (TestCpuFlag(kCpuHasSSSE3)) {
800     NV21ToARGBRow = NV21ToARGBRow_Any_SSSE3;
801     if (IS_ALIGNED(width, 8)) {
802       NV21ToARGBRow = NV21ToARGBRow_SSSE3;
803     }
804   }
805 #endif
806 #if defined(HAS_NV21TOARGBROW_AVX2)
807   if (TestCpuFlag(kCpuHasAVX2)) {
808     NV21ToARGBRow = NV21ToARGBRow_Any_AVX2;
809     if (IS_ALIGNED(width, 16)) {
810       NV21ToARGBRow = NV21ToARGBRow_AVX2;
811     }
812   }
813 #endif
814 #if defined(HAS_NV21TOARGBROW_NEON)
815   if (TestCpuFlag(kCpuHasNEON)) {
816     NV21ToARGBRow = NV21ToARGBRow_Any_NEON;
817     if (IS_ALIGNED(width, 8)) {
818       NV21ToARGBRow = NV21ToARGBRow_NEON;
819     }
820   }
821 #endif
822
823   for (y = 0; y < height; ++y) {
824     NV21ToARGBRow(src_y, src_uv, dst_argb, width);
825     dst_argb += dst_stride_argb;
826     src_y += src_stride_y;
827     if (y & 1) {
828       src_uv += src_stride_uv;
829     }
830   }
831   return 0;
832 }
833
834 // Convert M420 to ARGB.
835 LIBYUV_API
836 int M420ToARGB(const uint8* src_m420, int src_stride_m420,
837                uint8* dst_argb, int dst_stride_argb,
838                int width, int height) {
839   int y;
840   void (*NV12ToARGBRow)(const uint8* y_buf,
841                         const uint8* uv_buf,
842                         uint8* rgb_buf,
843                         int width) = NV12ToARGBRow_C;
844   if (!src_m420 || !dst_argb ||
845       width <= 0 || height == 0) {
846     return -1;
847   }
848   // Negative height means invert the image.
849   if (height < 0) {
850     height = -height;
851     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
852     dst_stride_argb = -dst_stride_argb;
853   }
854 #if defined(HAS_NV12TOARGBROW_SSSE3)
855   if (TestCpuFlag(kCpuHasSSSE3)) {
856     NV12ToARGBRow = NV12ToARGBRow_Any_SSSE3;
857     if (IS_ALIGNED(width, 8)) {
858       NV12ToARGBRow = NV12ToARGBRow_SSSE3;
859     }
860   }
861 #endif
862 #if defined(HAS_NV12TOARGBROW_AVX2)
863   if (TestCpuFlag(kCpuHasAVX2)) {
864     NV12ToARGBRow = NV12ToARGBRow_Any_AVX2;
865     if (IS_ALIGNED(width, 16)) {
866       NV12ToARGBRow = NV12ToARGBRow_AVX2;
867     }
868   }
869 #endif
870 #if defined(HAS_NV12TOARGBROW_NEON)
871   if (TestCpuFlag(kCpuHasNEON)) {
872     NV12ToARGBRow = NV12ToARGBRow_Any_NEON;
873     if (IS_ALIGNED(width, 8)) {
874       NV12ToARGBRow = NV12ToARGBRow_NEON;
875     }
876   }
877 #endif
878
879   for (y = 0; y < height - 1; y += 2) {
880     NV12ToARGBRow(src_m420, src_m420 + src_stride_m420 * 2, dst_argb, width);
881     NV12ToARGBRow(src_m420 + src_stride_m420, src_m420 + src_stride_m420 * 2,
882                   dst_argb + dst_stride_argb, width);
883     dst_argb += dst_stride_argb * 2;
884     src_m420 += src_stride_m420 * 3;
885   }
886   if (height & 1) {
887     NV12ToARGBRow(src_m420, src_m420 + src_stride_m420 * 2, dst_argb, width);
888   }
889   return 0;
890 }
891
892 // Convert YUY2 to ARGB.
893 LIBYUV_API
894 int YUY2ToARGB(const uint8* src_yuy2, int src_stride_yuy2,
895                uint8* dst_argb, int dst_stride_argb,
896                int width, int height) {
897   int y;
898   void (*YUY2ToARGBRow)(const uint8* src_yuy2, uint8* dst_argb, int pix) =
899       YUY2ToARGBRow_C;
900   if (!src_yuy2 || !dst_argb ||
901       width <= 0 || height == 0) {
902     return -1;
903   }
904   // Negative height means invert the image.
905   if (height < 0) {
906     height = -height;
907     src_yuy2 = src_yuy2 + (height - 1) * src_stride_yuy2;
908     src_stride_yuy2 = -src_stride_yuy2;
909   }
910   // Coalesce rows.
911   if (src_stride_yuy2 == width * 2 &&
912       dst_stride_argb == width * 4) {
913     width *= height;
914     height = 1;
915     src_stride_yuy2 = dst_stride_argb = 0;
916   }
917 #if defined(HAS_YUY2TOARGBROW_SSSE3)
918   if (TestCpuFlag(kCpuHasSSSE3)) {
919     YUY2ToARGBRow = YUY2ToARGBRow_Any_SSSE3;
920     if (IS_ALIGNED(width, 16)) {
921       YUY2ToARGBRow = YUY2ToARGBRow_SSSE3;
922     }
923   }
924 #endif
925 #if defined(HAS_YUY2TOARGBROW_AVX2)
926   if (TestCpuFlag(kCpuHasAVX2)) {
927     YUY2ToARGBRow = YUY2ToARGBRow_Any_AVX2;
928     if (IS_ALIGNED(width, 32)) {
929       YUY2ToARGBRow = YUY2ToARGBRow_AVX2;
930     }
931   }
932 #endif
933 #if defined(HAS_YUY2TOARGBROW_NEON)
934   if (TestCpuFlag(kCpuHasNEON)) {
935     YUY2ToARGBRow = YUY2ToARGBRow_Any_NEON;
936     if (IS_ALIGNED(width, 8)) {
937       YUY2ToARGBRow = YUY2ToARGBRow_NEON;
938     }
939   }
940 #endif
941   for (y = 0; y < height; ++y) {
942     YUY2ToARGBRow(src_yuy2, dst_argb, width);
943     src_yuy2 += src_stride_yuy2;
944     dst_argb += dst_stride_argb;
945   }
946   return 0;
947 }
948
949 // Convert UYVY to ARGB.
950 LIBYUV_API
951 int UYVYToARGB(const uint8* src_uyvy, int src_stride_uyvy,
952                uint8* dst_argb, int dst_stride_argb,
953                int width, int height) {
954   int y;
955   void (*UYVYToARGBRow)(const uint8* src_uyvy, uint8* dst_argb, int pix) =
956       UYVYToARGBRow_C;
957   if (!src_uyvy || !dst_argb ||
958       width <= 0 || height == 0) {
959     return -1;
960   }
961   // Negative height means invert the image.
962   if (height < 0) {
963     height = -height;
964     src_uyvy = src_uyvy + (height - 1) * src_stride_uyvy;
965     src_stride_uyvy = -src_stride_uyvy;
966   }
967   // Coalesce rows.
968   if (src_stride_uyvy == width * 2 &&
969       dst_stride_argb == width * 4) {
970     width *= height;
971     height = 1;
972     src_stride_uyvy = dst_stride_argb = 0;
973   }
974 #if defined(HAS_UYVYTOARGBROW_SSSE3)
975   if (TestCpuFlag(kCpuHasSSSE3)) {
976     UYVYToARGBRow = UYVYToARGBRow_Any_SSSE3;
977     if (IS_ALIGNED(width, 16)) {
978       UYVYToARGBRow = UYVYToARGBRow_SSSE3;
979     }
980   }
981 #endif
982 #if defined(HAS_UYVYTOARGBROW_AVX2)
983   if (TestCpuFlag(kCpuHasAVX2)) {
984     UYVYToARGBRow = UYVYToARGBRow_Any_AVX2;
985     if (IS_ALIGNED(width, 32)) {
986       UYVYToARGBRow = UYVYToARGBRow_AVX2;
987     }
988   }
989 #endif
990 #if defined(HAS_UYVYTOARGBROW_NEON)
991   if (TestCpuFlag(kCpuHasNEON)) {
992     UYVYToARGBRow = UYVYToARGBRow_Any_NEON;
993     if (IS_ALIGNED(width, 8)) {
994       UYVYToARGBRow = UYVYToARGBRow_NEON;
995     }
996   }
997 #endif
998   for (y = 0; y < height; ++y) {
999     UYVYToARGBRow(src_uyvy, dst_argb, width);
1000     src_uyvy += src_stride_uyvy;
1001     dst_argb += dst_stride_argb;
1002   }
1003   return 0;
1004 }
1005
1006 // Convert J420 to ARGB.
1007 LIBYUV_API
1008 int J420ToARGB(const uint8* src_y, int src_stride_y,
1009                const uint8* src_u, int src_stride_u,
1010                const uint8* src_v, int src_stride_v,
1011                uint8* dst_argb, int dst_stride_argb,
1012                int width, int height) {
1013   int y;
1014   void (*J422ToARGBRow)(const uint8* y_buf,
1015                         const uint8* u_buf,
1016                         const uint8* v_buf,
1017                         uint8* rgb_buf,
1018                         int width) = J422ToARGBRow_C;
1019   if (!src_y || !src_u || !src_v || !dst_argb ||
1020       width <= 0 || height == 0) {
1021     return -1;
1022   }
1023   // Negative height means invert the image.
1024   if (height < 0) {
1025     height = -height;
1026     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
1027     dst_stride_argb = -dst_stride_argb;
1028   }
1029 #if defined(HAS_J422TOARGBROW_SSSE3)
1030   if (TestCpuFlag(kCpuHasSSSE3)) {
1031     J422ToARGBRow = J422ToARGBRow_Any_SSSE3;
1032     if (IS_ALIGNED(width, 8)) {
1033       J422ToARGBRow = J422ToARGBRow_SSSE3;
1034     }
1035   }
1036 #endif
1037 #if defined(HAS_J422TOARGBROW_AVX2)
1038   if (TestCpuFlag(kCpuHasAVX2)) {
1039     J422ToARGBRow = J422ToARGBRow_Any_AVX2;
1040     if (IS_ALIGNED(width, 16)) {
1041       J422ToARGBRow = J422ToARGBRow_AVX2;
1042     }
1043   }
1044 #endif
1045 #if defined(HAS_J422TOARGBROW_NEON)
1046   if (TestCpuFlag(kCpuHasNEON)) {
1047     J422ToARGBRow = J422ToARGBRow_Any_NEON;
1048     if (IS_ALIGNED(width, 8)) {
1049       J422ToARGBRow = J422ToARGBRow_NEON;
1050     }
1051   }
1052 #endif
1053 #if defined(HAS_J422TOARGBROW_MIPS_DSPR2)
1054   if (TestCpuFlag(kCpuHasMIPS_DSPR2) && IS_ALIGNED(width, 4) &&
1055       IS_ALIGNED(src_y, 4) && IS_ALIGNED(src_stride_y, 4) &&
1056       IS_ALIGNED(src_u, 2) && IS_ALIGNED(src_stride_u, 2) &&
1057       IS_ALIGNED(src_v, 2) && IS_ALIGNED(src_stride_v, 2) &&
1058       IS_ALIGNED(dst_argb, 4) && IS_ALIGNED(dst_stride_argb, 4)) {
1059     J422ToARGBRow = J422ToARGBRow_MIPS_DSPR2;
1060   }
1061 #endif
1062
1063   for (y = 0; y < height; ++y) {
1064     J422ToARGBRow(src_y, src_u, src_v, dst_argb, width);
1065     dst_argb += dst_stride_argb;
1066     src_y += src_stride_y;
1067     if (y & 1) {
1068       src_u += src_stride_u;
1069       src_v += src_stride_v;
1070     }
1071   }
1072   return 0;
1073 }
1074
1075 // Convert J422 to ARGB.
1076 LIBYUV_API
1077 int J422ToARGB(const uint8* src_y, int src_stride_y,
1078                const uint8* src_u, int src_stride_u,
1079                const uint8* src_v, int src_stride_v,
1080                uint8* dst_argb, int dst_stride_argb,
1081                int width, int height) {
1082   int y;
1083   void (*J422ToARGBRow)(const uint8* y_buf,
1084                         const uint8* u_buf,
1085                         const uint8* v_buf,
1086                         uint8* rgb_buf,
1087                         int width) = J422ToARGBRow_C;
1088   if (!src_y || !src_u || !src_v ||
1089       !dst_argb ||
1090       width <= 0 || height == 0) {
1091     return -1;
1092   }
1093   // Negative height means invert the image.
1094   if (height < 0) {
1095     height = -height;
1096     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
1097     dst_stride_argb = -dst_stride_argb;
1098   }
1099   // Coalesce rows.
1100   if (src_stride_y == width &&
1101       src_stride_u * 2 == width &&
1102       src_stride_v * 2 == width &&
1103       dst_stride_argb == width * 4) {
1104     width *= height;
1105     height = 1;
1106     src_stride_y = src_stride_u = src_stride_v = dst_stride_argb = 0;
1107   }
1108 #if defined(HAS_J422TOARGBROW_SSSE3)
1109   if (TestCpuFlag(kCpuHasSSSE3)) {
1110     J422ToARGBRow = J422ToARGBRow_Any_SSSE3;
1111     if (IS_ALIGNED(width, 8)) {
1112       J422ToARGBRow = J422ToARGBRow_SSSE3;
1113     }
1114   }
1115 #endif
1116 #if defined(HAS_J422TOARGBROW_AVX2)
1117   if (TestCpuFlag(kCpuHasAVX2)) {
1118     J422ToARGBRow = J422ToARGBRow_Any_AVX2;
1119     if (IS_ALIGNED(width, 16)) {
1120       J422ToARGBRow = J422ToARGBRow_AVX2;
1121     }
1122   }
1123 #endif
1124 #if defined(HAS_J422TOARGBROW_NEON)
1125   if (TestCpuFlag(kCpuHasNEON)) {
1126     J422ToARGBRow = J422ToARGBRow_Any_NEON;
1127     if (IS_ALIGNED(width, 8)) {
1128       J422ToARGBRow = J422ToARGBRow_NEON;
1129     }
1130   }
1131 #endif
1132 #if defined(HAS_J422TOARGBROW_MIPS_DSPR2)
1133   if (TestCpuFlag(kCpuHasMIPS_DSPR2) && IS_ALIGNED(width, 4) &&
1134       IS_ALIGNED(src_y, 4) && IS_ALIGNED(src_stride_y, 4) &&
1135       IS_ALIGNED(src_u, 2) && IS_ALIGNED(src_stride_u, 2) &&
1136       IS_ALIGNED(src_v, 2) && IS_ALIGNED(src_stride_v, 2) &&
1137       IS_ALIGNED(dst_argb, 4) && IS_ALIGNED(dst_stride_argb, 4)) {
1138     J422ToARGBRow = J422ToARGBRow_MIPS_DSPR2;
1139   }
1140 #endif
1141
1142   for (y = 0; y < height; ++y) {
1143     J422ToARGBRow(src_y, src_u, src_v, dst_argb, width);
1144     dst_argb += dst_stride_argb;
1145     src_y += src_stride_y;
1146     src_u += src_stride_u;
1147     src_v += src_stride_v;
1148   }
1149   return 0;
1150 }
1151
1152 #ifdef __cplusplus
1153 }  // extern "C"
1154 }  // namespace libyuv
1155 #endif