📄 image.c
字号:
if (width & 15)
{
int i;
int pad_width = 16 - (width&15);
for (i = 0; i < height; i++)
{
memset(image->y + i*edged_width + width,
*(image->y + i*edged_width + width - 1), pad_width);
}
for (i = 0; i < height/2; i++)
{
memset(image->u + i*edged_width2 + width2,
*(image->u + i*edged_width2 + width2 - 1),pad_width/2);
memset(image->v + i*edged_width2 + width2,
*(image->v + i*edged_width2 + width2 - 1),pad_width/2);
}
}
if (height & 15)
{
int pad_height = 16 - (height&15);
int length = ((width+15)/16)*16;
int i;
for (i = 0; i < pad_height; i++)
{
memcpy(image->y + (height+i)*edged_width,
image->y + (height-1)*edged_width,length);
}
for (i = 0; i < pad_height/2; i++)
{
memcpy(image->u + (height2+i)*edged_width2,
image->u + (height2-1)*edged_width2,length/2);
memcpy(image->v + (height2+i)*edged_width2,
image->v + (height2-1)*edged_width2,length/2);
}
}
/*
if (interlacing)
image_printf(image, edged_width, height, 5,5, "[i]");
image_dump_yuvpgm(image, edged_width, ((width+15)/16)*16, ((height+15)/16)*16, "\\encode.pgm");
*/
return 0;
}
int
image_output(IMAGE * image,
uint32_t width,
int height,
uint32_t edged_width,
uint8_t * dst[4],
int dst_stride[4],
int csp,
int interlacing)
{
const int edged_width2 = edged_width/2;
int height2 = height/2;
/*
if (interlacing)
image_printf(image, edged_width, height, 5,100, "[i]=%i,%i",width,height);
image_dump_yuvpgm(image, edged_width, width, height, "\\decode.pgm");
*/
switch (csp & ~XVID_CSP_VFLIP) {
case XVID_CSP_RGB555:
safe_packed_conv(
dst[0], dst_stride[0], image->y, image->u, image->v,
edged_width, edged_width2, width, height, (csp & XVID_CSP_VFLIP),
interlacing?yv12_to_rgb555i :yv12_to_rgb555,
interlacing?yv12_to_rgb555i_c:yv12_to_rgb555_c, 2);
return 0;
case XVID_CSP_RGB565:
safe_packed_conv(
dst[0], dst_stride[0], image->y, image->u, image->v,
edged_width, edged_width2, width, height, (csp & XVID_CSP_VFLIP),
interlacing?yv12_to_rgb565i :yv12_to_rgb565,
interlacing?yv12_to_rgb565i_c:yv12_to_rgb565_c, 2);
return 0;
case XVID_CSP_BGR:
safe_packed_conv(
dst[0], dst_stride[0], image->y, image->u, image->v,
edged_width, edged_width2, width, height, (csp & XVID_CSP_VFLIP),
interlacing?yv12_to_bgri :yv12_to_bgr,
interlacing?yv12_to_bgri_c:yv12_to_bgr_c, 3);
return 0;
case XVID_CSP_BGRA:
safe_packed_conv(
dst[0], dst_stride[0], image->y, image->u, image->v,
edged_width, edged_width2, width, height, (csp & XVID_CSP_VFLIP),
interlacing?yv12_to_bgrai :yv12_to_bgra,
interlacing?yv12_to_bgrai_c:yv12_to_bgra_c, 4);
return 0;
case XVID_CSP_ABGR:
safe_packed_conv(
dst[0], dst_stride[0], image->y, image->u, image->v,
edged_width, edged_width2, width, height, (csp & XVID_CSP_VFLIP),
interlacing?yv12_to_abgri :yv12_to_abgr,
interlacing?yv12_to_abgri_c:yv12_to_abgr_c, 4);
return 0;
case XVID_CSP_RGB:
safe_packed_conv(
dst[0], dst_stride[0], image->y, image->u, image->v,
edged_width, edged_width2, width, height, (csp & XVID_CSP_VFLIP),
interlacing?yv12_to_rgbi :yv12_to_rgb,
interlacing?yv12_to_rgbi_c:yv12_to_rgb_c, 3);
return 0;
case XVID_CSP_RGBA:
safe_packed_conv(
dst[0], dst_stride[0], image->y, image->u, image->v,
edged_width, edged_width2, width, height, (csp & XVID_CSP_VFLIP),
interlacing?yv12_to_rgbai :yv12_to_rgba,
interlacing?yv12_to_rgbai_c:yv12_to_rgba_c, 4);
return 0;
case XVID_CSP_ARGB:
safe_packed_conv(
dst[0], dst_stride[0], image->y, image->u, image->v,
edged_width, edged_width2, width, height, (csp & XVID_CSP_VFLIP),
interlacing?yv12_to_argbi :yv12_to_argb,
interlacing?yv12_to_argbi_c:yv12_to_argb_c, 4);
return 0;
case XVID_CSP_YUY2:
safe_packed_conv(
dst[0], dst_stride[0], image->y, image->u, image->v,
edged_width, edged_width2, width, height, (csp & XVID_CSP_VFLIP),
interlacing?yv12_to_yuyvi :yv12_to_yuyv,
interlacing?yv12_to_yuyvi_c:yv12_to_yuyv_c, 2);
return 0;
case XVID_CSP_YVYU: /* u,v swapped */
safe_packed_conv(
dst[0], dst_stride[0], image->y, image->v, image->u,
edged_width, edged_width2, width, height, (csp & XVID_CSP_VFLIP),
interlacing?yv12_to_yuyvi :yv12_to_yuyv,
interlacing?yv12_to_yuyvi_c:yv12_to_yuyv_c, 2);
return 0;
case XVID_CSP_UYVY:
safe_packed_conv(
dst[0], dst_stride[0], image->y, image->u, image->v,
edged_width, edged_width2, width, height, (csp & XVID_CSP_VFLIP),
interlacing?yv12_to_uyvyi :yv12_to_uyvy,
interlacing?yv12_to_uyvyi_c:yv12_to_uyvy_c, 2);
return 0;
case XVID_CSP_I420: /* YCbCr == YUV == internal colorspace for MPEG */
yv12_to_yv12(dst[0], dst[0] + dst_stride[0]*height, dst[0] + dst_stride[0]*height + (dst_stride[0]/2)*height2,
dst_stride[0], dst_stride[0]/2,
image->y, image->u, image->v, edged_width, edged_width2,
width, height, (csp & XVID_CSP_VFLIP));
return 0;
case XVID_CSP_YV12: /* YCrCb == YVU == U and V plane swapped */
yv12_to_yv12(dst[0], dst[0] + dst_stride[0]*height, dst[0] + dst_stride[0]*height + (dst_stride[0]/2)*height2,
dst_stride[0], dst_stride[0]/2,
image->y, image->v, image->u, edged_width, edged_width2,
width, height, (csp & XVID_CSP_VFLIP));
return 0;
case XVID_CSP_PLANAR: /* YCbCr with arbitrary pointers and different strides for Y and UV */
yv12_to_yv12(dst[0], dst[1], dst[2],
dst_stride[0], dst_stride[1], /* v: dst_stride[2] not yet supported */
image->y, image->u, image->v, edged_width, edged_width2,
width, height, (csp & XVID_CSP_VFLIP));
return 0;
case XVID_CSP_INTERNAL :
dst[0] = image->y;
dst[1] = image->u;
dst[2] = image->v;
dst_stride[0] = edged_width;
dst_stride[1] = edged_width/2;
dst_stride[2] = edged_width/2;
return 0;
case XVID_CSP_NULL:
case XVID_CSP_SLICE:
return 0;
}
return -1;
}
float
image_psnr(IMAGE * orig_image,
IMAGE * recon_image,
uint16_t stride,
uint16_t width,
uint16_t 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;
}
float sse_to_PSNR(long sse, int pixels)
{
if (sse==0)
return 99.99F;
return 48.131F - 10*(float)log10((float)sse/(float)(pixels)); /* log10(255*255)=4.8131 */
}
long plane_sse(uint8_t *orig,
uint8_t *recon,
uint16_t stride,
uint16_t width,
uint16_t height)
{
int y, bwidth, bheight;
long sse = 0;
bwidth = width & (~0x07);
bheight = height & (~0x07);
/* Compute the 8x8 integer part */
for (y = 0; y<bheight; y += 8) {
int x;
/* Compute sse for the band */
for (x = 0; x<bwidth; x += 8)
sse += sse8_8bit(orig + x, recon + x, stride);
/* remaining pixels of the 8 pixels high band */
for (x = bwidth; x < width; x++) {
int diff;
diff = *(orig + 0*stride + x) - *(recon + 0*stride + x);
sse += diff * diff;
diff = *(orig + 1*stride + x) - *(recon + 1*stride + x);
sse += diff * diff;
diff = *(orig + 2*stride + x) - *(recon + 2*stride + x);
sse += diff * diff;
diff = *(orig + 3*stride + x) - *(recon + 3*stride + x);
sse += diff * diff;
diff = *(orig + 4*stride + x) - *(recon + 4*stride + x);
sse += diff * diff;
diff = *(orig + 5*stride + x) - *(recon + 5*stride + x);
sse += diff * diff;
diff = *(orig + 6*stride + x) - *(recon + 6*stride + x);
sse += diff * diff;
diff = *(orig + 7*stride + x) - *(recon + 7*stride + x);
sse += diff * diff;
}
orig += 8*stride;
recon += 8*stride;
}
/* Compute the down rectangle sse */
for (y = bheight; y < height; y++) {
int x;
for (x = 0; x < width; x++) {
int diff;
diff = *(orig + x) - *(recon + x);
sse += diff * diff;
}
orig += stride;
recon += stride;
}
return (sse);
}
#if 0
#include <stdio.h>
#include <string.h>
int image_dump_pgm(uint8_t * bmp, uint32_t width, uint32_t height, char * filename)
{
FILE * f;
char hdr[1024];
f = fopen(filename, "wb");
if ( f == NULL)
{
return -1;
}
sprintf(hdr, "P5\n#xvid\n%i %i\n255\n", width, height);
fwrite(hdr, strlen(hdr), 1, f);
fwrite(bmp, width, height, f);
fclose(f);
return 0;
}
/* dump image+edges to yuv pgm files */
int image_dump(IMAGE * image, uint32_t edged_width, uint32_t edged_height, char * path, int number)
{
char filename[1024];
sprintf(filename, "%s_%i_%c.pgm", path, number, 'y');
image_dump_pgm(
image->y - (EDGE_SIZE * edged_width + EDGE_SIZE),
edged_width, edged_height, filename);
sprintf(filename, "%s_%i_%c.pgm", path, number, 'u');
image_dump_pgm(
image->u - (EDGE_SIZE2 * edged_width / 2 + EDGE_SIZE2),
edged_width / 2, edged_height / 2, filename);
sprintf(filename, "%s_%i_%c.pgm", path, number, 'v');
image_dump_pgm(
image->v - (EDGE_SIZE2 * edged_width / 2 + EDGE_SIZE2),
edged_width / 2, edged_height / 2, filename);
return 0;
}
#endif
/* dump image to yuvpgm file */
#include <stdio.h>
int
image_dump_yuvpgm(const IMAGE * image,
const uint32_t edged_width,
const uint32_t width,
const uint32_t height,
char *filename)
{
FILE *f;
char hdr[1024];
uint32_t i;
uint8_t *bmp1;
uint8_t *bmp2;
f = fopen(filename, "wb");
if (f == NULL) {
return -1;
}
sprintf(hdr, "P5\n#xvid\n%i %i\n255\n", width, (3 * height) / 2);
fwrite(hdr, strlen(hdr), 1, f);
bmp1 = image->y;
for (i = 0; i < height; i++) {
fwrite(bmp1, width, 1, f);
bmp1 += edged_width;
}
bmp1 = image->u;
bmp2 = image->v;
for (i = 0; i < height / 2; i++) {
fwrite(bmp1, width / 2, 1, f);
fwrite(bmp2, width / 2, 1, f);
bmp1 += edged_width / 2;
bmp2 += edged_width / 2;
}
fclose(f);
return 0;
}
float
image_mad(const IMAGE * img1,
const IMAGE * img2,
uint32_t stride,
uint32_t width,
uint32_t height)
{
const uint32_t stride2 = stride / 2;
const uint32_t width2 = width / 2;
const uint32_t height2 = height / 2;
uint32_t x, y;
uint32_t sum = 0;
for (y = 0; y < height; y++)
for (x = 0; x < width; x++)
sum += abs(img1->y[x + y * stride] - img2->y[x + y * stride]);
for (y = 0; y < height2; y++)
for (x = 0; x < width2; x++)
sum += abs(img1->u[x + y * stride2] - img2->u[x + y * stride2]);
for (y = 0; y < height2; y++)
for (x = 0; x < width2; x++)
sum += abs(img1->v[x + y * stride2] - img2->v[x + y * stride2]);
return (float) sum / (width * height * 3 / 2);
}
void
output_slice(IMAGE * cur, int stride, int width, xvid_image_t* out_frm, int mbx, int mby,int mbl) {
uint8_t *dY,*dU,*dV,*sY,*sU,*sV;
int stride2 = stride >> 1;
int w = mbl << 4, w2,i;
if(w > width)
w = width;
w2 = w >> 1;
dY = (uint8_t*)out_frm->plane[0] + (mby << 4) * out_frm->stride[0] + (mbx << 4);
dU = (uint8_t*)out_frm->plane[1] + (mby << 3) * out_frm->stride[1] + (mbx << 3);
dV = (uint8_t*)out_frm->plane[2] + (mby << 3) * out_frm->stride[2] + (mbx << 3);
sY = cur->y + (mby << 4) * stride + (mbx << 4);
sU = cur->u + (mby << 3) * stride2 + (mbx << 3);
sV = cur->v + (mby << 3) * stride2 + (mbx << 3);
for(i = 0 ; i < 16 ; i++) {
memcpy(dY,sY,w);
dY += out_frm->stride[0];
sY += stride;
}
for(i = 0 ; i < 8 ; i++) {
memcpy(dU,sU,w2);
dU += out_frm->stride[1];
sU += stride2;
}
for(i = 0 ; i < 8 ; i++) {
memcpy(dV,sV,w2);
dV += out_frm->stride[2];
sV += stride2;
}
}
void
image_clear(IMAGE * img, int width, int height, int edged_width,
int y, int u, int v)
{
uint8_t * p;
int i;
p = img->y;
for (i = 0; i < height; i++) {
memset(p, y, width);
p += edged_width;
}
p = img->u;
for (i = 0; i < height/2; i++) {
memset(p, u, width/2);
p += edged_width/2;
}
p = img->v;
for (i = 0; i < height/2; i++) {
memset(p, v, width/2);
p += edged_width/2;
}
}
/****************************************************************************/
static void (*deintl_core)(uint8_t *, int width, int height, const int stride) = 0;
extern void xvid_deinterlace_sse(uint8_t *, int width, int height, const int stride);
#define CLIP_255(x) ( ((x)&~255) ? ((-(x)) >> (8*sizeof((x))-1))&0xff : (x) )
static void deinterlace_c(uint8_t *pix, int width, int height, const int bps)
{
pix += bps;
while(width-->0)
{
int p1 = pix[-bps];
int p2 = pix[0];
int p0 = p2;
int j = (height>>1) - 1;
int V;
unsigned char *P = pix++;
while(j-->0)
{
const int p3 = P[ bps];
const int p4 = P[2*bps];
V = ((p1+p3+1)>>1) + ((p2 - ((p0+p4+1)>>1)) >> 2);
P[0] = CLIP_255( V );
p0 = p2;
p1 = p3;
p2 = p4;
P += 2*bps;
}
V = ((p1+p1+1)>>1) + ((p2 - ((p0+p2+1)>>1)) >> 2);
P[0] = CLIP_255( V );
}
}
#undef CLIP_255
int xvid_image_deinterlace(xvid_image_t* img, int width, int height, int bottom_first)
{
if (height&1)
return 0;
if (img->csp!=XVID_CSP_PLANAR && img->csp!=XVID_CSP_I420 && img->csp!=XVID_CSP_YV12)
return 0; /* not yet supported */
if (deintl_core==0) {
deintl_core = deinterlace_c;
#ifdef ARCH_IS_IA32
{
int cpu_flags = check_cpu_features();
if (cpu_flags & XVID_CPU_MMX)
deintl_core = xvid_deinterlace_sse;
}
#endif
}
if (!bottom_first) {
deintl_core(img->plane[0], width, height, img->stride[0]);
deintl_core(img->plane[1], width>>1, height>>1, img->stride[1]);
deintl_core(img->plane[2], width>>1, height>>1, img->stride[2]);
}
else {
deintl_core((uint8_t *)img->plane[0] + ( height -1)*img->stride[0], width, height, -img->stride[0]);
deintl_core((uint8_t *)img->plane[1] + ((height>>1)-1)*img->stride[1], width>>1, height>>1, -img->stride[1]);
deintl_core((uint8_t *)img->plane[2] + ((height>>1)-1)*img->stride[2], width>>1, height>>1, -img->stride[2]);
}
emms();
return 1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -