📄 image.c
字号:
/**************************************************************************
*
* XVID MPEG-4 VIDEO CODEC
* image stuff
*
* This program is an implementation of a part of one or more MPEG-4
* Video tools as specified in ISO/IEC 14496-2 standard. Those intending
* to use this software module in hardware or software products are
* advised that its use may infringe existing patents or copyrights, and
* any such use would be at such party's own risk. The original
* developer of this software module and his/her company, and subsequent
* editors and their companies, will have no liability for use of this
* software or modifications or derivatives thereof.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*************************************************************************/
/**************************************************************************
*
* History:
*
* 01.05.2002 BFRAME image-based u,v interpolation
* 22.04.2002 added some B-frame support
* 14.04.2002 added image_dump_yuvpgm(), added image_mad()
* XVID_CSP_USER input support
* 09.04.2002 PSNR calculations
* 06.04.2002 removed interlaced edging from U,V blocks (as per spec)
* 26.03.2002 interlacing support (field-based edging in set_edges)
* 26.01.2002 rgb555, rgb565
* 07.01.2001 commented u,v interpolation (not required for uv-block-based)
* 23.12.2001 removed #ifdefs, added function pointers + init_common()
* 22.12.2001 cpu #ifdefs
* 19.12.2001 image_dump(); useful for debugging
* 6.12.2001 inital version; (c)2001 peter ross <pross@cs.rmit.edu.au>
*
*************************************************************************/
#include <stdlib.h>
#include <string.h> /* memcpy, memset*/
#include <math.h>
#include "../portab.h"
#include "../xvid.h" /* XVID_CSP_XXX's */
#include "image.h"
/*#include "colorspace.h"*/
#include "interpolate8x8.h"
/*#include "../divx4.h"*/
#include "../utils/mem_align.h"
#define SAFETY 64
#define EDGE_SIZE2 (EDGE_SIZE/2)
/*
create image buffer for edged padding image
Add by fyh 2002.12.26
*/
int32_t
image_create(IMAGE * image,
uint32_t edged_width,
uint32_t edged_height)
{
const uint32_t edged_width2 = edged_width / 2;/* chrominance component width */
const uint32_t edged_height2 = edged_height / 2;/* chrominance component heigth */
uint32_t i;
/* alloc luminance component buffer */
image->y =
xvid_malloc(edged_width * (edged_height + 1) + SAFETY, CACHE_LINE);
if (image->y == NULL) {
return -1;
}
/* Initialize luminance component buffer by use zero */
for (i = 0; i < edged_width * edged_height + SAFETY; i++) {
image->y[i] = 0;
}
/* alloc U component buffer */
image->u = xvid_malloc(edged_width2 * edged_height2 + SAFETY, CACHE_LINE);
if (image->u == NULL) {
xvid_free(image->y);
return -1;
}
/* alloc V component buffer */
image->v = xvid_malloc(edged_width2 * edged_height2 + SAFETY, CACHE_LINE);
if (image->v == NULL) {
xvid_free(image->u);
xvid_free(image->y);
return -1;
}
/* adjust image buffer pointer to point to start address of image buffer that has not edge padding */
image->y += EDGE_SIZE * edged_width + EDGE_SIZE;
image->u += EDGE_SIZE2 * edged_width2 + EDGE_SIZE2;
image->v += EDGE_SIZE2 * edged_width2 + EDGE_SIZE2;
return 0;/* normal exit */
}
/*
destory image buffer that is alloced by image_create function.
Add by fyh 2002.12.26
*/
void
image_destroy(IMAGE * image,
uint32_t edged_width,
uint32_t edged_height)
{
const uint32_t edged_width2 = edged_width / 2;
/* destroy luminance component buffer */
if (image->y) {
xvid_free(image->y - (EDGE_SIZE * edged_width + EDGE_SIZE));
}
/* destroy U component buffer */
if (image->u) {
xvid_free(image->u - (EDGE_SIZE2 * edged_width2 + EDGE_SIZE2));
}
/* destroy V component buffer */
if (image->v) {
xvid_free(image->v - (EDGE_SIZE2 * edged_width2 + EDGE_SIZE2));
}
}
/*
Two image buffers swapping.
Add by fyh 2002.12.26
*/
void
image_swap(IMAGE * image1,
IMAGE * image2)
{
uint8_t *tmp;
/* swapping Y component */
tmp = image1->y;
image1->y = image2->y;
image2->y = tmp;
/* swapping U component */
tmp = image1->u;
image1->u = image2->u;
image2->u = tmp;
/* swapping V component */
tmp = image1->v;
image1->v = image2->v;
image2->v = tmp;
}
#ifdef _DEBUG_PSNR
void
image_copy(IMAGE * image1,
IMAGE * image2,
uint32_t edged_width,
uint32_t height)
{
memcpy(image1->y, image2->y, edged_width * height);
memcpy(image1->u, image2->u, edged_width * height / 4);
memcpy(image1->v, image2->v, edged_width * height / 4);
}
/*
float
image_psnr(IMAGE * orig_image,
IMAGE * recon_image,
uint16_t stride,
uint16_t width,
uint16_t height)
*/
float
image_psnr(IMAGE * orig_image,
IMAGE * recon_image,
int stride,
int width,
int height)
{
int32_t diff, x, y, quad = 0;
uint8_t *orig = orig_image->y;
uint8_t *recon = recon_image->y;
float psnr_y;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
diff = *(orig + x) - *(recon + x);
quad += diff * diff;
}
orig += stride;
recon += stride;
}
psnr_y = (float) quad / (float) (width * height);
if (psnr_y) {
psnr_y = (float) (255 * 255) / psnr_y;
psnr_y = 10 * (float) log10(psnr_y);
} else
psnr_y = (float) 99.99;
return psnr_y;
}
#endif
/*
void
image_setedges(IMAGE * image,
uint32_t edged_width,
uint32_t edged_height,
uint32_t width,
uint32_t height,
uint32_t interlacing)
*/
/*
image edge padding(Y/U/V component)
Add by fyh.2002/12/26
*/
void
image_setedges(IMAGE * image,/* image buffer */
uint32_t edged_width,/* width for edged image */
uint32_t edged_height,/* heigth for edged image */
uint32_t width,/* width for edged imaged */
uint32_t height)/* heigth for edged image */
{
const uint32_t edged_width2 = edged_width / 2;/* chrominance component width of edged image*/
const uint32_t width2 = width / 2;/* chrominance component width of source image*/
uint32_t i;
uint8_t *dst;/* edged image */
uint8_t *src;/* source image */
/* luminance component edge padding */
dst = image->y - (EDGE_SIZE + EDGE_SIZE * edged_width);/* edged image lefttop pixel */
src = image->y;/* source image lefttop pixel */
/* vertical padding(top EDGE_SIZE rows) */
for (i = 0; i < EDGE_SIZE; i++) {
/* if interlacing, edges contain top-most data from each field*/
/* if (interlacing && (i & 1)) {
memset(dst, *(src + edged_width), EDGE_SIZE);
memcpy(dst + EDGE_SIZE, src + edged_width, width);
memset(dst + edged_width - EDGE_SIZE,
*(src + edged_width + width - 1), EDGE_SIZE);
} else {*/
memset(dst, *src, EDGE_SIZE);/* left */
memcpy(dst + EDGE_SIZE, src, width);/* middle */
memset(dst + edged_width - EDGE_SIZE, *(src + width - 1),
EDGE_SIZE);/* right */
/*}*/
dst += edged_width;
}
/* horizontal padding(height rows) */
for (i = 0; i < height; i++) {
memset(dst, *src, EDGE_SIZE);/* left */
memset(dst + edged_width - EDGE_SIZE, src[width - 1], EDGE_SIZE);/* right */
dst += edged_width;
src += edged_width;
}
/* vertical padding(below EDGE_SIZE rows) */
src -= edged_width;
for (i = 0; i < EDGE_SIZE; i++) {
/* if interlacing, edges contain bottom-most data from each field */
/* if (interlacing && !(i & 1)) {
memset(dst, *(src - edged_width), EDGE_SIZE);
memcpy(dst + EDGE_SIZE, src - edged_width, width);
memset(dst + edged_width - EDGE_SIZE,
*(src - edged_width + width - 1), EDGE_SIZE);
} else {*/
memset(dst, *src, EDGE_SIZE);/* left */
memcpy(dst + EDGE_SIZE, src, width);/* middle */
memset(dst + edged_width - EDGE_SIZE, *(src + width - 1),
EDGE_SIZE);/* right */
/*}*/
dst += edged_width;
}
/* U component edge padding */
dst = image->u - (EDGE_SIZE2 + EDGE_SIZE2 * edged_width2);
src = image->u;
/* vertical padding(top EDGE_SIZE2 rows) */
for (i = 0; i < EDGE_SIZE2; i++) {
memset(dst, *src, EDGE_SIZE2);/* left */
memcpy(dst + EDGE_SIZE2, src, width2);/* middle */
memset(dst + edged_width2 - EDGE_SIZE2, *(src + width2 - 1),
EDGE_SIZE2);/* right */
dst += edged_width2;
}
/* horizontal padding(height/2 rows) */
for (i = 0; i < height / 2; i++) {
memset(dst, *src, EDGE_SIZE2);/* left */
memset(dst + edged_width2 - EDGE_SIZE2, src[width2 - 1], EDGE_SIZE2);/* right */
dst += edged_width2;
src += edged_width2;
}
/* vertical padding(below EDGE_SIZE2 rows) */
src -= edged_width2;
for (i = 0; i < EDGE_SIZE2; i++) {
memset(dst, *src, EDGE_SIZE2);/* left */
memcpy(dst + EDGE_SIZE2, src, width2);/* middle */
memset(dst + edged_width2 - EDGE_SIZE2, *(src + width2 - 1),
EDGE_SIZE2);/* right */
dst += edged_width2;
}
/* U component edge padding */
dst = image->v - (EDGE_SIZE2 + EDGE_SIZE2 * edged_width2);
src = image->v;
/* vertical padding(top EDGE_SIZE2 rows) */
for (i = 0; i < EDGE_SIZE2; i++) {
memset(dst, *src, EDGE_SIZE2);/* left */
memcpy(dst + EDGE_SIZE2, src, width2);/* middle */
memset(dst + edged_width2 - EDGE_SIZE2, *(src + width2 - 1),
EDGE_SIZE2);/* right */
dst += edged_width2;
}
/* horizontal padding(height/2 rows) */
for (i = 0; i < height / 2; i++) {
memset(dst, *src, EDGE_SIZE2);/* left */
memset(dst + edged_width2 - EDGE_SIZE2, src[width2 - 1], EDGE_SIZE2);/* right */
dst += edged_width2;
src += edged_width2;
}
/* vertical padding(below EDGE_SIZE2 rows) */
src -= edged_width2;
for (i = 0; i < EDGE_SIZE2; i++) {
memset(dst, *src, EDGE_SIZE2);/* left */
memcpy(dst + EDGE_SIZE2, src, width2);/* middle */
memset(dst + edged_width2 - EDGE_SIZE2, *(src + width2 - 1),
EDGE_SIZE2);/* right */
dst += edged_width2;
}
}
/*
image luminance component half pixel interpolate
Add by fyh 2002/12/26
*/
void
image_interpolate(const IMAGE * refn,/* integer pixel image */
IMAGE * refh,/* horizontal half pixel interpolate image */
IMAGE * refv,/* vertical half pixel interpolate image */
IMAGE * refhv,/* horizontal and vertical half pixel interpolate image */
uint32_t edged_width,/* image width */
uint32_t edged_height,/* image height */
uint32_t rounding)/* rounding bit(0 or 1) */
{
const uint32_t offset = EDGE_SIZE * (edged_width + 1);/* offset from first pixel of edged image to first pixel of no edged padding image */
const uint32_t stride_add = 7 * edged_width;/* 8 row data offset */
uint8_t *n_ptr, *h_ptr, *v_ptr, *hv_ptr;
uint32_t x, y;
/*
get luminance component buffer pointer that point to
start address of image buffer that has not edge padding
*/
n_ptr = refn->y;
h_ptr = refh->y;
v_ptr = refv->y;
hv_ptr = refhv->y;
/*
adjust buffer pointer that point to
start address of image buffer that has edge padding
*/
n_ptr -= offset;
h_ptr -= offset;
v_ptr -= offset;
hv_ptr -= offset;
for (y = 0; y < edged_height; y = y + 8) {
for (x = 0; x < edged_width; x = x + 8) {
/* process 8x8 block interpolation */
interpolate8x8_halfpel_h(h_ptr, n_ptr, edged_width, rounding);
interpolate8x8_halfpel_v(v_ptr, n_ptr, edged_width, rounding);
interpolate8x8_halfpel_hv(hv_ptr, n_ptr, edged_width, rounding);
n_ptr += 8;
h_ptr += 8;
v_ptr += 8;
hv_ptr += 8;
}
h_ptr += stride_add;
v_ptr += stride_add;
hv_ptr += stride_add;
n_ptr += stride_add;
}
}
/*
del csp argument (by fyh)
*/
/*
int
image_input(IMAGE * image,
uint32_t width,
int height,
uint32_t edged_width,
uint8_t * src,
int csp)
*/
/*
Input image format convert.
Now, copy a image from small buffer to big buffer
Add by fyh, 2002.12.26
*/
void image_input(IMAGE * image,/* output image pointer */
uint32_t width,/* input image width */
int height,/* input image heigth */
uint32_t edged_width,/* output image width */
uint8_t * src)/* input image pointer */
{
uint32_t stride = edged_width;/* image buffer row length */
uint32_t stride2 = stride >> 1;
uint32_t width2 = width >> 1;
uint8_t * y_out=image->y;/* output image buffer poniter */
uint8_t * u_out=image->u;
uint8_t * v_out=image->v;
uint32_t y;
/* Y component copy */
for (y = height; y; y--) {
memcpy(y_out, src, width);
src += width;
y_out += stride;
}
/* U component copy */
for (y = height >> 1; y; y--) {
memcpy(u_out, src, width2);
src += width2;
u_out += stride2;
}
/* V component copy */
for (y = height >> 1; y; y--) {
memcpy(v_out, src, width2);
src += width2;
v_out += stride2;
}
}
#ifdef _OUT_CONSTRUCT_IMAGE
static __inline void
yv12_to_yuv(uint8_t * dst,
int dst_stride,
uint8_t * y_src,
uint8_t * u_src,
uint8_t * v_src,
int y_stride,
int uv_stride,
int width,
int height)
{
uint32_t dst_stride2 = dst_stride >> 1;
uint32_t width2 = width >> 1;
uint32_t y;
if (height < 0) {
height = -height;
y_src += (height - 1) * y_stride;
u_src += (height / 2 - 1) * uv_stride;
v_src += (height / 2 - 1) * uv_stride;
y_stride = -y_stride;
uv_stride = -uv_stride;
}
for (y = height; y; y--) {
memcpy(dst, y_src, width);
dst += dst_stride;
y_src += y_stride;
}
for (y = height >> 1; y; y--) {
memcpy(dst, u_src, width2);
dst += dst_stride2;
u_src += uv_stride;
}
for (y = height >> 1; y; y--) {
memcpy(dst, v_src, width2);
dst += dst_stride2;
v_src += uv_stride;
}
}
/*
int
image_output(IMAGE * image,
uint32_t width,
int height,
uint32_t edged_width,
uint8_t * dst,
uint32_t dst_stride,
int csp)
*/
void
image_output(IMAGE * image,
uint32_t width,
int height,
uint32_t edged_width,
uint8_t * dst,
uint32_t dst_stride)
{
yv12_to_yuv(dst, dst_stride, image->y, image->u, image->v, edged_width,
edged_width / 2, width, height);
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -