コード例 #1
0
ファイル: library.c プロジェクト: Dvizhenka/libgphoto2
static int
camera_capture_preview (Camera *camera, CameraFile *file, GPContext *context)
{
	unsigned char *frame_data;
	unsigned char *ppm, *ptr;
	unsigned char gtable[256];
	int size;
	int w = 320;
	int h = 240;
	int b=0x12c40;

	camera->pl->last_fetched_data = malloc (b);
	if (!camera->pl->last_fetched_data) {
		sq_rewind(camera->port, camera->pl);
		return GP_ERROR_NO_MEMORY;
	}

        sq_access_reg(camera->port, CAPTURE);
	sq_read_picture_data (camera->port, camera->pl->last_fetched_data, b);
	frame_data = camera->pl->last_fetched_data + 0x40;
	sq_preprocess(camera->pl->model, 1, 0, frame_data, w, h);

	/* Now put the data into a PPM image file. */
	ppm = malloc (w * h * 3 + 256);
	if (!ppm)
		return GP_ERROR_NO_MEMORY;
	sprintf ((char *)ppm,
		"P6\n"
		"# CREATOR: gphoto2, SQ905 library\n"
		"%d %d\n"
		"255\n", w, h);
	ptr = ppm + strlen ((char*)ppm);
	size = strlen ((char*)ppm) + (w * h * 3);
	GP_DEBUG ("size = %i\n", size);
	switch (camera->pl->model) {
	case SQ_MODEL_POCK_CAM:
		gp_bayer_decode (frame_data, w , h , ptr, BAYER_TILE_GBRG);
		break;
	default:
		gp_bayer_decode (frame_data, w , h , ptr, BAYER_TILE_BGGR);
		break;
	}

	/* TO DO: 
	 * Adapt some postprocessing routine to work here, because results
	 * can vary greatly, depending both on lighting conditions and on
	 * camera model.
	 */

	gp_gamma_fill_table (gtable, .5);
	gp_gamma_correct_single (gtable, ptr, w * h);
	gp_file_set_mime_type (file, GP_MIME_PPM);
	gp_file_set_data_and_size (file, (char *)ppm, size);

	sq_reset(camera->port);
        sq_access_reg(camera->port, CAPTURE);
	sq_reset(camera->port);

	return (GP_OK);
}
コード例 #2
0
ファイル: ultrapocket.c プロジェクト: AleksKolkov/libgphoto2
/* Different camera types (pocket digital/generic)
 * use a different protocol - have to differetiate.
 */
int
ultrapocket_getpicture(Camera *camera, GPContext *context, unsigned char **pdata, int *size, const char *filename)
{
    char	   *savelocale;
    char           ppmheader[200];
    unsigned char *rawdata,*outdata;
    int            width, height, result;
    size_t         outsize;
    int            imgstart = 0;
    int            pc, pmmhdr_len;
    BayerTile      tile;
#if DO_GAMMA
    unsigned char  gtable[256];
#endif

    switch (camera->pl->up_type) {
     case BADGE_CARDCAM:
     case BADGE_FLATFOTO:
     case BADGE_GENERIC:
     case BADGE_ULTRAPOCKET:
     case BADGE_AXIA:
	CHECK_RESULT(getpicture_generic(camera, context, &rawdata, &width, &height, &imgstart, filename));
	break;
     case BADGE_LOGITECH_PD:
	CHECK_RESULT(getpicture_logitech_pd(camera, context, &rawdata, filename));
	width = 640;
	height = 480;
	imgstart = 0x29;
	break;
     default:
	return GP_ERROR;
    }

   tile = BAYER_TILE_BGGR;

   savelocale = setlocale (LC_ALL, "C");
   snprintf (ppmheader, sizeof(ppmheader), "P6\n"
	    "# CREATOR: gphoto2, ultrapocket library,"
	    " assuming Bayer tile %s, interpolated"
#if DO_GAMMA
	    ", gamma %.2f"
#endif
	    "\n%d %d\n"
	    "255\n", BayerTileNames[tile], 
#if DO_GAMMA
	    GAMMA_NUMBER,
#endif
	    width, height);
   setlocale (LC_ALL, savelocale);

   /* Allocate memory for Interpolated ppm image */
   pmmhdr_len = strlen(ppmheader);
   outsize = ((long)width + 4) * height * 3 + pmmhdr_len;
   outdata = malloc(outsize);
   if (!outdata) {
     free (rawdata);
     return (GP_ERROR_NO_MEMORY);
   }

   /* Set header */
   strcpy((char *)outdata, ppmheader);

   /* Decode and interpolate the Bayer tiles */
   result = gp_bayer_decode((rawdata+imgstart), width+4, height,
			    &outdata[pmmhdr_len], tile);

   /* and chop the spare 4 pixels off the RHS */
   for (pc = 1; pc < height; pc++) {
      memmove(outdata + pmmhdr_len + ((long)width * pc * 3), 
              outdata + pmmhdr_len + (((long)width + 4) * pc * 3), 
              ((long)width) * 3);
   }
   /* modify outsize to reflect trim */
   outsize = ((long)width) * height * 3 + pmmhdr_len;

   free(rawdata);
   if (result < 0) {
      free (outdata);
      return (result);
   }

#if DO_GAMMA
   gp_gamma_fill_table(gtable, GAMMA_NUMBER);
   gp_gamma_correct_single(gtable, &outdata[pmmhdr_len], height * width);
#endif

   *pdata = outdata;
   *size  = outsize;
   return GP_OK;
}
コード例 #3
0
ファイル: jamcam.c プロジェクト: CastorGemini/libgphoto2
static int get_file_func (CameraFilesystem *fs, const char *folder,
			  const char *filename, CameraFileType type,
			  CameraFile *file, void *user_data, GPContext *context)
{
	Camera *camera = user_data;
	char *raw, *ppm;
	unsigned char gtable[256];
	char *ptr;
	int size = 0, n = 0;
	int width, height;
	struct jamcam_file *jc_file;

	GP_DEBUG ("* camera_file_get");
	GP_DEBUG ("*** folder: %s", folder);
	GP_DEBUG ("*** filename: %s",filename);
	GP_DEBUG ("*** type: %d", type);

	CHECK (n = gp_filesystem_number (camera->fs, folder,
					 filename, context));

	if (gp_context_cancel (context) == GP_CONTEXT_FEEDBACK_CANCEL)
		return (GP_ERROR_CANCEL);

	raw = malloc(640*480 * 3);
	ppm = malloc(640*480 * 3 + 200);
	
	switch (type) {
	case GP_FILE_TYPE_PREVIEW:

		CHECK_free (jamcam_request_thumbnail (camera, file, raw, &size, n, context));


		width = 80;
		height = 60;

		sprintf( ppm,
			"P6\n"
			"# CREATOR: gphoto2, jamcam library\n"
			"%d %d\n"
			"255\n", width, height );

		ptr = ppm + strlen( ppm );

		size = strlen( ppm ) + ( height * width * 3 );

		gp_bayer_decode(raw, width, height, ptr, BAYER_TILE_GBRG );
		gp_gamma_fill_table( gtable, 0.5 );
		gp_gamma_correct_single( gtable, ptr, height * width );

		CHECK_free (gp_file_set_mime_type (file, GP_MIME_PPM));
		CHECK_free (gp_file_append (file, ppm, size));
		break;

	case GP_FILE_TYPE_NORMAL:
		CHECK_free (jamcam_request_image (camera, file, raw, &size, n, context));

		jc_file = jamcam_file_info (camera, n);

		sprintf( ppm,
			"P6\n"
			"# CREATOR: gphoto2, jamcam library\n"
			"%d %d\n"
			"255\n", jc_file->width, jc_file->height );

		ptr = ppm + strlen( ppm );

		size = strlen( ppm ) + ( jc_file->width * jc_file->height * 3 );

		gp_bayer_decode( raw, jc_file->width, jc_file->height, ptr,
			BAYER_TILE_GBRG );
		gp_gamma_fill_table( gtable, 0.5 );
		gp_gamma_correct_single( gtable, ptr, jc_file->width * jc_file->height );

		CHECK_free (gp_file_set_mime_type (file, GP_MIME_PPM));
		CHECK_free (gp_file_append (file, ppm, size));
		break;

	case GP_FILE_TYPE_RAW:
		CHECK_free (jamcam_request_image (camera, file, raw, &size, n, context));
		CHECK_free (gp_file_set_mime_type (file, GP_MIME_RAW));
		CHECK_free (gp_file_append (file, raw, size));
		break;
	default:
		free(raw); free(ppm);
		return (GP_ERROR_NOT_SUPPORTED);
	}
	free(raw); free(ppm);
	return (GP_OK);
}
コード例 #4
0
int main(int argc, char *argv[])
{
	
	image_info *info;


	int i;
	BYTE *bufp;
	BYTE *ppm, *ptr;
	FILE *fp_src, *fp_dest;
	char *dest;
	BYTE invert=0;
	BYTE qvga = 0;
	int size;
	float gamma_factor;
	BYTE gtable[256];
	int b;
	BYTE *buf;
	BYTE *buf2;
	int WIDTH=176, HEIGHT=144;
	BYTE outdoors;
        GtkWidget *window;
	GtkWidget *image;
	GtkWidget *event_box;
	int current = 1;
	int offset_correct = 0;

	if ( !(argc > 1) ){
		printf("Syntax: show_sonix_raw sourcefile, or \n");
		printf("Syntax: show_sonix_raw -useoffset sourcefile, or \n");
		printf("Syntax: show_sonix_raw -useoffset -invert sourcefile\n");
		return 0;
	}

	if ((strcmp(argv[current], "-qvga") == 0) && (current+1 < argc)) 
	{ 
		qvga = 1;
		offset_correct=8;
		current += 1;
		if (argc != 3) {
			printf("Syntax: show_sonix_raw -qvga sourcefile\n");
			return 0;
		}
	}


	if ( !(argc > 2) && (strcmp(argv[current], "-useoffset") == 0) )
	{
		printf("Syntax: show_sonix_raw sourcefile, or \n");
		printf("Syntax: show_sonix_raw -useoffset sourcefile \n");
		printf("Syntax: show_sonix_raw -useoffset -invert sourcefile\n");
		return 0;
	}

		printf("argc=%i\n", argc);


	if ((strcmp(argv[current], "-useoffset") == 0) && (current+1 < argc)) {
		offset_correct = 8;
		current += 1;
		printf("useoffset option used\n");
		printf("current=%i\n", current);
		if ( !(argc > 2) || !(argc < 5) ){
			printf("Syntax: show_sonix_raw sourcefile, or \n");
			printf("Syntax: show_sonix_raw -useoffset sourcefile, or \n");
			printf("Syntax: show_sonix_raw -useoffset -invert sourcefile, or\n");
			printf("Syntax: show_sonix_raw -qvga sourcefile\n");
			return 0;
		}
	}

	if ( !(argc > 3) && (strcmp(argv[current], "-invert") == 0) )
	{
		printf("Syntax: show_sonix_raw sourcefile, or \n");
		printf("Syntax: show_sonix_raw -useoffset sourcefile, or \n");
		printf("Syntax: show_sonix_raw -useoffset -invert sourcefile\n");
		return 0;
	}

	if ((strcmp(argv[current], "-invert") == 0) && (current+1 < argc)) {
		invert = 1;
		current += 1;
		printf("invert option used\n");
		printf("current=%i\n", current);
		if ( !(argc > 3) || !(argc < 5) ){
			printf("Syntax: show_sonix_raw sourcefile, or \n");
			printf("Syntax: show_sonix_raw -useoffset sourcefile, or \n");
			printf("Syntax: show_sonix_raw -useoffset -invert sourcefile \n");
			return 0;
		}

	}

	printf("Options: offset=%i invert=%i\n", offset_correct, invert);


	fprintf (stderr, "Name of source file is %s\n", argv[current]);
	
	/* input file is raw_(some characters).raw, so, first thing, we find 
	 * the "." in the name.
	 */

	dest = malloc(strlen(argv[current]));
	if (!dest){
		free(dest);
		return -1;
	}

	if ((!strchr(argv[current], 0x2e))|| (strncmp(argv[current], "raw", 3))) {
		fprintf (stderr, "Source file appears not to be a gphoto2 raw file.\n");
		fprintf (stderr, "Its name should begin with raw_ and end with .raw\n");		
		fprintf (stderr, "Exiting.\n");
		return 0; 
	}

	i = strchr(argv[current], 0x2e) - argv[current];

	/* and throw away the period (to avoid clobbering any finished images
	 * from gphoto2 which are in the same directory) and throw away the 
	 * suffix.
	 */

	strncpy(dest, argv[current] + 4, i - 4);
	/* then affix "ppm" as a suffix (no preceding period) */
	strcat (dest, "ppm");
	fprintf (stderr, "Destination file will be called %s\n", dest);
	/* now open the raw file */
	if ( (fp_src = fopen(argv[current], "rb") ) == NULL )
	{
		fprintf (stderr, "Error opening source file.\n");
		return 0;
	}
	/* get the size of the raw file and assign that size to "b" */    
	fseek(fp_src, 0, 2);
	b = ftell(fp_src);
	fseek(fp_src, 0, 0);

	buf = malloc(b);
	if (!buf) return -1;

	/* read the raw file to "buf", and close it */
	fread (buf, 1, b, fp_src);
	fclose (fp_src);

	info = malloc(512);
	if (!info) { free(info); return -1; }


	get_image_info( info, buf, b, qvga);

	/* If there is a header, then we print it as debug output, then 
	 * move past it, to the data. 
	 */
	bufp = buf+offset_correct;
	/* show header */
	for (i = 0; i < HEADER_LEN; i++) {
		fprintf(stderr, " %02X", buf[i]);
	}
	fprintf(stderr, "\n");

	WIDTH = info->width;
	HEIGHT = info->height;
	outdoors = info->outdoors;
	gamma_factor = info->gamma;
	gp_gamma_fill_table(gtable, gamma_factor);
	buf2 = malloc(WIDTH * HEIGHT+256);
	if (!buf2) {
		free (buf2);
		return -1;
	}
	if((offset_correct)&&!(qvga)) {
		info->reverse = 1;
		info->bayer = BAYER_TILE_BGGR;
	}
	if (info->compression) { /* non-zero if compression in use */
		sonix_decode(buf2, bufp, WIDTH,HEIGHT);	
	 } else {
		memcpy(buf2, bufp, WIDTH*HEIGHT);
	}
	free(buf);
	if (invert)
		reverse_bytes(buf2, WIDTH*HEIGHT);
	ppm = malloc (WIDTH * HEIGHT * 3 + 256); /* Data + header */
	if (!ppm) {
		free (buf2);
		return 0;
	}

	memset (ppm, 0, WIDTH * HEIGHT * 3 + 256);

	sprintf ((char *)ppm,
        	"P6\n"
        	"#CREATOR: My_decoder\n"
        	"%d %d\n"
        	"255\n", WIDTH, HEIGHT);

        ptr = ppm + strlen ((char *)ppm);
        size = strlen ((char *)ppm) + (WIDTH * HEIGHT * 3);
	gp_bayer_decode(buf2, WIDTH, HEIGHT, ptr, info->bayer);
	free(buf2);
        white_balance(ptr, WIDTH * HEIGHT, 1.2);

	if ( (fp_dest = fopen(dest, "wb") ) == NULL )
	{
		fprintf (stderr, "Error opening dest file.\n");
		return 0;
	}
	fwrite(ppm, 1, size, fp_dest);
	fclose (fp_dest);
	free (ppm);

	/* The file has been saved. The GUI effects follow now. */
        gtk_init (&argc, &argv);
        window = gtk_window_new (GTK_WINDOW_TOPLEVEL);


	event_box = gtk_event_box_new();
	gtk_container_add(GTK_CONTAINER (window), event_box);
	gtk_widget_show(event_box);

	/* This lets the Window Manager to close the window _and_ sets up 
	 * this program to exit when the window is closed. 
	 */

        g_signal_connect (G_OBJECT (window), "delete_event",
                          G_CALLBACK (delete_event), NULL);
	/* This displays the image file. */
	image = gtk_image_new_from_file(dest);
	gtk_container_add(GTK_CONTAINER(event_box), image);
	gtk_widget_show (image);
        gtk_widget_show (window);
        gtk_main ();
	free(info);
	free(dest);
	return 0;
}
コード例 #5
0
ファイル: serial.c プロジェクト: simonswine/libgphoto2
int
jd11_get_image_full(
    Camera *camera, CameraFile*file, int nr, int raw, GPContext *context
) {
    unsigned char	*s,*uncomp[3],**imagebufs;
    int			ret,sizes[3];
    unsigned char	*data;
    int 		h;

    ret = serial_image_reader(camera,file,nr,&imagebufs,sizes, context);
    if (ret!=GP_OK)
	return ret;
    uncomp[0] = malloc(320*480);
    uncomp[1] = malloc(320*480/2);
    uncomp[2] = malloc(320*480/2);
    if (sizes[0]!=115200) {
	    picture_decomp_v1(imagebufs[0],uncomp[0],320,480);
	    picture_decomp_v1(imagebufs[1],uncomp[1],320,480/2);
	    picture_decomp_v1(imagebufs[2],uncomp[2],320,480/2);
    } else {
	    picture_decomp_v2(imagebufs[0],uncomp[0],320,480);
	    picture_decomp_v2(imagebufs[1],uncomp[1],320,480/2);
	    picture_decomp_v2(imagebufs[2],uncomp[2],320,480/2);
    }
    gp_file_append(file, IMGHEADER, strlen(IMGHEADER));
    data = malloc(640*480*3);
    if (!raw) {
	unsigned char *bayerpre;
	s = bayerpre = malloc(640*480);
	/* note that picture is upside down and left<->right mirrored */
	for (h=480;h--;) {
	    int w;
	    for (w=320;w--;) {
		if (h&1) {
		    /* G B G B G B G B G */
		    *s++ = uncomp[2][(h/2)*320+w];
		    *s++ = uncomp[0][h*320+w];
		} else {
		    /* R G R G R G R G R */
		    *s++ = uncomp[0][h*320+w];
		    *s++ = uncomp[1][(h/2)*320+w];
		}
	    }
	}
	gp_bayer_decode(bayerpre,640,480,data,BAYER_TILE_RGGB);
	free(bayerpre);
    } else {
	s=data;
	for (h=480;h--;) { /* upside down */
	    int w;
	    for (w=640;w--;) { /* right to left */
		/* and images are in green red blue */
		*s++=uncomp[1][(h/2)*320+(w/2)];
		*s++=uncomp[0][h*320+(w/2)];
		*s++=uncomp[2][(h/2)*320+(w/2)];
	    }
	}
    }
    free(uncomp[0]);free(uncomp[1]);free(uncomp[2]);
    free(imagebufs[0]);free(imagebufs[1]);free(imagebufs[2]);free(imagebufs);
    gp_file_append(file, (char*)data, 640*480*3);
    free(data);
    return GP_OK;
}
コード例 #6
0
ファイル: library.c プロジェクト: ryanstout/libgphoto2
static int
get_file_func (CameraFilesystem *fs, const char *folder, const char *filename,
	       CameraFileType type, CameraFile *file, void *user_data,
	       GPContext *context)
{
    	Camera *camera = user_data; 

/* The camera will always download the low-resolution pictures first, if any.
 * As those are compressed, they are not of fixed size. Unfortunately, the 
 * compression method is not known. 
 * For a high-resolution picture, the size is always the same. 
 * Every picture file has a header, which is of length 0x98. The high-
 * resolution pictures are just Bayer data; their headers will be discarded.  
 */

        int i, j, k, n, num_lo_pics, num_hi_pics, w = 0, h = 0;  	
	unsigned char temp;
	unsigned char *data;
	unsigned char *p_data = NULL;
	unsigned char *output = NULL;     
	int len;
	int header_len;
	char header[128];	
	unsigned char gtable[256];

	k = gp_filesystem_number(camera->fs, "/", filename, context);


	num_lo_pics = aox_get_num_lo_pics(camera->pl->info);
	num_hi_pics = aox_get_num_hi_pics(camera->pl->info);


	GP_DEBUG("There are %i compressed photos\n", num_lo_pics);
	GP_DEBUG("There are %i hi-res photos\n", num_hi_pics);

	if ( (k < num_lo_pics) ) { 
		n = k; 
		w = 320;
		h = 240;
	} else {
		n = k - num_lo_pics;
		w = 640;	
		h = 480;
	}

	len = aox_get_picture_size (camera->port, num_lo_pics, 
						num_hi_pics, n, k);
	GP_DEBUG("len = %i\n", len);
	data = malloc(len);
	if (!data) {
		printf("Malloc failed\n"); return 0;}
    	aox_read_picture_data (camera->port, (char *)data, len, n);

	switch (type) {
	case GP_FILE_TYPE_EXIF:
		free (data);
		return (GP_ERROR_FILE_EXISTS);

	case GP_FILE_TYPE_PREVIEW:
	case GP_FILE_TYPE_NORMAL:
		if (w == 320) {
			gp_file_detect_mime_type (file); /* Detected as "raw"*/
			gp_file_set_data_and_size (file, (char *)data, len);
			gp_file_adjust_name_for_mime_type (file);
			break;
		}
		if (w == 640) {
			/* Stripping useless header */
			p_data = data + 0x98;
			/* Picture is mirror-imaged.*/
    			for (i = 0; i < h; ++i) {
				for (j = 0 ; j < w/2; j++) { 
        				temp = p_data[w*i +j];
        				p_data[w*i +j] = p_data[w*i+ w -1 -j];
        				p_data[w*i + w  - 1 - j] = temp;
				}
    			}    	
			/* Not only this, but some columns are 
			 * interchanged, too. */
			for (i = 0; i < w*h/4; i++) {
				temp = p_data[4*i +1];
				p_data[4*i + 1] = p_data[4*i+2];
				p_data[4*i+2] = temp;
			}
			/* And now create a ppm file, with our own header */
			header_len = snprintf(header, 127, 
				"P6\n" 
				"# CREATOR: gphoto2, aox library\n" 
				"%d %d\n" 
				"255\n", w, h);

			output = malloc(3*w*h);
			if(!output) {
				free(output);
				return GP_ERROR_NO_MEMORY;
			}	
			if (camera->pl->model == AOX_MODEL_DMAX)
			    gp_bayer_decode (p_data, w, h, 
					output, BAYER_TILE_RGGB);
			else
			    gp_bayer_decode (p_data, w, h, 
					output, BAYER_TILE_GRBG);
			/* gamma correction of .70 may not be optimal. */
			gp_gamma_fill_table (gtable, .65);
			gp_gamma_correct_single (gtable, output, w * h);
    			gp_file_set_mime_type (file, GP_MIME_PPM);
    			gp_file_append (file, header, header_len);
			gp_file_append (file, (char *)output, 3*w*h);
		}
		free (data);
		free (output);
		return GP_OK;
	case GP_FILE_TYPE_RAW:
		gp_file_set_data_and_size (file, (char *)data, len);
		gp_file_set_mime_type (file, GP_MIME_RAW);
		gp_file_adjust_name_for_mime_type(file);
		break;
	default:
		free (data);
		return (GP_ERROR_NOT_SUPPORTED); 	
	}
	return GP_OK;
}
コード例 #7
0
ファイル: library.c プロジェクト: Dvizhenka/libgphoto2
static int
get_file_func (CameraFilesystem *fs, const char *folder, const char *filename,
	       CameraFileType type, CameraFile *file, void *user_data,
	       GPContext *context)
{
    	Camera *camera = user_data;
	int entry, w, h; /* frame; */
	unsigned char *frame_data, *frame_ptr;
	unsigned char *ppm, *ptr;
	unsigned char gtable[256];
	int start;
	int datasize, framesize, hdrsize, ppmsize;
	int nb_frames=1;
	unsigned char buf[0x8000];

#if 0	/* libgphoto2 likes to search in vain for EXIF data, which isn't there.
	   It's a waste of time, and there should be a way to disable it
	   explicitly.  But there isn't.  Un-if this if you don't like it,
	   and you can still retrieve the first frame of a video via the
	   frame filename instead. */
	if (GP_FILE_TYPE_PREVIEW==type)
		return GP_ERROR_NOT_SUPPORTED;
#endif

	if (GP_FILE_TYPE_RAW!=type && GP_FILE_TYPE_NORMAL!=type
		&& GP_FILE_TYPE_PREVIEW!=type) {

		return GP_ERROR_NOT_SUPPORTED;
	}

	/* Get the entry number of the photo on the camera */
	entry = gp_filesystem_number (camera->fs, folder, filename, context);
	if (entry < GP_OK)
		return GP_ERROR_FILE_NOT_FOUND;

	GP_DEBUG ("Download file %s, entry = %d\n",
			filename, entry);

	if (entry >= camera->pl->nb_entries)
		return GP_ERROR_FILE_NOT_FOUND;

	/* Fetch entries until the one we need, and toss all but the one we need.
	 * TODO: Either find out how to use the location info in the catalog to
	 * download just the entry needed, or show it is as impossible as it seems.
	 */

	/* Change register to DATA, but only if necessary */
	if (camera->pl->data_offset == -1) {
		icl_access_reg(camera->port, DATA);

		/* Camera starts at the first picture.. */
		camera->pl->data_offset = icl_get_start (camera->pl, 0);
	}

	start = icl_get_start (camera->pl, entry);
	datasize = icl_get_size (camera->pl, entry);
	/* datasize exceeds the actual datasize by 0x100 bytes, which seems to be
	 * 0x100 bytes of filler at the beginning. For now we will treat this extra
	 * 0x100 bytes as junk and just ditch it.
	 */

	GP_DEBUG ("data offset at %d, picture at %d\n", camera->pl->data_offset, start);

	/* Rewind if we're past the requested picture */
	if (camera->pl->data_offset > start) {
		icl_rewind(camera->port, camera->pl);
	}

	/* Seek to the requested picture */
	while ((camera->pl->data_offset + 0x8000) < start) {
		icl_read_picture_data(camera->port, buf, 0x8000);
		camera->pl->data_offset += 0x8000;
	}
	if (camera->pl->data_offset < start) {
		icl_read_picture_data(camera->port, buf, start - camera->pl->data_offset);
		camera->pl->data_offset = start;
	}

	/* Retrieve frames */
	framesize = datasize;

	frame_data = malloc(datasize);
	if (!frame_data) return GP_ERROR_NO_MEMORY;
	icl_read_picture_data(camera->port, frame_data, datasize);
	camera->pl->data_offset += datasize;

	switch (type) {
	case GP_FILE_TYPE_PREVIEW:
		if (icl_get_width_height (camera->pl, entry, &w, &h) >= GP_OK)
			break; /* Known format, process image */
		/* No previewing of raw data */
		free (frame_data);
		return GP_ERROR_NOT_SUPPORTED;
	case GP_FILE_TYPE_NORMAL:
		if (icl_get_width_height (camera->pl, entry, &w, &h) >= GP_OK)
			break; /* Known format, process image */
		/* Unsupported format, fallthrough to raw */
	case GP_FILE_TYPE_RAW:
		gp_file_set_mime_type (file, GP_MIME_RAW);
		gp_file_adjust_name_for_mime_type (file);
	        gp_file_set_data_and_size (file, (char *)frame_data, datasize);
		return (GP_OK);
	default:
		return GP_ERROR_NOT_SUPPORTED;
	}

	/* Write the frame(s) */
	snprintf((char *)buf, sizeof(buf),
		"P6\n"
		"# CREATOR: gphoto2, iClick library\n"
		"%d %d\n"
		"255\n", w, h);
	hdrsize = strlen((char *)buf);

	ppmsize = (hdrsize + w*h*3) * nb_frames;
	GP_DEBUG ("ppmsize = %i\n", ppmsize);

	ptr = ppm = malloc(ppmsize);

	frame_ptr = frame_data + 0x100;
	/* Here, we just threw away the "superfluous" first 0x100 bytes */
	memcpy(ptr, buf, hdrsize);
	ptr += hdrsize;

	gp_bayer_decode (frame_ptr, w , h , ptr, BAYER_TILE_GBRG);

	gp_gamma_fill_table (gtable, .5);
	/* The gamma factor is pure guesswork; shooting in the dark. This
	 * is the kind of thing which might be hidden in those 0x100 bytes.
	 */

	gp_gamma_correct_single (gtable, ptr, w * h);

	ptr += w*h*3;

	gp_file_set_mime_type (file, GP_MIME_PPM);
	gp_file_set_data_and_size (file, (char *)ppm, ppmsize);
	free (frame_data);
        return GP_OK;
}