⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 image.c

📁 用MPEG-4对YUV视频文件编码压缩成divx视频文件
💻 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 + -