| /* |
| * Copyright (c) 2011 The LibYuv project authors. All Rights Reserved. |
| * |
| * Use of this source code is governed by a BSD-style license |
| * that can be found in the LICENSE file in the root of the source |
| * tree. An additional intellectual property rights grant can be found |
| * in the file PATENTS. All contributing project authors may |
| * be found in the AUTHORS file in the root of the source tree. |
| */ |
| |
| #include "libyuv/general.h" |
| |
| #include <string.h> // memcpy(), memset() |
| |
| #include "libyuv/planar_functions.h" |
| |
| namespace libyuv { |
| |
| int |
| I420Mirror(const uint8* src_yplane, int src_ystride, |
| const uint8* src_uplane, int src_ustride, |
| const uint8* src_vplane, int src_vstride, |
| uint8* dst_yplane, int dst_ystride, |
| uint8* dst_uplane, int dst_ustride, |
| uint8* dst_vplane, int dst_vstride, |
| int width, int height) { |
| if (src_yplane == NULL || src_uplane == NULL || src_vplane == NULL || |
| dst_yplane == NULL || dst_uplane == NULL || dst_vplane == NULL) { |
| return -1; |
| } |
| |
| int indO = 0; |
| int indS = 0; |
| int wind, hind; |
| uint8 tmpVal, tmpValU, tmpValV; |
| // Will swap two values per iteration |
| const int halfWidth = (width + 1) >> 1; |
| |
| // Y |
| for (wind = 0; wind < halfWidth; wind++) { |
| for (hind = 0; hind < height; hind++) { |
| indO = hind * src_ystride + wind; |
| indS = hind * dst_ystride + (width - wind - 1); |
| tmpVal = src_yplane[indO]; |
| dst_yplane[indO] = src_yplane[indS]; |
| dst_yplane[indS] = tmpVal; |
| } |
| } |
| |
| const int halfHeight = (height + 1) >> 1; |
| const int halfSrcuvStride = (height + 1) >> 1; |
| const int halfuvWidth = (width + 1) >> 2; |
| |
| for (wind = 0; wind < halfuvWidth; wind++) { |
| for (hind = 0; hind < halfHeight; hind++) { |
| indO = hind * halfSrcuvStride + wind; |
| indS = hind * halfSrcuvStride + (halfuvWidth - wind - 1); |
| // U |
| tmpValU = src_uplane[indO]; |
| dst_uplane[indO] = src_uplane[indS]; |
| dst_uplane[indS] = tmpValU; |
| // V |
| tmpValV = src_vplane[indO]; |
| dst_vplane[indO] = src_vplane[indS]; |
| dst_vplane[indS] = tmpValV; |
| } |
| } |
| return 0; |
| } |
| |
| // Make a center cut |
| int |
| I420Crop(uint8* frame, |
| int src_width, int src_height, |
| int dst_width, int dst_height) |
| { |
| if (frame == NULL) |
| return -1; |
| |
| if (src_width == dst_width && src_height == dst_height) { |
| // Nothing to do |
| return 3 * dst_height * dst_width / 2; |
| } |
| if (dst_width > src_width || dst_height > src_height) { |
| // error |
| return -1; |
| } |
| int i = 0; |
| int m = 0; |
| int loop = 0; |
| int half_dst_width = dst_width / 2; |
| int halfdst_height = dst_height / 2; |
| int halfsrc_width = src_width / 2; |
| int half_dst_height= src_height / 2; |
| int crop_height = ( src_height - dst_height ) / 2; |
| int crop_width = ( src_width - dst_width ) / 2; |
| |
| for (i = src_width * crop_height + crop_width; loop < dst_height ; |
| loop++, i += src_width) { |
| memcpy(&frame[m],&frame[i],dst_width); |
| m += dst_width; |
| } |
| i = src_width * src_height; // ilum |
| loop = 0; |
| for ( i += (halfsrc_width * crop_height / 2 + crop_width / 2); |
| loop < halfdst_height; loop++,i += halfsrc_width) { |
| memcpy(&frame[m],&frame[i],half_dst_width); |
| m += half_dst_width; |
| } |
| loop = 0; |
| i = src_width * src_height + half_dst_height * halfsrc_width; // ilum + Cr |
| for ( i += (halfsrc_width * crop_height / 2 + crop_width / 2); |
| loop < halfdst_height; loop++, i += halfsrc_width) { |
| memcpy(&frame[m],&frame[i],half_dst_width); |
| m += half_dst_width; |
| } |
| return 0; |
| } |
| |
| |
| int |
| I420CropPad(const uint8* src_frame, int src_width, |
| int src_height, uint8* dst_frame, |
| int dst_width, int dst_height) |
| { |
| if (src_width < 1 || dst_width < 1 || src_height < 1 || dst_height < 1) { |
| return -1; |
| } |
| if (src_width == dst_width && src_height == dst_height) { |
| memcpy(dst_frame, src_frame, 3 * dst_width * (dst_height >> 1)); |
| } else { |
| if (src_height < dst_height) { |
| // pad height |
| int pad_height = dst_height - src_height; |
| int i = 0; |
| int pad_width = 0; |
| int crop_width = 0; |
| int width = src_width; |
| if (src_width < dst_width) { |
| // pad width |
| pad_width = dst_width - src_width; |
| } else { |
| // cut width |
| crop_width = src_width - dst_width; |
| width = dst_width; |
| } |
| if (pad_height) { |
| memset(dst_frame, 0, dst_width * (pad_height >> 1)); |
| dst_frame += dst_width * (pad_height >> 1); |
| } |
| for (i = 0; i < src_height;i++) { |
| if (pad_width) { |
| memset(dst_frame, 0, pad_width / 2); |
| dst_frame += pad_width / 2; |
| } |
| src_frame += crop_width >> 1; // in case we have a cut |
| memcpy(dst_frame,src_frame ,width); |
| src_frame += crop_width >> 1; |
| dst_frame += width; |
| src_frame += width; |
| if (pad_width) { |
| memset(dst_frame, 0, pad_width / 2); |
| dst_frame += pad_width / 2; |
| } |
| } |
| if (pad_height) { |
| memset(dst_frame, 0, dst_width * (pad_height >> 1)); |
| dst_frame += dst_width * (pad_height >> 1); |
| } |
| if (pad_height) { |
| memset(dst_frame, 127, (dst_width >> 2) * (pad_height >> 1)); |
| dst_frame += (dst_width >> 2) * (pad_height >> 1); |
| } |
| for (i = 0; i < (src_height >> 1); i++) { |
| if (pad_width) { |
| memset(dst_frame, 127, pad_width >> 2); |
| dst_frame += pad_width >> 2; |
| } |
| src_frame += crop_width >> 2; // in case we have a cut |
| memcpy(dst_frame, src_frame,width >> 1); |
| src_frame += crop_width >> 2; |
| dst_frame += width >> 1; |
| src_frame += width >> 1; |
| if (pad_width) { |
| memset(dst_frame, 127, pad_width >> 2); |
| dst_frame += pad_width >> 2; |
| } |
| } |
| if (pad_height) { |
| memset(dst_frame, 127, (dst_width >> 1) * (pad_height >> 1)); |
| dst_frame += (dst_width >> 1) * (pad_height >> 1); |
| } |
| for (i = 0; i < (src_height >> 1); i++) { |
| if (pad_width) { |
| memset(dst_frame, 127, pad_width >> 2); |
| dst_frame += pad_width >> 2; |
| } |
| src_frame += crop_width >> 2; // in case we have a cut |
| memcpy(dst_frame, src_frame,width >> 1); |
| src_frame += crop_width >> 2; |
| dst_frame += width >> 1; |
| src_frame += width >> 1; |
| if (pad_width) { |
| memset(dst_frame, 127, pad_width >> 2); |
| dst_frame += pad_width >> 2; |
| } |
| } |
| if (pad_height) { |
| memset(dst_frame, 127, (dst_width >> 2) * (pad_height >> 1)); |
| dst_frame += (dst_width >> 2) * (pad_height >> 1); |
| } |
| } else { |
| // cut height |
| int i = 0; |
| int pad_width = 0; |
| int crop_width = 0; |
| int width = src_width; |
| |
| if (src_width < dst_width) { |
| // pad width |
| pad_width = dst_width - src_width; |
| } else { |
| // cut width |
| crop_width = src_width - dst_width; |
| width = dst_width; |
| } |
| int diff_height = src_height - dst_height; |
| src_frame += src_width * (diff_height >> 1); // skip top I |
| |
| for (i = 0; i < dst_height; i++) { |
| if (pad_width) { |
| memset(dst_frame, 0, pad_width / 2); |
| dst_frame += pad_width / 2; |
| } |
| src_frame += crop_width >> 1; // in case we have a cut |
| memcpy(dst_frame,src_frame ,width); |
| src_frame += crop_width >> 1; |
| dst_frame += width; |
| src_frame += width; |
| if (pad_width) { |
| memset(dst_frame, 0, pad_width / 2); |
| dst_frame += pad_width / 2; |
| } |
| } |
| src_frame += src_width * (diff_height >> 1); // skip end I |
| src_frame += (src_width >> 2) * (diff_height >> 1); // skip top of Cr |
| for (i = 0; i < (dst_height >> 1); i++) { |
| if (pad_width) { |
| memset(dst_frame, 127, pad_width >> 2); |
| dst_frame += pad_width >> 2; |
| } |
| src_frame += crop_width >> 2; // in case we have a cut |
| memcpy(dst_frame, src_frame,width >> 1); |
| src_frame += crop_width >> 2; |
| dst_frame += width >> 1; |
| src_frame += width >> 1; |
| if (pad_width) { |
| memset(dst_frame, 127, pad_width >> 2); |
| dst_frame += pad_width >> 2; |
| } |
| } |
| src_frame += (src_width >> 2) * (diff_height >> 1); // skip end of Cr |
| src_frame += (src_width >> 2) * (diff_height >> 1); // skip top of Cb |
| for (i = 0; i < (dst_height >> 1); i++) { |
| if (pad_width) { |
| memset(dst_frame, 127, pad_width >> 2); |
| dst_frame += pad_width >> 2; |
| } |
| src_frame += crop_width >> 2; // in case we have a cut |
| memcpy(dst_frame, src_frame, width >> 1); |
| src_frame += crop_width >> 2; |
| dst_frame += width >> 1; |
| src_frame += width >> 1; |
| if (pad_width) { |
| memset(dst_frame, 127, pad_width >> 2); |
| dst_frame += pad_width >> 2; |
| } |
| } |
| } |
| } |
| return 0; |
| } |
| |
| } // namespace libyuv |