📄 yuv2yuv.c
字号:
/* ***** BEGIN LICENSE BLOCK *****
* Version: RCSL 1.0/RPSL 1.0
*
* Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved.
*
* The contents of this file, and the files included with this file, are
* subject to the current version of the RealNetworks Public Source License
* Version 1.0 (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the RealNetworks Community Source License Version 1.0
* (the "RCSL") available at http://www.helixcommunity.org/content/rcsl,
* in which case the RCSL will apply. You may also obtain the license terms
* directly from RealNetworks. You may not use this file except in
* compliance with the RPSL or, if you have a valid RCSL with RealNetworks
* applicable to this file, the RCSL. Please see the applicable RPSL or
* RCSL for the rights, obligations and limitations governing use of the
* contents of the file.
*
* This file is part of the Helix DNA Technology. RealNetworks is the
* developer of the Original Code and owns the copyrights in the portions
* it created.
*
* This file, and the files included with this file, is distributed and made
* available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
*
* Technology Compatibility Kit Test Suite(s) Location:
* http://www.helixcommunity.org/content/tck
*
* Contributor(s):
*
* ***** END LICENSE BLOCK ***** */
/*** #includes: ********************************************/
#include "hxassert.h"
#include "env.h"
#include "yuv.h" /* YUV-to-RGB conversion tables & macros */
#include "clip.h" /* macros for clipping & dithering */
#include "hxassert.h"
#include "colorlib.h"
int PackedYUVMemcpyWithPitch( unsigned char *dest_ptr,
int dest_width, int dest_height,
int dest_pitch,
int dest_x, int dest_y, int dest_dx, int dest_dy,
unsigned char *src_ptr,
int src_width, int src_height, int src_pitch,
int src_x, int src_y, int src_dx, int src_dy);
/*** YUV to YUV color converters: **************************/
/*
* These functions were borrowed from our "old" color conversion library,
* and they do not support things like stretching or color adjustments.
* Given some more time this module should be completely rewritten.
*
***************/
static int YUY2toPlanarYUV(unsigned char *dY, unsigned char *dU, unsigned char *dV,
int dest_width, int dest_height,
int dyPitch, int duPitch, int dvPitch,
int dest_x, int dest_y, int dest_dx, int dest_dy,
unsigned char *src_ptr, int src_width, int src_height, int src_pitch,
int src_x, int src_y, int src_dx, int src_dy);
static int UYVYtoPlanarYUV(unsigned char *dY, unsigned char *dU, unsigned char *dV,
int dest_width, int dest_height,
int dyPitch, int duPitch, int dvPitch,
int dest_x, int dest_y, int dest_dx, int dest_dy,
unsigned char *src_ptr, int src_width, int src_height, int src_pitch,
int src_x, int src_y, int src_dx, int src_dy);
/*
* Checks format conversion parameters.
* Use:
* int chk_args (unsigned char *dest_ptr, int dest_width, int dest_height,
* int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
* unsigned char *src_ptr, int src_width, int src_height,
* int src_pitch, int src_x, int src_y, int src_dx, int src_dy,
* int *p_scale_x, int *p_scale_y);
* Input:
* dest_ptr - pointer to a destination buffer
* dest_width, dest_height - width/height of the destination image (pixels)
* dest_pitch - pitch of the dest. buffer (in bytes; <0 - if bottom up image)
* dest_x, dest_y, dest_dx, dest_dy - destination rectangle (pixels)
* src_ptr - pointer to an input image
* src_width, src_height - width/height of the input image (pixels)
* src_pitch - pitch of the source buffer (in bytes; <0 - if bottom up image)
* src_x, src_y, src_dx, src_dy - source rectangle (pixels)
* Output:
* p_scale_x, p_scale_y - scale factors for x,y axes
* (currently only 1:1, and 2:1 scale factors are allowed)
* Returns:
* 0 - if success; -1 if failure.
*/
static int
chk_args (unsigned char *dest_ptr, int dest_width, int dest_height,
int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
unsigned char *src_ptr, int src_width, int src_height,
int src_pitch, int src_x, int src_y, int src_dx, int src_dy,
int *p_scale_x, int *p_scale_y)
{
/* alignments: */
if (((unsigned)dest_ptr & 3) || (dest_pitch & 3) ||
((unsigned)src_ptr & 3) || (src_pitch & 3) ||
/* image sizes: */
dest_width <= 0 || dest_height <= 0 ||
src_width <= 0 || src_height <= 0 ||
/* rectangles: */
dest_x < 0 || dest_y < 0 || dest_dx <= 0 || dest_dy <= 0 ||
src_x < 0 || src_y < 0 || src_dx <= 0 || src_dy <= 0 ||
/* overlaps: */
dest_width < dest_x + dest_dx || dest_height < dest_y + dest_dy ||
src_width < src_x + src_dx || src_height < src_y + src_dy)
goto fail;
/* scale factors: */
if (dest_dx == src_dx) *p_scale_x = 1;
else if (dest_dx == 2 * src_dx) *p_scale_x = 2;
else goto fail;
if (dest_dy == src_dy) *p_scale_y = 1;
else if (dest_dy == 2 * src_dy) *p_scale_y = 2;
else goto fail;
/* success: */
return 1;
/* failure: */
fail:
return 0;
}
static int adjust_range (int *z1, int *dz1, int *z2, int *dz2, int inc2)
{
/* skip odd start pixel: */
if (*z1 & 1) {
*z1 += 1;
*dz1 -= 1;
*z2 += inc2;
*dz2 -= inc2;
}
/* clip the range: */
if (*dz1 & 1) {
*dz1 -= 1;
*dz2 -= inc2;
}
return (*dz1 > 0 && *dz2 > 0);
}
/*** "from I420" converters: *******************************/
/*
* I420toI420x() converter:
*/
int I420toI420x (unsigned char *dest_ptr, int dest_width, int dest_height,
int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
unsigned char *pY, unsigned char *pU, unsigned char *pV,
int src_width, int src_height, int yPitch, int uPitch, int vPitch,
int src_x, int src_y, int src_dx, int src_dy)
{
/* scale factors: */
int scale_x, scale_y;
/* Chroma Shifting Allowed */
int OddPattern;
/* check arguments: */
if (!chk_args (dest_ptr, dest_width, dest_height, dest_pitch,
dest_x, dest_y, dest_dx, dest_dy, pY, src_width, src_height,
yPitch, src_x, src_y, src_dx, src_dy, &scale_x, &scale_y))
return -1;
/* remove odd destination pixels: */
if (!adjust_range (&dest_x, &dest_dx, &src_x, &src_dx, scale_x) ||
!adjust_range (&dest_y, &dest_dy, &src_y, &src_dy, scale_y))
return 0;
/* check if we have matching chroma components: */
//if ((src_x & 1) || (src_y & 1))
// OddCrop= true; /* can't shift chromas */
//else
// OddCrop = false;
/* check if bottop-up images: */
if (dest_pitch <= 0 || yPitch <= 0)
return -1; /* not supported for this format */
/* check if 1:1 scale: */
if (scale_x == 1 && scale_y == 1) {
/* check if no color adjustmenst: */
if (!(is_alpha | is_beta | is_gamma | is_kappa)) {
/* no color adjustments: */
unsigned char *s, *d, *v, *s2, *v2;
int dest_uv_offs;
register int i,j;
/* copy Y plane: */
s = pY + src_x + src_y * yPitch;
d = dest_ptr + dest_x + dest_y * dest_pitch;
for (i = 0; i < dest_dy; i ++) {
memcpy (d, s, dest_dx); /* Flawfinder: ignore */
s += yPitch;
d += dest_pitch;
}
/* get Cr/Cb offsets: */
dest_uv_offs = dest_height * dest_pitch / 4;
/* copy Cr/Cb planes: */
s = pU + src_x/2 + src_y/2 * uPitch;
v = pV + src_x/2 + src_y/2 * vPitch;
d = (dest_ptr + dest_height * dest_pitch) + dest_x/2 + dest_y/2 * dest_pitch/2;
// extremely cheap way to handle 1 pel cropping
OddPattern = ((src_y & 1) << 1) | (src_x & 1);
for (i = 0; i < dest_dy/2; i++)
{
if((i+1) < dest_dy/2) {
s2 = s+uPitch;
v2 = v+vPitch;
} else {
s2 = s;
v2 = v;
}
/* convert pixels: */
switch(OddPattern)
{
case(0):
memcpy (d, s, dest_dx/2); /* Flawfinder: ignore */
memcpy (d + dest_uv_offs, v, dest_dx/2); /* Flawfinder: ignore */
//memcpy (d + dest_uv_offs, s + src_uv_offs, dest_dx/2);
break;
case(1):
for (j = 0; j < dest_dx/2 -1; j ++) {
d[j] = ((unsigned int)s[j] + (unsigned int)s[j+1] + 1)>>1;
d[j + dest_uv_offs] = ((unsigned int)v[j] + (unsigned int)v[j+1] + 1)>>1;
}
d[j] = s[j];
d[j + dest_uv_offs] = v[j];
break;
case(2):
for (j = 0; j < dest_dx/2; j ++) {
d[j] = (s[j] + s2[j] + 1)>>1;
d[j + dest_uv_offs] = ((unsigned int)v[j] + (unsigned int)v2[j] + 1)>>1;
}
break;
case(3):
for (j = 0; j < dest_dx/2 -1; j ++) {
d[j] = ((unsigned int)s[j] + (unsigned int)s[j+1] + (unsigned int)s2[j] + (unsigned int)s2[j+1] + 2)>>2;
d[j + dest_uv_offs] = ((unsigned int)v[j] + (unsigned int)v[j+1] + (unsigned int)v2[j] + (unsigned int)v2[j+1] + 2)>>2;
}
d[j] = ((unsigned int)s[j]+ (unsigned int)s2[j] + 1)>>1;
d[j + dest_uv_offs] = ((unsigned int)v[j] + (unsigned int)v2[j] + 1) >> 1;
break;
}
s += uPitch;
v += vPitch;
d += (dest_pitch/2);
}
} else {
/* adjust colors: */
unsigned char *s, *d, *v, *s2, *v2;
int dest_uv_offs;
register int i, j;
/* convert Y plane: */
s = pY + src_x + src_y * yPitch;
d = dest_ptr + dest_x + dest_y * dest_pitch;
for (i = 0; i < dest_dy; i ++) {
/* convert pixels: */
for (j = 0; j < dest_dx; j ++)
d[j] = _yytab[s[j]];
s += yPitch;
d += dest_pitch;
}
/* get Cr/Cb offsets: */
dest_uv_offs = dest_height * dest_pitch / 4;
/* get chroma pointers: */
s = pU + src_x/2 + src_y/2 * uPitch;
v = pV + src_x/2 + src_y/2 * vPitch;
d = (dest_ptr + dest_height * dest_pitch) + dest_x/2 + dest_y/2 * dest_pitch/2;
OddPattern = ((src_y & 1) << 1) | (src_x & 1);
/* check if no hue adjustment: */
if (!is_alpha) {
/* no chroma rotation: */
for (i = 0; i < dest_dy/2; i ++) {
if((i+1) < dest_dy/2) {
s2 = s+uPitch;
v2 = v+vPitch;
} else {
s2 = s;
v2 = v;
}
/* convert pixels: */
switch(OddPattern)
{
case(0):
for (j = 0; j < dest_dx/2; j ++) {
d[j] = _vvtab[s[j]];
d[j + dest_uv_offs] = _uutab[v[j]];
}
break;
case(1):
for (j = 0; j < dest_dx/2 -1; j ++) {
register unsigned int s1 = ((unsigned int)s[j] + (unsigned int)s[j+1] + 1)>>1;
register unsigned int v1 = ((unsigned int)v[j] + (unsigned int)v[j+1] + 1)>>1;
d[j] = _vvtab[s1];
d[j + dest_uv_offs] = _uutab[v1];
}
d[j] = _vvtab[s[j]];
d[j + dest_uv_offs] = _uutab[v[j]];
break;
case(2):
for (j = 0; j < dest_dx/2; j ++) {
register unsigned int s1 = ((unsigned int)s[j] + (unsigned int)s2[j] + 1)>>1;
register unsigned int v1 = ((unsigned int)v[j] + (unsigned int)v2[j] + 1)>>1;
d[j] = _vvtab[s1];
d[j + dest_uv_offs] = _uutab[v1];
}
break;
case(3):
{
register unsigned int s1, v1;
for (j = 0; j < dest_dx/2 -1; j ++) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -