yuv数据上添加水印功能,先使用libyuv把yuv数据转为RGB,然后在RGB上画水印

int yuvWidth=640;
int yuvHeight=360;

char *rgbBuf = new char[yuvWidth*yuvHeight*4];

//创建主画布与bitmap关联
SkBitmap *pMainSkBitmap = new SkBitmap();

SkImageInfo info(SkImageInfo::MakeN32Premul(yuvWidth,yuvHeight));
pMainSkBitmap ->setInfo(info);
pMainSkBitmap ->setPixels(rgbBuf);
pMainSkCanvas = new SkCanvas(*pMainSkBitmap );

yuv转成rgb以后,数据放在rgbBuf里

一:图片水印

1.先加载图片资源

//加载图片资源
sk_sp<SkData> skData = SkData::MakeFromFileName("/storage/emulated/0/hello.png");
sk_sp<SkImage> m_pSkimage = SkImage::MakeFromEncoded(skData);

m_imageWidth = m_pSkimage->width();
m_imageHeight = m_pSkimage->height();

 2.格式转换,

为啥要格式转换?

最初是直接把SkImage画到pMainSkCanvas,但是图片的颜色不对了,好像是R和B对调了,所以把image里的bitmap拷贝出来,把ColorType手动换成kBGRA_8888_SkColorType,颜色才对(原因好像是windows和android上rgb的颜色不一样,后面文字水印也遇到了同样的问题)

//SkImage转SkBitmap
SkBitmap bitmap;
bool bRes = m_pSkimage->asLegacyBitmap(&bitmap);

SkBitmap drawbitmap; //最终要画到主画布上的图片bitmap       
SkImageInfo info = SkImageInfo::Make(m_imageWidth,m_imageHeight,kBGRA_8888_SkColorType,
                                m_pSkimage->alphaType());
drawbitmap.setInfo(info);
drawbitmap.setPixels(bitmap.getPixels());

3.画水印

//设置缩放,图片透明度
//m_scale缩放比例
SkRect rect = SkRect::MakeXYWH(x,y,m_imageWidth*m_scale/100,m_imageHeight*m_scale/100);
SkPaint paint;
paint.setAlpha(m_opacity);//设置透明度,m_opacity=0~255
pMainSkCanvas->drawBitmapRect(drawbitmap,rect,&paint);//在主画布上画图片水印

二、文字水印

字体使用的是DroidSansFallback.ttf,不然中文会乱码,字体编码格式为utf-8

//加载字体
sk_sp<SkTypeface> m_pFontFace = SkTypeface::MakeFromFile("/mnt/sdcard/DroidSansFallback.ttf");

SkPaint m_paint;
m_paint.setTypeface(m_pFontFace);

m_paint.setARGB((color & 0xff000000)>>24, color & 0xff,(color & 0xff00)>>8,(color & 0xff0000)>>16);//跟windows下的不一样,RGB,R和B反着
m_paint.setTextSize(SkIntToScalar(fontsize));
m_paint.setAntiAlias(true);
m_paint.setTextAlign(SkPaint::Align::kLeft_Align);
m_paint.setTextEncoding(SkPaint::TextEncoding::kUTF8_TextEncoding);
m_paint.setSubpixelText(true);
//计算文字宽高

char *utftext = "abc文字水印dg";
int utftextlen = strlen(utftextlen);

SkRect skRect;
m_paint.measureText(utftext,utftextlen,&skRect);

int m_textWidth = skRect.right()-skRect.left();
int m_textHeight = skRect.bottom()-skRect.top();

文字画布比文字稍微大一点
int m_imageWidth  = m_textWidth+8;
int m_imageHeight = m_textHeight+8;

int len = m_imageWidth * m_imageHeight * 4;
m_pDataBuf = new(std::nothrow) char[len];
memset(m_pDataBuf,0,m_imageWidth * m_imageHeight * 4);

SkImageInfo info(SkImageInfo::MakeN32Premul(m_imageWidth,m_imageHeight));

//创建文字画布
m_pSkBitmap = new SkBitmap();
m_pSkBitmap->setInfo(info);
m_pSkBitmap->setPixels(m_pDataBuf);
m_pSkCanvas = new SkCanvas(*m_pSkBitmap);

//设置文字画布背景色
m_pSkBitmap->eraseARGB((m_nBgcolor & 0xff000000)>>24, m_nBgcolor & 0xff, (m_nBgcolor & 0xff00)>>8, (m_nBgcolor & 0xff0000)>>16);

SkString sktext(utftext);
SkScalar fontSpacing = m_paint.getFontSpacing();  
    
SkScalar ratio = m_paint.getTextSize()/fontSpacing;//文字字体大小除以字体space

//此处x,y的计算,是基于m_paint设置的文字左对齐计算的,x坐标比较正常,y坐标比较难懂(y好像是下面是0坐标),试出这么一个公式,乘以1个比率ratio,这样画出来的文字才在中心,x,y为文字画布的起始点
SkScalar x = (SkScalar)(m_imageWidth-m_textWidth)/2*ratio;
SkScalar y = (SkScalar)m_imageHeight*ratio;

//skcanvas bitmap的顶部是零坐标,y是文字的底部在bitmap上的坐标

//在文字画布上画文字
m_pSkCanvas->drawText(sktext.c_str(), sktext.size(),x, y,m_paint);

然后再把文字bitmap画到主画布上

//此处x,y是主画面的坐标系中的点
pMainSkCanvas->drawBitmap(*m_pSkBitmap,x,y);

 

三、效果图

颜色:

abcde文字fg:颜色值:0xCCFFA07A  偏橙色一点  背景色: 0xFF0000FF 蓝色 透明度255

时间水印,背景颜色设置的透明度20,

图片的透明度设置的100

 

字体下载

https://download.csdn.net/download/u011737099/19711898

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐