吴少雄

吴少雄

0个粉丝

15

问答

0

专栏

0

资料

吴少雄  发布于  2016-11-02 14:39:34
采纳率 0%
15个问答
4395

内存搬移加黑边问题的讨论

 
想把1080P的图像叠加到 2120*1280 的全黑图像的缓存中,Y分量搬移成功,但是UV分量的偏移起始地址这个怎么算啊,数据是YUV420P  ,UV12求大神指导UV分量怎么算

int IMAGE::AddBorders(int ImgType, IMAGE image)
{
        if(image.dwImgWidth         {
                return ERROR_OUT_PARAM;
        }
        FILE* fp;
        FILE* fout;
        char *ImageDatabuf ;
        char *pbufyuv;
        int pbufoffset;
        ImageDatabuf = (char*)malloc(image.dwScrImgHeight * image.dwScrImgWidth * 3/2);
        pbufyuv = (char*)malloc(image.dwImgWidth *image.dwImgHeight * 3/2);
        fp = fopen("E://File/1920_1080_chushi30_nv12.yuv","rb+");
        if(ImgType == IMG_YUV_P)
        {
                fout = fopen("E://File/out_p.yuv","wb+");
        }
        else
        {
                fout = fopen("E://File/out_sp.yuv","wb+");
        }
        mW_offset = (image.dwImgWidth - image.dwScrImgWidth)/2 ;
        mH_offset = (image.dwImgHeight - image.dwScrImgHeight)/2;
        //背景置黑色
        memset(pbufyuv, BLOCK_Y, image.dwImgHeight * image.dwImgWidth * 3/2);
        memset(pbufyuv+image.dwImgHeight * image.dwImgWidth, BLOCK_UV, image.dwImgHeight * image.dwImgWidth*1/2);
        //先拷贝Y
        pbufoffset = mW_offset + (mH_offset * image.dwImgWidth);

        for(int line =1; line <= image.dwScrImgHeight; line++)
        {
                fread(ImageDatabuf, 1,image.dwScrImgWidth, fp);
                memcpy(pbufyuv + pbufoffset, ImageDatabuf,image.dwScrImgWidth);
                if(line != image.dwScrImgHeight)
                {
                        pbufoffset = pbufoffset + image.dwImgWidth;
                }
                memset(ImageDatabuf, 0, image.dwScrImgWidth);
        }
        if(ImgType == IMG_YUV_P)
        {
                pbufoffset = pbufoffset + image.dwImgWidth /2 - (mW_offset/2 + mH_offset*image.dwImgWidth/2);
                for(int Luv = 1;Luv <= image.dwScrImgHeight; Luv++)
                {
                        fread(ImageDatabuf, 1,image.dwScrImgWidth/2, fp);
                        //拷贝数据
                        memcpy(pbufyuv+pbufoffset, ImageDatabuf,image.dwScrImgWidth/2);
                        if(Luv != image.dwScrImgHeight)
                        {
                                pbufoffset= pbufoffset+ image.dwImgWidth/2;
                        }       
                        memset(ImageDatabuf, 0, image.dwScrImgWidth/2);
                }
        }
        int s32ret = fwrite(pbufyuv ,1,image.dwImgHeight * image.dwImgWidth * 3/2, fout);
        if(s32ret >0)
        {
                fclose(fout);
                fclose(fp);
        }
}
我来回答
回答14个
时间排序
认可量排序

吴少雄

0个粉丝

15

问答

0

专栏

0

资料

吴少雄 2016-11-02 14:44:50
认可0
问题现在就出现UV分量的初始的偏移地址      pbufoffset = pbufoffset + image.dwImgWidth /2 - (mW_offset/2 + mH_offset*image.dwImgWidth/2);

zhuangweiye

8个粉丝

0

问答

0

专栏

0

资料

zhuangweiye 2016-11-02 15:47:16
认可0

从代码来看
    memset(pbufyuv, BLOCK_Y, image.dwImgHeight * image.dwImgWidth * 3/2);
    memset(pbufyuv+image.dwImgHeight * image.dwImgWidth, BLOCK_UV, image.dwImgHeight * image.dwImgWidth*1/2);

背景是YUV420的,但是是planar还是semi-planar是看不出来的, 因此需要知道是什么格式的

假定 要把image放到背景的起点为(x, y)的位置, 那么Y的起始位置也是(x,y), U/V的起始位置就是(x/2,y/2), 对应于YUV420(这个不分p还是sp都一样)

如果背景是p的, 那么U V是分开放的
背景的 U 的起始地址为 pU = pbufyuv+image.dwImgHeight * image.dwImgWidth
           V 的起始地址为 pV = pbufyuv+image.dwImgHeight * image.dwImgWidth + image.dwImgHeight * image.dwImgWidth / 4
           U/V的strideUV = image.dwImgWidth / 2

要放image的pUVoffset 为 (y/2)*strideUV + (x/2), 即 pUstart = pU + pUVoffset , pVstart = pV + pUVoffset


如果背景是sp的, 那么U V是放在一起的, 假定是UVUV。。。的格式
背景的 U 的起始地址为 pU = pbufyuv+image.dwImgHeight * image.dwImgWidth
           V 的起始地址为 pV = pU + 1
           U/V的strideUV = image.dwImgWidth

要放image的pUVoffset 为 (y/2)*strideUV + (x/2),即 pUstart = pU + pUVoffset , pVstart = pV + pUVoffset , 但是注意这里U/V的地址增量是2

(注意:这里是根据楼主的代码来定的,是假定stride== image.dwImgWidth)

吴少雄

0个粉丝

15

问答

0

专栏

0

资料

吴少雄 2016-11-02 15:51:22
认可0
[quote][url=forum.php?mod=redirect&goto=findpost&pid=40711&ptid=13226]zhuangweiye 发表于 2016-11-2 15:47[/url]
从代码来看
    memset(pbufyuv, BLOCK_Y, image.dwImgHeight * image.dwImgWidth * 3/2);
    memset( ...[/quote]

跨度就是 image.dwImgWidth ,因为这个是黑色的底图。我的数据格式UV12 的  ,黑色的底图高和贴图的高一样时,没有问题,UV数据都贴的正常,就是高不一致时,启动地址算的不对

吴少雄

0个粉丝

15

问答

0

专栏

0

资料

吴少雄 2016-11-02 15:54:14
认可0
[quote][url=forum.php?mod=redirect&goto=findpost&pid=40712&ptid=13226]吴少雄 发表于 2016-11-2 15:51[/url]
跨度就是 image.dwImgWidth ,因为这个是黑色的底图。我的数据格式UV12 的  ,黑色的底图高和贴图的高一 ...[/quote]

就是这句计算  pbufoffset = pbufoffset + image.dwImgWidth /2 - (mW_offset/2 + mH_offset*image.dwImgWidth/2); 有问题,mW_offset = 100,mH_offset =100,image.dwImgWidth 是黑色底图的跨距

zhuangweiye

8个粉丝

0

问答

0

专栏

0

资料

zhuangweiye 2016-11-02 15:56:12
认可0
[quote][url=forum.php?mod=redirect&goto=findpost&pid=40706&ptid=13226]吴少雄 发表于 2016-11-2 14:44[/url]
问题现在就出现UV分量的初始的偏移地址      pbufoffset = pbufoffset + image.dwImgWidth /2 - (mW_of ...[/quote]

为什么要减呢?

吴少雄

0个粉丝

15

问答

0

专栏

0

资料

吴少雄 2016-11-02 16:03:46
认可0
[quote][url=forum.php?mod=redirect&goto=findpost&pid=40715&ptid=13226]zhuangweiye 发表于 2016-11-2 15:56[/url]
为什么要减呢?[/quote]

不减水平偏移的1/2时,UV数据向右整体移动了100

吴少雄

0个粉丝

15

问答

0

专栏

0

资料

吴少雄 2016-11-02 16:19:05
认可0
[quote][url=forum.php?mod=redirect&goto=findpost&pid=40717&ptid=13226]吴少雄 发表于 2016-11-2 16:03[/url]
不减水平偏移的1/2时,UV数据向右整体移动了100[/quote]

庄工:
      减了X,Y的1/2,就是确定UV的起始地址。其实跟你上面说的(x/2,y/2)一样的。

zhuangweiye

8个粉丝

0

问答

0

专栏

0

资料

zhuangweiye 2016-11-02 16:37:32
认可0
本帖最后由 zhuangweiye 于 2016-11-2 16:39 编辑

[quote][url=forum.php?mod=redirect&goto=findpost&pid=40719&ptid=13226]吴少雄 发表于 2016-11-2 16:19[/url]
庄工:
      减了X,Y的1/2,就是确定UV的起始地址。其实跟你上面说的(x/2,y/2)一样的。[/quote]

为什么不是加呢? 另外注意 要使用背景的宽做为stride来搬移

zhuangweiye

8个粉丝

0

问答

0

专栏

0

资料

zhuangweiye 2016-11-02 16:48:24
认可0
[quote][url=forum.php?mod=redirect&goto=findpost&pid=40722&ptid=13226]zhuangweiye 发表于 2016-11-2 16:37[/url]
为什么不是加呢? 另外注意 要使用背景的宽做为stride来搬移[/quote]

U 的起始地址为 pU = pbufyuv+2120* 1280
V 的起始地址为 pV = pbufyuv+2110* 1280 + 2110 * 1280 / 4

千万别用1920x1080, 要用背景的宽高


zhuangweiye

8个粉丝

0

问答

0

专栏

0

资料

zhuangweiye 2016-11-02 17:38:10
认可0
[quote][url=forum.php?mod=redirect&goto=findpost&pid=40714&ptid=13226]吴少雄 发表于 2016-11-2 15:54[/url]
就是这句计算  pbufoffset = pbufoffset + image.dwImgWidth /2 - (mW_offset/2 + mH_offset*image.dwImg ...[/quote]

其实很简单就知道这样写是不对的, 当(x, y) = (0, 0)时 pbufoffset应该不变才对, 而楼主的代码pbufoffset = pbufoffset + image.dwImgWidth /2

吴少雄

0个粉丝

15

问答

0

专栏

0

资料

吴少雄 2016-11-03 09:06:25
认可0
[quote][url=forum.php?mod=redirect&goto=findpost&pid=40729&ptid=13226]zhuangweiye 发表于 2016-11-2 17:38[/url]
其实很简单就知道这样写是不对的, 当(x, y) = (0, 0)时 pbufoffset应该不变才对, 而楼主的代码pbufoffset ...[/quote]

庄工:
      这句话解释是 拷贝最后一行Y时,pbufoffset是没有加跨度,而且最后的跨度应该算UV的跨度,黑色底图的跨度应该就是image.dwIngWidth /2,这个我测试了,是没有错的。底图跟原图一样也没有问题。

zhuangweiye

8个粉丝

0

问答

0

专栏

0

资料

zhuangweiye 2016-11-03 09:40:33
认可0
[quote][url=forum.php?mod=redirect&goto=findpost&pid=40747&ptid=13226]吴少雄 发表于 2016-11-3 09:06[/url]
庄工:
      这句话解释是 拷贝最后一行Y时,pbufoffset是没有加跨度,而且最后的跨度应该算UV的跨度, ...[/quote]

按楼主的解释

pbufoffset是没有加跨度, 加了stride, 也只是U的起始地址, 这时候减, 不是把U copy到Y里面去了

zhuangweiye

8个粉丝

0

问答

0

专栏

0

资料

zhuangweiye 2016-11-03 09:49:59
认可0
本帖最后由 zhuangweiye 于 2016-11-3 09:52 编辑

[quote][url=forum.php?mod=redirect&goto=findpost&pid=40747&ptid=13226]吴少雄 发表于 2016-11-3 09:06[/url]
庄工:
      这句话解释是 拷贝最后一行Y时,pbufoffset是没有加跨度,而且最后的跨度应该算UV的跨度, ...[/quote]

楼主的 原图和黑背景都是 YUV420 planar的对不对?

那么U 和 V 是分开放的, 楼主代码里面 UV是一个循环处理, 这个做法对于把一个前景图copy到背景俩面是不可能对的, 必须分开处理

做法: (只说U)
按3楼的做法
1.先计算, 黑背景的U的起始地址 pU = pY+image.dwImgHeight * image.dwImgWidth
   其中 pY = malloc的地址
2.然后计算 前景要copy的起始地址, pUstart = pU + pUoffset
3.读一行U(直接读到背景, copy都可以)
4. pUstart += image.dwImgWidth / 2

V的方式相同

建议楼主试验一下

吴少雄

0个粉丝

15

问答

0

专栏

0

资料

吴少雄 2016-11-03 11:18:29
认可0
[quote][url=forum.php?mod=redirect&goto=findpost&pid=40755&ptid=13226]zhuangweiye 发表于 2016-11-3 09:49[/url]
楼主的 原图和黑背景都是 YUV420 planar的对不对?

那么U 和 V 是分开放的, 楼主代码里面 UV是一个循 ...[/quote]

庄工:
        YUV420 semi-planar 的实现了。YUV420 planar 现在只实现水平可以,但是height加法,还没有实现。我根据你说的试一下。谢谢啦
或将文件直接拖到这里
悬赏:
E币
网盘
* 网盘链接:
* 提取码:
悬赏:
E币

Markdown 语法

  • 加粗**内容**
  • 斜体*内容*
  • 删除线~~内容~~
  • 引用> 引用内容
  • 代码`代码`
  • 代码块```编程语言↵代码```
  • 链接[链接标题](url)
  • 无序列表- 内容
  • 有序列表1. 内容
  • 缩进内容
  • 图片![alt](url)
+ 添加网盘链接/附件

Markdown 语法

  • 加粗**内容**
  • 斜体*内容*
  • 删除线~~内容~~
  • 引用> 引用内容
  • 代码`代码`
  • 代码块```编程语言↵代码```
  • 链接[链接标题](url)
  • 无序列表- 内容
  • 有序列表1. 内容
  • 缩进内容
  • 图片![alt](url)
相关问答
无更多相似问答 去提问
举报反馈

举报类型

  • 内容涉黄/赌/毒
  • 内容侵权/抄袭
  • 政治相关
  • 涉嫌广告
  • 侮辱谩骂
  • 其他

详细说明

易百纳技术社区