YUV 任意尺寸缩放2011-11-20 16:52最近项目中遇到jpeg 图片缩放问题,libjpeg 只支持 1/8, 1/4, 1/2, 1/1 的缩小。而 ffplay 对 Jpeg, 视频的缩放貌似不支持。
于是经过断断续续的编码和思考,“基本上” 解决了YUV420P格式的缩放问题。
这里的“基本上”指的是:
1)它解决了视频全屏缩小问题,没有产生颜色偏移等问题;
2)YUV 按某一特定比例对静态图缩放后,颜色可能会变;
代码:
/*file:sdl_yuv.c
direct access yuv color space
author: ludi
gcc sdl_yuv.c rgb2yuv.c -g -DGEN_SDL_YUV_EXE `sdl-config --cflags --libs`
quick and dirty, but it is correct:
void drawHLine_(SDL_Overlay *yuv, int sx, int sy, int len)
{
int w = yuv->pitches[0];
memset(yuv->pixels[0]+sy*w + sx, 255, len*1);
memset(yuv->pixels[1]+(sy*w + 2*sx)/4, 255, (len+1)/2);
memset(yuv->pixels[2]+(sy*w + 2*sx)/4, 255, (len+1)/2);
}
todo: add scalability for blitSurface2YUV (really need this??).
history: 2011.11.05 initial startup.
*/
#include<string.h>
#include<SDL.h>
/*
双线性内插值算法描述如下:
对于一个目的像素,设置坐标通过反向变换得到的浮点坐标为(i+u,j+v)
(其中i、j均为浮点坐标的整数部分,u、v为浮点坐标的小数部分,是取值[0,1)区间的浮点数),
则这个像素的值 f(i+u,j+v) 可由原图像中坐标为 (i,j)、(i+1,j)、(i,j+1)、(i+1,j+1)所对应的周围四个像素的值决定,即:
f(i+u,j+v) = (1-u)(1-v)f(i,j) + (1-u)vf(i,j+1) + u(1-v)f(i+1,j) + uvf(i+1,j+1) 公式1
其中f(i,j)表示源图像(i,j)处的的像素值,以此类推。
例子:
假如目标图的象素坐标为(1,1),那么反推得到的对应于源图的坐标是(0.75 , 0.75),
这其实只是一个概念上的虚拟象素,实际在源图中并不存在这样一个象素,
那么目标图的象素(1,1)的取值不能够由这个虚拟象素来决定,
而只能由源图的这四个象素共同决定:(0,0)(0,1)(1,0)(1,1),
而由于(0.75,0.75)离(1,1)要更近一些,那么(1,1)所起的决定作用更大一些,
这从公式1中的系数uv=0.75×0.75就可以体现出来,
而(0.75,0.75)离(0,0)最远,所以(0,0)所起的决定作用就要小一些,
公式中系数为(1-u)(1-v)=0.25×0.25也体现出了这一特点;
浮点运算的优化:
反向变换
(x, y) --> (i+u, j+v) = (sw/dw * x, sh/dh * y)
u = (sw*x % dw)/dw
v = (sh*y % dh)/dh
1 - u = (dw - sw*x % dw)/dw
1 - v = (dh - sh*y % dh)/dh
公式1
f(i+u,j+v) = (1-u)(1-v)f(i,j) + (1-u)vf(i,j+1) + u(1-v)f(i+1,j) + uvf(i+1,j+1)
两边同时乘以 dw*dh,得到
dw*dh*f(i+u, j+v) = (dw - sw*x % dw)*(dh - sh*y %dh)*f(i,j) + ... + (sw*x % dw)(sh*y % dh)f(i+1,j+1)
* */
#define yf(i,j) (*((Uint8*)src->pixels[0] + ((j) + srcrect->y)*src->pitches[0] + ((i) + srcrect->x) ))
#define vf(i,j) (*((Uint8*)src->pixels[1] + ((j)/2 + srcrect->y/2)*src->pitches[1] + ((i)/2 + srcrect->x/2) ))
#define uf(i,j) (*((Uint8*)src->pixels[2] + ((j)/2 + srcrect->y/2)*src->pitches[2] + ((i)/2 + srcrect->x/2) ))
int blitYUV2YUVScale(SDL_Overlay *src, SDL_Rect *srcrect, SDL_Overlay *dst, SDL_Rect *dstrect)
{
unsigned int x,y, i,j, tu,tv,tu1,tv1,tf;
unsigned int y1,v1,u1;
int dw,dh, sw,sh;
//check args
if(src->format != dst->format)return 1;
dw = dstrect->x + dstrect->w < dst->w ? dstrect->w : dst->w - dstrect->x;
dh = dstrect->y + dstrect->h < dst->h ? dstrect->h : dst->h - dstrect->y;
sw = srcrect->x + srcrect->w < src->w ? srcrect->w : src->w - srcrect->x;
sh = srcrect->y + srcrect->h < src->h ? srcrect->h : src->h - srcrect->y;
if(dw <= 0 || dh <= 0 || sw <= 0 || sh <= 0)
return 1;
for(y = 0; y < dh; ++y)
{
for(x = 0; x < dw; ++x)
{
i = sw*x / dw;
j = sh*y / dh;
tu = sw*x % dw;
tv = sh*y % dh;
tu1 = dw - tu;
tv1 = dh - tv;
tf =
tu1 * tv1 * yf(i,j) + tu1 * tv * yf(i,j+1) +
tu * tv1 * yf(i+1,j) + tu * tv * yf(i+1,j+1);
y1 = tf/(dw*dh);
*(dst->pixels[0] + (dstrect->y + y) * dst->pitches[0] + (dstrect->x + x)) = y1;
if((x%2 == 0 ) && (y%2 == 0 ))
{
tf =
tu1 * tv1 * vf(i,j) + tu1 * tv * vf(i,j+1) +
tu * tv1 * vf(i+1,j) + tu * tv * vf(i+1,j+1);
v1 = tf/(dw*dh);
tf =
tu1 * tv1 * uf(i,j) + tu1 * tv * uf(i,j+1) +
tu * tv1 * uf(i+1,j) + tu * tv * uf(i+1,j+1);
u1 = tf/(dw*dh);
*(dst->pixels[1] + (y/2 + dstrect->y /2) * dst->pitches[1] + (dstrect->x/2 + x/2)) = v1;
*(dst->pixels[2] + (y/2 + dstrect->y /2) * dst->pitches[2] + (dstrect->x/2 + x/2)) = u1;
}
}
}
return 0;
}
extern void rgb2yuv(int r, int g, int b, int *y, int *u, int *v);
extern void yuv2rgb(int y, int u, int v, int *r, int *g, int *b);
void fillRect(SDL_Overlay *yuv, SDL_Rect *rect, int y0, int u, int v)
{
int y;
int size = rect->w;
int uv_size = (size-1)/2+1;
int uv_off = 0;
for(y = 0; y< rect->h; ++y)
{
memset(yuv->pixels[0] + (rect->y + y) * yuv->pitches[0] + rect->x,
y0, size);
if(y%2 == 0)
{
memset(yuv->pixels[1] + (uv_off + rect->y /2) * yuv->pitches[1] + rect->x/2,
v, uv_size);
memset(yuv->pixels[2] + (uv_off + rect->y /2) * yuv->pitches[2] + rect->x/2,
u, uv_size);
++uv_off;
}
}
}
int blitYUV2YUV(SDL_Overlay *src, int srcx, int srcy, SDL_Overlay *dst, SDL_Rect *dstrect)
{
int min_size, uv_size, min_h, line, uv_off;
min_size = (src->pitches[0] - srcx < dst->pitches[0] - dstrect->x)?
src->pitches[0] - srcx : dst->pitches[0] - dstrect->x;
min_h = (src->h - srcy < dst->h - dstrect->y)?
src->h - srcy : dst->h - dstrect->y;
if(min_size > dstrect->w ) min_size = dstrect->w;
if(min_h > dstrect->h)min_h = dstrect->h;
if(min_size <= 0 || min_h <= 0)return 0;
if(src->format != dst->format)return 1;
for(uv_off = 0, line = 0; line < min_h; line++)
{
memcpy(dst->pixels[0] + (line + dstrect->y) * dst->pitches[0] + dstrect->x,
src->pixels[0] + (line + srcy) * src->pitches[0] + srcx, min_size);
if(line%2 == 0)
{
uv_size = (min_size+1)/2;
memcpy(dst->pixels[1] + (uv_off + dstrect->y /2) * dst->pitches[1] + dstrect->x /2,
src->pixels[1] + (uv_off + srcy /2) * src->pitches[1] + srcx /2, uv_size);
memcpy(dst->pixels[2] + (uv_off + dstrect->y /2) * dst->pitches[2] + dstrect->x /2,
src->pixels[2] + (uv_off + srcy /2) * src->pitches[2] + srcx /2, uv_size);
++uv_off;
}
}
return 0;
}
int blitSurface2YUV(SDL_Surface *src, SDL_Overlay *dst, SDL_Rect *dstrect)
{
Uint8 r, g, b;
int y1,u1,v1;
int y,x;
int height = src->h < dstrect->h ? src->h: dstrect->h;
int width = src->w < dstrect->w ? src->w: dstrect->w;
int uv_off = 0;
Uint32 pixel;
if(dst->format != SDL_YV12_OVERLAY)return 1;
for(y = 0; y < height; ++y)
{
for(x = 0; x < width; ++x)
{
switch(src->format->BitsPerPixel)
{
case 8:
pixel = *((Uint8*)src->pixels + y*src->pitch + x);
break;
case 16:
pixel = *((Uint16*)src->pixels + y*src->pitch/2 + x);
break;
case 32:
pixel = *((Uint32*)src->pixels + y*src->pitch/4 + x);
break;
default:
return -1;
}
SDL_GetRGB(pixel, src->format, &r, &g, &b);
rgb2yuv(r, g, b, &y1, &u1, &v1);
memset(dst->pixels[0] + (dstrect->y + y) * dst->pitches[0] + (dstrect->x + x),
(Uint8)y1, 1);
if((x%2 == 0 ) && (y%2 == 0 ))
{
memset(dst->pixels[1] + (uv_off + dstrect->y /2) * dst->pitches[1] + (dstrect->x/2 + x/2),
(Uint8)v1, 1);
memset(dst->pixels[2] + (uv_off + dstrect->y /2) * dst->pitches[2] + (dstrect->x/2 + x/2),
(Uint8)u1, 1);
}
}
if(y%2 == 0)++uv_off;
}
retu
没有合适的资源?快使用搜索试试~ 我知道了~
sdl_yuv.rar_JPEG YUV_libjpeg yuv _yuv jpeg_yuv的缩放_yuv缩放
共1个文件
c:1个
1.该资源内容由用户上传,如若侵权请联系客服进行举报
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
版权申诉
0 下载量 112 浏览量
2022-09-14
19:40:05
上传
评论
收藏 4KB RAR 举报
温馨提示
YUV 任意尺寸缩放 jpeg 图片缩放问题,libjpeg 只支持 1/8, 1/4, 1/2, 1/1 的缩小。而 ffplay 对 Jpeg, 视频的缩放貌似不支持。 于是经过断断续续的编码和思考,“基本上” 解决了YUV420P格式的缩放问题。 这里的“基本上”指的是: 1)它解决了视频全屏缩小问题,没有产生颜色偏移等问题; 2)YUV 按某一特定比例对静态图缩放后,颜色可能会变;
资源详情
资源评论
资源推荐
收起资源包目录
sdl_yuv.rar (1个子文件)
sdl_yuv.c 11KB
共 1 条
- 1
寒泊
- 粉丝: 86
- 资源: 1万+
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- Java 代码覆盖率库.zip
- Java 代码和算法的存储库 也为该存储库加注星标 .zip
- 免安装Windows10/Windows11系统截图工具,无需安装第三方截图工具 双击直接使用截图即可 是一款免费可靠的截图小工具哦~
- Libero Soc v11.9的安装以及证书的获取(2021新版).zip
- BouncyCastle.Cryptography.dll
- 5.1 孤立奇点(JD).ppt
- 基于51单片机的智能交通灯控制系统的设计与实现源码+报告(高分项目)
- 什么是 SQL 注入.docx
- Windows 11上启用与禁用网络发现功能的操作指南
- Java Redis 客户端 GUI 工具.zip
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论0