Android用C++创建surface显示RGB数据

以下在Android 4.4平台开发测试,用于在屏幕直接显示RGB数据,当然,如果要直接显示YUV,写个函数转换一下也能直接显示。

其中从文件中获取RGB的RGB数据可以从这里下载 http://kc.cc/WeVp

#include <cutils/memory.h>

#include <unistd.h>
#include <utils/Log.h>

#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>

#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
#include <gui/ISurfaceComposer.h>
#include <ui/DisplayInfo.h>
#include <ui/Rect.h>
#include <ui/Region.h>
#include <android/native_window.h>
#include <SkGraphics.h>
#include <SkBitmap.h>
#include <SkCanvas.h>
#include <SkDevice.h>
#include <SkStream.h>
#include <SkImageDecoder.h>

#include <hardware/hwcomposer_defs.h>
using namespace android;

static inline SkBitmap::Config convertPixelFormat(PixelFormat format) {
    /* note: if PIXEL_FORMAT_RGBX_8888 means that all alpha bytes are 0xFF, then
        we can map to SkBitmap::kARGB_8888_Config, and optionally call
        bitmap.setIsOpaque(true) on the resulting SkBitmap (as an accelerator)
    */
    switch (format) {
    case PIXEL_FORMAT_RGBX_8888:    return SkBitmap::kARGB_8888_Config;
    case PIXEL_FORMAT_RGBA_8888:    return SkBitmap::kARGB_8888_Config;
    case PIXEL_FORMAT_RGB_565:      return SkBitmap::kRGB_565_Config;
    default:                        return SkBitmap::kNo_Config;
    }
}

int main(int argc, char** argv)
{
    // set up the thread-pool
    sp<ProcessState> proc(ProcessState::self());
    ProcessState::self()->startThreadPool();

    // create a client to surfaceflinger
    sp<SurfaceComposerClient> client = new SurfaceComposerClient();
    //DisplayoutBuffer display;
    //client->getDisplayoutBuffer(client->getBuiltInDisplay(HWC_DISPLAY_PRIMARY), &display);
	sp<IBinder> dtoken(SurfaceComposerClient::getBuiltInDisplay(
            ISurfaceComposer::eDisplayIdMain));
	DisplayInfo dinfo;
	//获取屏幕的宽高等信息
    status_t status = SurfaceComposerClient::getDisplayInfo(dtoken, &dinfo);
	printf("w=%d,h=%d,xdpi=%f,ydpi=%f,fps=%f,ds=%f\n", 
        dinfo.w, dinfo.h, dinfo.xdpi, dinfo.ydpi, dinfo.fps, dinfo.density);
    if (status)
        return -1;
    sp<SurfaceControl> surfaceControl = client->createSurface(String8("testsurface"),
            dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565, 0);

/****************************第一张图******************************************************/
    SurfaceComposerClient::openGlobalTransaction();
    surfaceControl->setLayer(100000);//设定Z坐标
	surfaceControl->setPosition(0, 0);//以左上角为(0,0)设定显示位置
    SurfaceComposerClient::closeGlobalTransaction();
	surfaceControl->show();//感觉没有这步,图片也能显示
	sp<Surface> surface = surfaceControl->getSurface();

	ANativeWindow_Buffer outBuffer;
	//Surface::SurfaceoutBuffer outBuffer;
	surface->lock(&outBuffer,NULL);//获取surface缓冲区的地址
    ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format);
    android_memset16((uint16_t*)outBuffer.bits, 0xF800, bpr*outBuffer.height);//往surface缓冲区塞要显示的RGB内容
    surface->unlockAndPost();
	sleep(3);

//从文件中获取RGB数据显示 下载地址:http://kc.cc/WeVp
/****************************第二张图******************************************************/
    SurfaceComposerClient::openGlobalTransaction();
    surfaceControl->setSize(480, 272);
	surfaceControl->setPosition(100, 100);
    SurfaceComposerClient::closeGlobalTransaction();
	surfaceControl->show();//感觉没有这步,图片也能显示
	
	FILE *fp = fopen("/tmp/rgb565.rgb","rb");//我们从一个文件里获取RGB565图像数据 480*272
	if(fp != NULL){
		unsigned char *rgb565Data = new unsigned char[480*272*2];
		memset(rgb565Data,0x00,480*272*2);
		fread(rgb565Data,1,480*272*2,fp);
		surface->lock(&outBuffer,NULL);
		//bpr = outBuffer.stride * bytesPerPixel(outBuffer.format);
		//android_memset16((uint16_t*)outBuffer.bits, 0x04E0, bpr*outBuffer.height);
		memcpy(outBuffer.bits,rgb565Data,480*272*2);
		delete[] rgb565Data;
		surface->unlockAndPost();
	}
	fclose(fp);
	sleep(3);

//用skia画图
/*******************************第三张图***************************************************/
    SurfaceComposerClient::openGlobalTransaction();
    surfaceControl->setSize(320, 420);
	surfaceControl->setPosition(100, 100);
    SurfaceComposerClient::closeGlobalTransaction();
	surfaceControl->show();//感觉没有这部图片也能显示
	
    SkPaint paint;
    paint.setColor(SK_ColorBLUE);
    Rect rect(0, 0, 320, 240);
    Region dirtyRegion(rect);
    
    surface->lock(&outBuffer, &rect);
    bpr = outBuffer.stride * bytesPerPixel(outBuffer.format);
//    printf("w=%d,h=%d,bpr=%d,fmt=%d,bits=%p\n", outBuffer.w, outBuffer.h, bpr, outBuffer.format, outBuffer.bits);
    SkBitmap bitmap;
    bitmap.setConfig(convertPixelFormat(outBuffer.format), 320, 240, bpr);
    bitmap.setPixels(outBuffer.bits);
    SkCanvas canvas;
    SkRegion clipReg;
    const Rect b(dirtyRegion.getBounds());
    clipReg.setRect(b.left, b.top, b.right, b.bottom);
    canvas.clipRegion(clipReg);
    canvas.drawARGB(0, 0xFF, 0x00, 0xFF);
    canvas.drawCircle(200, 200, 100, paint);
    bitmap.notifyPixelsChanged();
    surface->unlockAndPost();
    sleep(3);
 

/**********************************************************************************/
    SkFILEStream stream("/sdcard/test.jpg");
    SkImageDecoder* codec = SkImageDecoder::Factory(&stream);
    if(codec){
    	SkBitmap bmp;
    	stream.rewind();
    	codec->decode(&stream, &bmp, SkBitmap::kRGB_565_Config, SkImageDecoder::kDecodePixels_Mode);
    	surface->lock(&outBuffer,NULL);
    	bpr = outBuffer.stride * bytesPerPixel(outBuffer.format);
    	bitmap.setConfig(convertPixelFormat(outBuffer.format), 320, 240, bpr);
    	bitmap.setPixels(outBuffer.bits);
    	//dev = new SkDevice(bitmap);
    	//canvas.setDevice(dev);
    	canvas.drawBitmap(bmp, SkIntToScalar(200), SkIntToScalar(300));
    	surface->unlockAndPost();
		sleep(3);
		//delete dev;
    }
    
    IPCThreadState::self()->joinThreadPool();
    
    IPCThreadState::self()->stopProcess();

    return 0;
}

Android.mk

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= \
	testsurface.cpp

LOCAL_C_INCLUDES := \
	external/skia/include/core

LOCAL_SHARED_LIBRARIES := \
	libcutils \
	libutils \
	libbinder \
    libui \
    libgui \
    libskia

LOCAL_MODULE:= testsurface

LOCAL_MODULE_TAGS := tests

include $(BUILD_EXECUTABLE)

代码修改自http://blog.csdn.net/lxl123/article/details/21465841 他的代码在Android4.4编译会报错.

你可能感兴趣的:(RGB,Surface,yuv,Skia,android4.4)