4

I want to take screenshot programmatically. I have taken the below class fro this http://www.pocketmagic.net/?p=1473, but its not take take screenshot. to debug the code when I try to debug code using

 __android_log_print(ANDROID_LOG_DEBUG,DEBUG_TAG,"messsage");

it does not recognize ANDROID_LOG_DEBUG give me error on this Symbol 'ANDROID_LOG_DEBUG' could not be resolved rather i had include android/log.h

Please Help to solve this problem.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <time.h>
#include <linux/fb.h>
#include <linux/kd.h>
#include <jni.h>
#include "pixelflinger.h"
#include<sys/syscall.h>
#include<sys/stat.h>
#include <string.h>
#include <android/log.h>

typedef struct {
     long filesize;
     char reserved[2];
     long headersize;
     long infoSize;
     long width;
     long depth;
     short biPlanes;
     short bits;
     long biCompression;
     long biSizeImage;
     long biXPelsPerMeter;
     long biYPelsPerMeter;
     long biClrUsed;
     long biClrImportant;
} BMPHEAD;

//copyright text
char cprght[255]="Copyright(C)2009 Motisan Radu , All rights reserved.\n radu.motisan@gmail.com";
//surface pointer
static GGLSurface gr_framebuffer[2];
//handler
static int gr_fb_fd = -1;
//v screen info
static struct fb_var_screeninfo vi;
//f screen info
struct fb_fix_screeninfo fi;

static void dumpinfo(struct fb_fix_screeninfo *fi,
                     struct fb_var_screeninfo *vi);

static int get_framebuffer(GGLSurface *fb)
{
    int fd;
    void *bits;

    fd = open("/dev/graphics/fb0", O_RDWR);
    if(fd < 0) {
        perror("cannot open fb0");
        return -1;
    }

    if(ioctl(fd, FBIOGET_FSCREENINFO, &fi) < 0) {
        perror("failed to get fb0 info");
        return -1;
    }

    if(ioctl(fd, FBIOGET_VSCREENINFO, &vi) < 0) {
        perror("failed to get fb0 info");
        return -1;
    }

    //dumpinfo(&fi, &vi);

    bits = mmap(0, fi.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if(bits == MAP_FAILED) {
        perror("failed to mmap framebuffer");
        return -1;
    }

    fb->version = sizeof(*fb);
    fb->width = vi.xres;
    fb->height = vi.yres;
    fb->stride = fi.line_length / (vi.bits_per_pixel >> 3);
    fb->data = bits;
    fb->format = GGL_PIXEL_FORMAT_RGB_565;

    fb++;

    fb->version = sizeof(*fb);
    fb->width = vi.xres;
    fb->height = vi.yres;
    fb->stride = fi.line_length / (vi.bits_per_pixel >> 3);
    fb->data = (void*) (((unsigned) bits) + vi.yres * vi.xres * 2);
    fb->format = GGL_PIXEL_FORMAT_RGB_565;

    return fd;
}


static void dumpinfo(struct fb_fix_screeninfo *fi, struct fb_var_screeninfo *vi)
{
    /*fprintf(stderr,"vi.xres = %d\n", vi->xres);
    fprintf(stderr,"vi.yres = %d\n", vi->yres);
    fprintf(stderr,"vi.xresv = %d\n", vi->xres_virtual);
    fprintf(stderr,"vi.yresv = %d\n", vi->yres_virtual);
    fprintf(stderr,"vi.xoff = %d\n", vi->xoffset);
    fprintf(stderr,"vi.yoff = %d\n", vi->yoffset);
    fprintf(stderr, "vi.bits_per_pixel = %d\n", vi->bits_per_pixel);

    fprintf(stderr, "fi.line_length = %d\n", fi->line_length);*/

}


//int main(int argc, char **argv)
jint Java_com_example_JazzkActivity_stringFromJNI( JNIEnv* env, jobject thiz )
//int main(int argc, char **argv)
{

  __android_log_print(ANDROID_LOG_DEBUG,DEBUG_TAG,"messsage");
 //get screen capture
  gr_fb_fd = get_framebuffer(gr_framebuffer);
  if (gr_fb_fd <= 0) exit(1);
  //__android_log_print(ANDROID_API_LEVEL_H);
  int w = vi.xres, h = vi.yres, depth = vi.bits_per_pixel;

  //convert pixel data
  uint8_t *rgb24;
  if (depth == 16)
  {
    rgb24 = (uint8_t *)malloc(w * h * 3);
    int i = 0;
    for (;i<w*h;i++)
    {
        uint16_t pixel16 = ((uint16_t *)gr_framebuffer[0].data)[i];
        // RRRRRGGGGGGBBBBBB -> RRRRRRRRGGGGGGGGBBBBBBBB
        // in rgb24 color max is 2^8 per channel (*255/32 *255/64 *255/32)
        rgb24[3*i+2]   = (255*(pixel16 & 0x001F))/ 32;      //Blue
        rgb24[3*i+1]   = (255*((pixel16 & 0x07E0) >> 5))/64;    //Green
        rgb24[3*i]     = (255*((pixel16 & 0xF800) >> 11))/32;   //Red
    }
  }
  else
  if (depth == 24) //exactly what we need
  {
    rgb24 = (uint8_t *) gr_framebuffer[0].data;
  }
  else
  if (depth == 32) //skip transparency channel
  {
      rgb24 = (uint8_t *) malloc(w * h * 3);
      //rgb24 = new uint8_t[w * h * 3];
    int i=0;
    for (;i<w*h;i++)
    {
        uint32_t pixel32 = ((uint32_t *)gr_framebuffer[0].data)[i];
        // in rgb24 color max is 2^8 per channel
        rgb24[3*i+0]   =  pixel32 & 0x000000FF;         //Blue
        rgb24[3*i+1]   = (pixel32 & 0x0000FF00) >> 8;   //Green
        rgb24[3*i+2]   = (pixel32 & 0x00FF0000) >> 16;  //Red
    }
  }
  else
  {
    //free
        close(gr_fb_fd);
    exit(2);
  };
  //save RGB 24 Bitmap
  int bytes_per_pixel = 3;
  BMPHEAD bh;
  memset ((char *)&bh,0,sizeof(BMPHEAD)); // sets everything to 0
  //bh.filesize  =   calculated size of your file (see below)
  //bh.reserved  = two zero bytes
  bh.headersize  = 54L;         // for 24 bit images
  bh.infoSize  =  0x28L;        // for 24 bit images
  bh.width     = w;         // width of image in pixels
  bh.depth     = h;         // height of image in pixels
  bh.biPlanes  =  1;            // for 24 bit images
  bh.bits      = 8 * bytes_per_pixel;   // for 24 bit images
  bh.biCompression = 0L;        // no compression
  int bytesPerLine;
  bytesPerLine = w * bytes_per_pixel;   // for 24 bit images
  //round up to a dword boundary
  if (bytesPerLine & 0x0003)
  {
        bytesPerLine |= 0x0003;
        ++bytesPerLine;
  }
  bh.filesize = bh.headersize + (long)bytesPerLine * bh.depth;
  FILE * bmpfile;
  //printf("Bytes per line : %d\n", bytesPerLine);
  bmpfile = fopen("screen.bmp", "wb");
  if (bmpfile == NULL)
  {
    close(gr_fb_fd);
    //exit(3);
  }
  fwrite("BM",1,2,bmpfile);
  fwrite((char *)&bh, 1, sizeof (bh), bmpfile);
  //fwrite(rgb24,1,w*h*3,bmpfile);
  char *linebuf;
  linebuf = (char *) calloc(1, bytesPerLine);
  if (linebuf == NULL)
  {
        fclose(bmpfile);
    close(gr_fb_fd);
    exit(4);
  }
  int line,x;
  for (line = h-1; line >= 0; line --)
  {
        // fill line linebuf with the image data for that line
    for( x =0 ; x < w; x++ )
    {
        *(linebuf+x*bytes_per_pixel) = *(rgb24 + (x+line*w)*bytes_per_pixel+2);
        *(linebuf+x*bytes_per_pixel+1) = *(rgb24 + (x+line*w)*bytes_per_pixel+1);
        *(linebuf+x*bytes_per_pixel+2) = *(rgb24 + (x+line*w)*bytes_per_pixel+0);
    }
    // remember that the order is BGR and if width is not a multiple
        // of 4 then the last few bytes may be unused
    fwrite(linebuf, 1, bytesPerLine, bmpfile);
  }
  fclose(bmpfile);
  close(gr_fb_fd);
  return 0;
}

Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_LDLIBS    := -llog
LOCAL_MODULE    := jazzk
### Add all source file names to be included in lib separated by a whitespace
LOCAL_SRC_FILES := capturescr.c

include $(BUILD_SHARED_LIBRARY)

Thanks in advance

If anyone Know other way to implement screenshot programmatically then please post.

Karan
  • 497
  • 10
  • 23

2 Answers2

0

I have built your code, and it works great when call the jni. I just remove __android_log_print(ANDROID_LOG_DEBUG,DEBUG_TAG,"messsage") the tag, and build in the Android source code project.

You just need to put the .so file to your Java project. I don't try the NDK to build.

Brad Larson
  • 170,088
  • 45
  • 397
  • 571
robben
  • 9
  • 1
  • 1
    finally I am able to do by adding the following path project->properties->C/C++ General->path and symbols->Add 1. C:\eclipse\android-ndk-r8-windows\android-ndk-r8\platforms\android-14\arch-arm\usr\include 2. C:\eclipse\android-ndk-r8-windows\android-ndk-r8\toolchains\arm-linux-androideabi-4.4.3\prebuilt\windows\lib\gcc\arm-linux-androideabi\4.4.3\include – Karan Aug 06 '12 at 07:27
  • @robben - removing the triggering code is a pretty poor solution, as then one does not benefit from its intended functionality. As we see from Karan's comment, there's actually nothing wrong with the code or the NDK, rather the issue is with the misconfiguration of the Eclipse CDT, causing it to generate "errors" not representative of what will happen with an actual build using ndk-build. – Chris Stratton Apr 03 '14 at 00:58
0

Had same issue in latest ADT(22.6.2 bundle, which has Eclipse 4.3.1), NDK(r9d). Solved by wiping the whole thing, installing ADT(22.0.5 bundle from Aug31,Sept4/2013, which has Eclipse 4.2.1), NDK(r9b).

Community
  • 1
  • 1
alexey
  • 453
  • 6
  • 15
  • Actually, even in this setup the problem showed up again. Cleaning the project and Project -> Build Project (I have Build Automatically disabled) recreated the .so library and all the symbols are now properly found. – alexey Apr 17 '14 at 01:10