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 status = GP_OK; int w, h = 0, k; int i,j; int b = 0; int compressed = 0; unsigned char header[5] = "\xff\xff\xff\xff\x55"; unsigned int size; unsigned char *data; unsigned char *image_start; unsigned char *p_data=NULL; unsigned char *ppm=NULL, *ptr=NULL; unsigned char gtable[256]; unsigned char temp; GP_DEBUG ("Downloading pictures!\n"); /* These are cheap cameras. There ain't no EXIF data. So kill this. */ if (GP_FILE_TYPE_EXIF == type) return GP_ERROR_FILE_EXISTS; /* Get the number of the photo on the camera */ k = gp_filesystem_number (camera->fs, "/", filename, context); GP_DEBUG ("Filesystem number is %i\n",k); b = jl2005a_get_pic_data_size(camera->port, k); GP_DEBUG("b = %i = 0x%x bytes\n", b,b); w = jl2005a_get_pic_width(camera->port); GP_DEBUG ("width is %i\n", w); h = jl2005a_get_pic_height(camera->port); GP_DEBUG ("height is %i\n", h); /* Image data to be downloaded contains header and footer bytes */ data = malloc (b+14); if (!data) return GP_ERROR_NO_MEMORY; jl2005a_read_picture_data (camera, camera->port, data, b+14); if (memcmp(header,data,5) != 0) /* Image data is corrupted! Repeat the operation. */ jl2005a_read_picture_data (camera, camera->port, data, b+14); if (GP_FILE_TYPE_RAW == type) { gp_file_set_mime_type(file, GP_MIME_RAW); gp_file_set_name(file, filename); gp_file_set_data_and_size(file, (char *)data , b+14 ); return GP_OK; } /* Now get ready to put the data into a PPM image file. */ p_data = malloc( w*h ); if (!p_data) { status = GP_ERROR_NO_MEMORY; goto end; } image_start=data+5; if (w == 176) { for (i=1; i < h; i +=4){ for (j=1; j< w; j ++){ temp=image_start[i*w+j]; image_start[i*w+j] = image_start[(i+1)*w+j]; image_start[(i+1)*w+j] = temp; } } if (h == 72) { compressed = 1; h = 144; } } else if (h == 144) { compressed = 1; h = 288; } p_data = malloc( w*h ); if (!p_data) { status = GP_ERROR_NO_MEMORY; goto end; } if (compressed) jl2005a_decompress (image_start, p_data, w, h); else memcpy(p_data, image_start, w*h); ppm = malloc (w * h * 3 + 256); /* room for data and header */ if (!ppm) { status = GP_ERROR_NO_MEMORY; goto end; } sprintf ((char *)ppm, "P6\n" "# CREATOR: gphoto2, JL2005A library\n" "%d %d\n" "255\n", w, h); size = strlen ((char *)ppm); ptr = ppm + size; size = size + (w * h * 3); GP_DEBUG ("size = %i\n", size); gp_ahd_decode (p_data, w , h, ptr, BAYER_TILE_BGGR); free(p_data); gp_gamma_fill_table (gtable, .65); gp_gamma_correct_single (gtable, ptr, w * h); gp_file_set_mime_type (file, GP_MIME_PPM); gp_file_set_name (file, filename); gp_file_set_data_and_size (file, (char *)ppm, size); end: free(data); return status; return GP_OK; }
static int get_file_func(CameraFilesystem *fs, const char *folder, const char *filename, CameraFileType type, CameraFile *file, void *user_data, GPContext *context) { int status = GP_OK; Camera *camera = user_data; int w, h, b; int k, next; unsigned char comp_ratio; unsigned char lighting; unsigned char *data = NULL; unsigned char *p_data = NULL; unsigned char *ppm; unsigned char *ptr; unsigned char gtable[256]; int size; if (!camera->pl->init_done) digi_init (camera->port, camera->pl); /* Get the entry number of the photo on the camera */ k = gp_filesystem_number (camera->fs, "/", filename, context); if (GP_FILE_TYPE_EXIF ==type) return GP_ERROR_FILE_EXISTS; if (GP_FILE_TYPE_RAW!=type && GP_FILE_TYPE_NORMAL != type && GP_FILE_TYPE_PREVIEW != type) { return GP_ERROR_NOT_SUPPORTED; } next = camera->pl->last_fetched_entry +1; while (next < k) { b = digi_get_data_size (camera->pl, next); data = malloc(b); if(!data) return GP_ERROR_NO_MEMORY; digi_read_picture_data (camera->port, data, b, next); free(data); next ++; } comp_ratio = digi_get_comp_ratio (camera->pl, k); w = digi_get_picture_width (camera->pl, k); switch (w) { case 176: h = 144; break; case 640: h = 480; break; case 320: h = 240; break; default: h = 288; break; } lighting = camera->pl->catalog[k*0x10+0x0b]; b = digi_get_data_size (camera->pl, k); if (!b) { GP_DEBUG("Photo number %i deleted?\n",k+1); camera->pl->last_fetched_entry = k; return GP_OK; } data = malloc (w*h); if(!data) return GP_ERROR_NO_MEMORY; GP_DEBUG("Fetch entry %i\n", k); digi_read_picture_data (camera->port, data, b, k); camera->pl->last_fetched_entry = k; if (GP_FILE_TYPE_RAW == type) { /* type is GP_FILE_TYPE_RAW */ size = b; gp_file_set_mime_type (file, GP_MIME_RAW); gp_file_append(file, (char *)data, size); /* Save photo's catalog entry as a footer for the raw file */ gp_file_append(file, (char *)camera->pl->catalog + k * 0x10, 0x10); /* Reset camera when done, for more graceful exit. */ if (k +1 == camera->pl->nb_entries) { digi_rewind (camera->port, camera->pl); } free(data); return(GP_OK); } /* * Now put the data into a PPM image file. */ ppm = malloc (w * h * 3 + 256); /* room for data + header */ if (!ppm) { status = GP_ERROR_NO_MEMORY; goto end; } snprintf ((char *)ppm, 64, "P6\n" "# CREATOR: gphoto2, SQ905C library\n" "%d %d\n" "255\n", w, h); size = strlen ((char *)ppm); ptr = ppm + size; size = size + (w * h * 3); GP_DEBUG ("size = %i\n", size); p_data = malloc(w * h); if (!p_data) { status = GP_ERROR_NO_MEMORY; goto end; } if(comp_ratio) { digi_decompress (p_data, data, w, h); } else memcpy(p_data, data, w * h); gp_ahd_decode(p_data, w , h , ptr, BAYER_TILE_BGGR); free(p_data); digi_postprocess(w, h, ptr); if (lighting < 0x40) { GP_DEBUG( "Low light condition. Using default gamma. \ No white balance.\n"); gp_gamma_fill_table (gtable, .65); gp_gamma_correct_single(gtable,ptr,w*h); } else
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 i, w, h, b, entry, frame, is_in_clip; int nb_frames, to_fetch; int do_preprocess; unsigned char comp_ratio; unsigned char *frame_data, *rawdata; unsigned char *ppm, *ptr; unsigned char gtable[256]; int size; int this_cam_tile; if (GP_FILE_TYPE_EXIF ==type) return GP_ERROR_FILE_EXISTS; 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 = -1; if (0==strcmp(folder, "/")) { i = atoi(filename+4); do { do entry++; while (sq_is_clip(camera->pl, entry) && entry<camera->pl->nb_entries); i--; } while (i>0); if (entry == camera->pl->nb_entries) return GP_ERROR_FILE_NOT_FOUND; frame = 0; is_in_clip = 0; } else { i = atoi(folder+1+4); do { do entry++; while (!sq_is_clip(camera->pl, entry) && entry<camera->pl->nb_entries); i--; } while (i>0); if (entry == camera->pl->nb_entries) return GP_ERROR_DIRECTORY_NOT_FOUND; frame = atoi(filename+4)-1; if (frame >= sq_get_num_frames(camera->pl, entry)) return GP_ERROR_FILE_NOT_FOUND; is_in_clip = 1; } GP_DEBUG ("Download file %s from %s, entry = %d, frame = %d\n", filename, folder, entry, frame); /* Fetch entries until the one we need, and toss all before * 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 to be. */ GP_DEBUG ("last entry was %d\n", camera->pl->last_fetched_entry); /* Change register to DATA, but only if necessary */ if ((camera->pl->last_fetched_entry == -1) || ((is_in_clip) && (frame == 0)) ) sq_access_reg(camera->port, DATA); if (camera->pl->last_fetched_entry > entry) { sq_rewind(camera->port, camera->pl); } do_preprocess = 0; do { to_fetch = camera->pl->last_fetched_entry; if (to_fetch < entry) { to_fetch++; free(camera->pl->last_fetched_data); camera->pl->last_fetched_data = NULL; } nb_frames = sq_get_num_frames(camera->pl, to_fetch); comp_ratio = sq_get_comp_ratio (camera->pl, to_fetch); w = sq_get_picture_width (camera->pl, to_fetch); switch (w) { case 176: h = 144; break; case 640: h = 480; break; case 320: h = 240; break; default: h = 288; break; } b = nb_frames * w * h / comp_ratio; do_preprocess = 1; if (camera->pl->last_fetched_data) break; camera->pl->last_fetched_data = malloc (nb_frames*w*h); if (!camera->pl->last_fetched_data) { sq_rewind(camera->port, camera->pl); return GP_ERROR_NO_MEMORY; } GP_DEBUG("Fetch entry %i\n", to_fetch); sq_read_picture_data (camera->port, camera->pl->last_fetched_data, b); camera->pl->last_fetched_entry = to_fetch; } while (camera->pl->last_fetched_entry<entry); frame_data = camera->pl->last_fetched_data+(w*h)*frame/comp_ratio; /* sq_preprocess ( ) turns the photo right-side-up and for some * models must also de-mirror the photo */ if (GP_FILE_TYPE_RAW!=type) { if (do_preprocess) { sq_preprocess(camera->pl->model, comp_ratio, is_in_clip, frame_data, w, h); } /* * Now put the data into a PPM image file. */ ppm = malloc (w * h * 3 + 256); /* room for data + header */ if (!ppm) { return GP_ERROR_NO_MEMORY; } sprintf ((char *)ppm, "P6\n" "# CREATOR: gphoto2, SQ905 library\n" "%d %d\n" "255\n", w, h); size = strlen ((char *)ppm); ptr = ppm + size; switch (camera->pl->model) { case SQ_MODEL_POCK_CAM: case SQ_MODEL_MAGPIX: this_cam_tile = BAYER_TILE_GBRG; break; default: this_cam_tile = BAYER_TILE_BGGR; break; } size = size + (w * h * 3); GP_DEBUG ("size = %i\n", size); if (comp_ratio>1) { rawdata = malloc (w*h); if (!rawdata) return GP_ERROR_NO_MEMORY; sq_decompress (camera->pl->model, rawdata, frame_data, w, h); gp_gamma_fill_table (gtable, .65); } else { rawdata = frame_data; gp_gamma_fill_table (gtable, .55); } gp_ahd_decode (rawdata, w , h , ptr, this_cam_tile); 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); } else { /* type is GP_FILE_TYPE_RAW */ size = w*h/comp_ratio; rawdata = malloc (size+16); if (!rawdata) return GP_ERROR_NO_MEMORY; memcpy (rawdata, frame_data, size); memcpy (rawdata+size,camera->pl->catalog+16*entry,16); gp_file_set_mime_type (file, GP_MIME_RAW); gp_file_set_data_and_size (file, (char *)rawdata, size+16); } /* Reset camera when done, for more graceful exit. */ if ((!(is_in_clip)&&(entry +1 == camera->pl->nb_entries)) || ((is_in_clip)&& (frame +1 == nb_frames ))) sq_reset (camera->port); return GP_OK; }