Home | History | Annotate | Download | only in source
      1 /*
      2  *  Copyright (c) 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/general.h"
     12 
     13 #include <string.h>     // memcpy(), memset()
     14 
     15 #include "libyuv/planar_functions.h"
     16 
     17 namespace libyuv {
     18 
     19 int
     20 I420Mirror(const uint8* src_yplane, int src_ystride,
     21            const uint8* src_uplane, int src_ustride,
     22            const uint8* src_vplane, int src_vstride,
     23            uint8* dst_yplane, int dst_ystride,
     24            uint8* dst_uplane, int dst_ustride,
     25            uint8* dst_vplane, int dst_vstride,
     26            int width, int height) {
     27   if (src_yplane == NULL || src_uplane == NULL || src_vplane == NULL ||
     28       dst_yplane == NULL || dst_uplane == NULL || dst_vplane == NULL) {
     29     return -1;
     30   }
     31 
     32   int indO = 0;
     33   int indS  = 0;
     34   int wind, hind;
     35   uint8 tmpVal, tmpValU, tmpValV;
     36   // Will swap two values per iteration
     37   const int halfWidth = (width + 1) >> 1;
     38 
     39   // Y
     40   for (wind = 0; wind < halfWidth; wind++) {
     41    for (hind = 0; hind < height; hind++) {
     42      indO = hind * src_ystride + wind;
     43      indS = hind * dst_ystride + (width - wind - 1);
     44      tmpVal = src_yplane[indO];
     45      dst_yplane[indO] = src_yplane[indS];
     46      dst_yplane[indS] = tmpVal;
     47     }
     48   }
     49 
     50   const int halfHeight = (height + 1) >> 1;
     51   const int halfSrcuvStride = (height + 1) >> 1;
     52   const int halfuvWidth = (width + 1) >> 2;
     53 
     54   for (wind = 0; wind < halfuvWidth; wind++) {
     55    for (hind = 0; hind < halfHeight; hind++) {
     56      indO = hind * halfSrcuvStride + wind;
     57      indS = hind * halfSrcuvStride + (halfuvWidth - wind - 1);
     58      // U
     59      tmpValU = src_uplane[indO];
     60      dst_uplane[indO] = src_uplane[indS];
     61      dst_uplane[indS] = tmpValU;
     62      // V
     63      tmpValV = src_vplane[indO];
     64      dst_vplane[indO] = src_vplane[indS];
     65      dst_vplane[indS] = tmpValV;
     66    }
     67   }
     68   return 0;
     69 }
     70 
     71 // Make a center cut
     72 int
     73 I420Crop(uint8* frame,
     74          int src_width, int src_height,
     75          int dst_width, int dst_height)
     76 {
     77   if (frame == NULL)
     78     return -1;
     79 
     80   if (src_width == dst_width && src_height == dst_height) {
     81       // Nothing to do
     82     return 3 * dst_height * dst_width / 2;
     83   }
     84   if (dst_width > src_width || dst_height > src_height) {
     85       // error
     86       return -1;
     87   }
     88   int i = 0;
     89   int m = 0;
     90   int loop = 0;
     91   int half_dst_width = dst_width / 2;
     92   int halfdst_height = dst_height / 2;
     93   int halfsrc_width = src_width / 2;
     94   int half_dst_height= src_height / 2;
     95   int crop_height = ( src_height - dst_height ) / 2;
     96   int crop_width = ( src_width - dst_width ) / 2;
     97 
     98   for (i = src_width * crop_height + crop_width; loop < dst_height ;
     99       loop++, i += src_width) {
    100     memcpy(&frame[m],&frame[i],dst_width);
    101     m += dst_width;
    102   }
    103   i = src_width * src_height; // ilum
    104   loop = 0;
    105   for ( i += (halfsrc_width * crop_height / 2 + crop_width / 2);
    106         loop < halfdst_height; loop++,i += halfsrc_width) {
    107     memcpy(&frame[m],&frame[i],half_dst_width);
    108     m += half_dst_width;
    109   }
    110   loop = 0;
    111   i = src_width * src_height + half_dst_height * halfsrc_width; // ilum + Cr
    112   for ( i += (halfsrc_width * crop_height / 2 + crop_width / 2);
    113         loop < halfdst_height; loop++, i += halfsrc_width) {
    114     memcpy(&frame[m],&frame[i],half_dst_width);
    115     m += half_dst_width;
    116   }
    117   return 0;
    118 }
    119 
    120 
    121 int
    122 I420CropPad(const uint8* src_frame, int src_width,
    123             int src_height, uint8* dst_frame,
    124             int dst_width, int dst_height)
    125 {
    126   if (src_width < 1 || dst_width < 1 || src_height < 1 || dst_height < 1) {
    127     return -1;
    128   }
    129   if (src_width == dst_width && src_height == dst_height) {
    130     memcpy(dst_frame, src_frame, 3 * dst_width * (dst_height >> 1));
    131   } else {
    132     if (src_height < dst_height) {
    133       // pad height
    134       int pad_height = dst_height - src_height;
    135       int i = 0;
    136       int pad_width = 0;
    137       int crop_width = 0;
    138       int width = src_width;
    139       if (src_width < dst_width) {
    140         // pad width
    141         pad_width = dst_width - src_width;
    142       } else {
    143         // cut width
    144         crop_width = src_width - dst_width;
    145         width = dst_width;
    146       }
    147       if (pad_height) {
    148         memset(dst_frame, 0, dst_width * (pad_height >> 1));
    149         dst_frame +=  dst_width * (pad_height >> 1);
    150       }
    151       for (i = 0; i < src_height;i++) {
    152         if (pad_width) {
    153             memset(dst_frame, 0, pad_width / 2);
    154             dst_frame +=  pad_width / 2;
    155         }
    156         src_frame += crop_width >> 1; // in case we have a cut
    157         memcpy(dst_frame,src_frame ,width);
    158         src_frame += crop_width >> 1;
    159         dst_frame += width;
    160         src_frame += width;
    161         if (pad_width) {
    162           memset(dst_frame, 0, pad_width / 2);
    163           dst_frame +=  pad_width / 2;
    164         }
    165       }
    166       if (pad_height) {
    167         memset(dst_frame, 0, dst_width * (pad_height >> 1));
    168         dst_frame +=  dst_width * (pad_height >> 1);
    169       }
    170       if (pad_height) {
    171         memset(dst_frame, 127, (dst_width >> 2) * (pad_height >> 1));
    172         dst_frame +=  (dst_width >> 2) * (pad_height >> 1);
    173       }
    174       for (i = 0; i < (src_height >> 1); i++) {
    175         if (pad_width) {
    176           memset(dst_frame, 127, pad_width >> 2);
    177           dst_frame +=  pad_width >> 2;
    178         }
    179         src_frame += crop_width >> 2; // in case we have a cut
    180         memcpy(dst_frame, src_frame,width >> 1);
    181         src_frame += crop_width >> 2;
    182         dst_frame += width >> 1;
    183         src_frame += width >> 1;
    184         if (pad_width) {
    185           memset(dst_frame, 127, pad_width >> 2);
    186           dst_frame +=  pad_width >> 2;
    187         }
    188       }
    189       if (pad_height) {
    190         memset(dst_frame, 127, (dst_width >> 1) * (pad_height >> 1));
    191         dst_frame +=  (dst_width >> 1) * (pad_height >> 1);
    192       }
    193       for (i = 0; i < (src_height >> 1); i++) {
    194         if (pad_width) {
    195           memset(dst_frame, 127, pad_width >> 2);
    196           dst_frame +=  pad_width >> 2;
    197         }
    198         src_frame += crop_width >> 2; // in case we have a cut
    199         memcpy(dst_frame, src_frame,width >> 1);
    200         src_frame += crop_width >> 2;
    201         dst_frame += width >> 1;
    202         src_frame += width >> 1;
    203         if (pad_width) {
    204           memset(dst_frame, 127, pad_width >> 2);
    205           dst_frame += pad_width >> 2;
    206         }
    207       }
    208       if (pad_height) {
    209         memset(dst_frame, 127, (dst_width >> 2) * (pad_height >> 1));
    210         dst_frame +=  (dst_width >> 2) * (pad_height >> 1);
    211       }
    212     } else {
    213       // cut height
    214       int i = 0;
    215       int pad_width = 0;
    216       int crop_width = 0;
    217       int width = src_width;
    218 
    219       if (src_width < dst_width) {
    220         // pad width
    221         pad_width = dst_width - src_width;
    222       } else {
    223         // cut width
    224         crop_width = src_width - dst_width;
    225         width = dst_width;
    226       }
    227       int diff_height = src_height - dst_height;
    228       src_frame += src_width * (diff_height >> 1);  // skip top I
    229 
    230       for (i = 0; i < dst_height; i++) {
    231         if (pad_width) {
    232           memset(dst_frame, 0, pad_width / 2);
    233           dst_frame +=  pad_width / 2;
    234         }
    235         src_frame += crop_width >> 1; // in case we have a cut
    236         memcpy(dst_frame,src_frame ,width);
    237         src_frame += crop_width >> 1;
    238         dst_frame += width;
    239         src_frame += width;
    240         if (pad_width) {
    241           memset(dst_frame, 0, pad_width / 2);
    242           dst_frame +=  pad_width / 2;
    243         }
    244       }
    245       src_frame += src_width * (diff_height >> 1);  // skip end I
    246       src_frame += (src_width >> 2) * (diff_height >> 1); // skip top of Cr
    247       for (i = 0; i < (dst_height >> 1); i++) {
    248         if (pad_width) {
    249           memset(dst_frame, 127, pad_width >> 2);
    250           dst_frame +=  pad_width >> 2;
    251         }
    252         src_frame += crop_width >> 2; // in case we have a cut
    253         memcpy(dst_frame, src_frame,width >> 1);
    254         src_frame += crop_width >> 2;
    255         dst_frame += width >> 1;
    256         src_frame += width >> 1;
    257         if (pad_width) {
    258           memset(dst_frame, 127, pad_width >> 2);
    259           dst_frame +=  pad_width >> 2;
    260         }
    261       }
    262       src_frame += (src_width >> 2) * (diff_height >> 1); // skip end of Cr
    263       src_frame += (src_width >> 2) * (diff_height >> 1); // skip top of Cb
    264       for (i = 0; i < (dst_height >> 1); i++) {
    265         if (pad_width) {
    266           memset(dst_frame, 127, pad_width >> 2);
    267           dst_frame +=  pad_width >> 2;
    268         }
    269         src_frame += crop_width >> 2; // in case we have a cut
    270         memcpy(dst_frame, src_frame, width >> 1);
    271         src_frame += crop_width >> 2;
    272         dst_frame += width >> 1;
    273         src_frame += width >> 1;
    274         if (pad_width) {
    275           memset(dst_frame, 127, pad_width >> 2);
    276           dst_frame +=  pad_width >> 2;
    277         }
    278       }
    279     }
    280   }
    281   return 0;
    282 }
    283 
    284 } // namespace libyuv
    285