浅谈android截屏问题

做了几个月的截屏开发,稍微了解了一下这方面的知识,于是拿来分享一下,也许对你有一些帮助吧。

    我是基于android2.3.3系统之上的,想必大家应该知道在android源码下面有个文件叫做screencap吧,位于frameworks\base\services\surfaceflinger\tests\screencap\screencap.cpp,你直接在linux下编译(保存在 /system/bin/test-screencap),然后push到手机上再通过电脑去敲命令test-screencap /mnt/sdcard/scapxx.png就可以实现截屏。

01 /*
02  * Copyright (C) 2010 The Android Open Source Project
03  *
04  * Licensed under the Apache License, Version 2.0 (the "License");
05  * you may not use this file except in compliance with the License.
06  * You may obtain a copy of the License at
07  *
08  *      http://www.apache.org/licenses/LICENSE-2.0
09  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16  
17 #include
18  
19 #include
20 #include
21 #include
22  
23 #include
24 #include
25  
26 #include
27 #include
28  
29 using namespace android;
30  
31 int main(int argc, char** argv)
32 {
33     if (argc != 2) {
34         printf("usage: %s path\n", argv[0]);
35         exit(0);
36     }
37  
38     const String16 name("SurfaceFlinger");
39     sp composer;
40     getService(name, &composer);
41  
42     sp heap;
43     uint32_t w, h;
44     PixelFormat f;
45     status_t err = composer->captureScreen(0, &heap, &w, &h, &f, 0, 0);
46     if (err != NO_ERROR) {
47         fprintf(stderr, "screen capture failed: %s\n"strerror(-err));
48         exit(0);
49     }
50  
51     printf("screen capture success: w=%u, h=%u, pixels=%p\n",
52             w, h, heap->getBase());
53  
54     printf("saving file as PNG in %s ...\n", argv[1]);
55  
56     SkBitmap b;
57     b.setConfig(SkBitmap::kARGB_8888_Config, w, h);
58     b.setPixels(heap->getBase());
59     SkImageEncoder::EncodeFile(argv[1], b,
60             SkImageEncoder::kPNG_Type, SkImageEncoder::kDefaultQuality);
61  
62     return 0;
63 }


    其实这个程序真正用到的就是一个叫做capturescreen的函数,而capturescreen会调用captureScreenImplLocked这个函数

下面是代码:

001 status_t SurfaceFlinger::captureScreenImplLocked(DisplayID dpy,
002         sp* heap,
003         uint32_t* w, uint32_t* h, PixelFormat* f,
004         uint32_t sw, uint32_t sh)
005 {
006    LOGI("captureScreenImplLocked");
007     status_t result = PERMISSION_DENIED;
008  
009     // only one display supported for now
010     if (UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT))
011         return BAD_VALUE;
012  
013     if (!GLExtensions::getInstance().haveFramebufferObject())
014         return INVALID_OPERATION;
015  
016     // get screen geometry
017     const DisplayHardware& hw(graphicPlane(dpy).displayHardware());
018     const uint32_t hw_w = hw.getWidth();
019     const uint32_t hw_h = hw.getHeight();
020  
021     if ((sw > hw_w) || (sh > hw_h))
022         return BAD_VALUE;
023  
024     sw = (!sw) ? hw_w : sw;
025     sh = (!sh) ? hw_h : sh;
026     const size_t size = sw * sh * 4;
027  
028     // make sure to clear all GL error flags
029     while ( glGetError() != GL_NO_ERROR ) ;
030  
031     // create a FBO
032     GLuint name, tname;
033     glGenRenderbuffersOES(1, &tname);
034     glBindRenderbufferOES(GL_RENDERBUFFER_OES, tname);
035     glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_RGBA8_OES, sw, sh);
036     glGenFramebuffersOES(1, &name);
037     glBindFramebufferOES(GL_FRAMEBUFFER_OES, name);
038     glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES,
039             GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, tname);
040  
041     GLenum status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES);
042     if (status == GL_FRAMEBUFFER_COMPLETE_OES) {
043  
044         // invert everything, b/c glReadPixel() below will invert the FB
045         glViewport(0, 0, sw, sh);
046         glScissor(0, 0, sw, sh);
047         glMatrixMode(GL_PROJECTION);
048         glPushMatrix();
049         glLoadIdentity();
050         glOrthof(0, hw_w, 0, hw_h, 0, 1);
051         glMatrixMode(GL_MODELVIEW);
052  
053         // redraw the screen entirely...
054         glClearColor(0,0,0,1);
055         glClear(GL_COLOR_BUFFER_BIT);
056  
057         const Vector< sp >& layers(mVisibleLayersSortedByZ);
058         const size_t count = layers.size();
059         for (size_t i=0 ; i
060             const sp& layer(layers[i]);
061             layer->drawForSreenShot();
062         }
063  
064         // XXX: this is needed on tegra
065         glScissor(0, 0, sw, sh);
066  
067         // check for errors and return screen capture
068         if (glGetError() != GL_NO_ERROR) {
069             // error while rendering
070             result = INVALID_OPERATION;
071         else {
072             // allocate shared memory large enough to hold the
073             // screen capture
074             sp base(
075                     new MemoryHeapBase(size, 0, "screen-capture") );
076             voidconst ptr = base->getBase();
077             if (ptr) {
078                 // capture the screen with glReadPixels()
079                 glReadPixels(0, 0, sw, sh, GL_RGBA, GL_UNSIGNED_BYTE, ptr);
080                 if (glGetError() == GL_NO_ERROR) {
081                     *heap = base;
082                     *w = sw;
083                     *h = sh;
084                     *f = PIXEL_FORMAT_RGBA_8888;
085                     result = NO_ERROR;
086                 }
087             else {
088                 result = NO_MEMORY;
089             }
090         }
091         glEnable(GL_SCISSOR_TEST);
092         glViewport(0, 0, hw_w, hw_h);
093         glMatrixMode(GL_PROJECTION);
094         glPopMatrix();
095         glMatrixMode(GL_MODELVIEW);
096  
097  
098     else {
099         result = BAD_VALUE;
100     }
101  
102     // release FBO resources
103     glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
104     glDeleteRenderbuffersOES(1, &tname);
105     glDeleteFramebuffersOES(1, &name);
106  
107     hw.compositionComplete();
108  
109     return result;
110 }
111  
112  
113 status_t SurfaceFlinger::captureScreen(DisplayID dpy,
114         sp* heap,
115         uint32_t* width, uint32_t* height, PixelFormat* format,
116         uint32_t sw, uint32_t sh)
117 {
118            LOGI("into captureScreen");          
119     // only one display supported for now
120     if (UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT))
121         return BAD_VALUE;
122  
123     if (!GLExtensions::getInstance().haveFramebufferObject())
124         return INVALID_OPERATION;
125  
126     class MessageCaptureScreen : public MessageBase {
127         SurfaceFlinger* flinger;
128         DisplayID dpy;
129         sp* heap;
130         uint32_t* w;
131         uint32_t* h;
132         PixelFormat* f;
133         uint32_t sw;
134         uint32_t sh;
135         status_t result;
136     public:
137         MessageCaptureScreen(SurfaceFlinger* flinger, DisplayID dpy,
138                 sp* heap, uint32_t* w, uint32_t* h, PixelFormat* f,
139                 uint32_t sw, uint32_t sh)
140             : flinger(flinger), dpy(dpy),
141               heap(heap), w(w), h(h), f(f), sw(sw), sh(sh), result(PERMISSION_DENIED)
142         {
143  
144

你可能感兴趣的:(android)