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); }
/* 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; }
int mars_white_balance (unsigned char *data, unsigned int size, float saturation, float image_gamma) { int x, r, g, b, max, d; double r_factor, g_factor, b_factor, max_factor; int htable_r[0x100], htable_g[0x100], htable_b[0x100]; unsigned char gtable[0x100]; double new_gamma, gamma=1.0; /* ------------------- GAMMA CORRECTION ------------------- */ histogram(data, size, htable_r, htable_g, htable_b); x = 1; for (r = 48; r < 208; r++) { x += htable_r[r]; x += htable_g[r]; x += htable_r[r]; } new_gamma = sqrt((double) (x * 1.5) / (double) (size * 3)); x=0; GP_DEBUG("Provisional gamma correction = %1.2f\n", new_gamma); /* Recalculate saturation factor for later use. */ saturation=saturation*new_gamma*new_gamma; GP_DEBUG("saturation = %1.2f\n", saturation); if(new_gamma >= 1.0) gamma = new_gamma; else gamma = image_gamma; GP_DEBUG("Gamma correction = %1.2f\n", gamma); gp_gamma_fill_table(gtable, gamma); /* ---------------- BRIGHT DOTS ------------------- */ max = size / 200; histogram(data, size, htable_r, htable_g, htable_b); for (r=0xfe, x=0; (r > 32) && (x < max); r--) x += htable_r[r]; for (g=0xfe, x=0; (g > 32) && (x < max); g--) x += htable_g[g]; for (b=0xfe, x=0; (b > 32) && (x < max); b--) x += htable_b[b]; r_factor = (double) 0xfd / r; g_factor = (double) 0xfd / g; b_factor = (double) 0xfd / b; max_factor = r_factor; if (g_factor > max_factor) max_factor = g_factor; if (b_factor > max_factor) max_factor = b_factor; if (max_factor >= 2.5) { r_factor = (r_factor / max_factor) * 2.5; g_factor = (g_factor / max_factor) * 2.5; b_factor = (b_factor / max_factor) * 2.5; } GP_DEBUG("White balance (bright): r=%1d, g=%1d, b=%1d, fr=%1.3f, fg=%1.3f, fb=%1.3f\n", r, g, b, r_factor, g_factor, b_factor); if (max_factor <= 2.5) { for (x = 0; x < (size * 3); x += 3) { d = (data[x+0]<<8) * r_factor; d >>=8; if (d > 0xff) { d = 0xff; } data[x+0] = d; d = (data[x+1]<<8) * g_factor; d >>=8; if (d > 0xff) { d = 0xff; } data[x+1] = d; d = (data[x+2]<<8) * b_factor; d >>=8; if (d > 0xff) { d = 0xff; } data[x+2] = d; } } /* ---------------- DARK DOTS ------------------- */ max = size / 200; /* 1/200 = 0.5% */ histogram(data, size, htable_r, htable_g, htable_b); for (r=0, x=0; (r < 96) && (x < max); r++) x += htable_r[r]; for (g=0, x=0; (g < 96) && (x < max); g++) x += htable_g[g]; for (b=0, x=0; (b < 96) && (x < max); b++) x += htable_b[b]; r_factor = (double) 0xfe / (0xff-r); g_factor = (double) 0xfe / (0xff-g); b_factor = (double) 0xfe / (0xff-b); max_factor = r_factor; if (g_factor > max_factor) max_factor = g_factor; if (b_factor > max_factor) max_factor = b_factor; if (max_factor >= 1.15) { r_factor = (r_factor / max_factor) * 1.15; g_factor = (g_factor / max_factor) * 1.15; b_factor = (b_factor / max_factor) * 1.15; } GP_DEBUG( "White balance (dark): r=%1d, g=%1d, b=%1d, fr=%1.3f, fg=%1.3f, fb=%1.3f\n", r, g, b, r_factor, g_factor, b_factor); for (x = 0; x < (size * 3); x += 3) { d = (int) 0xff08-(((0xff-data[x+0])<<8) * r_factor); d >>= 8; if (d < 0) { d = 0; } data[x+0] = d; d = (int) 0xff08-(((0xff-data[x+1])<<8) * g_factor); d >>= 8; if (d < 0) { d = 0; } data[x+1] = d; d = (int) 0xff08-(((0xff-data[x+2])<<8) * b_factor); d >>= 8; if (d < 0) { d = 0; } data[x+2] = d; } /* ------------------ COLOR ENHANCE ------------------ */ if(saturation > 0.0) { for (x = 0; x < (size * 3); x += 3) { r = data[x+0]; g = data[x+1]; b = data[x+2]; d = (int) (r + g + b) /3.; if ( r > d ) r = r + (int) ((r - d) * (0xff-r)/(0x100-d) * saturation); else r = r + (int) ((r - d) * (0xff-d)/(0x100-r) * saturation); if (g > d) g = g + (int) ((g - d) * (0xff-g)/(0x100-d) * saturation); else g = g + (int) ((g - d) * (0xff-d)/(0x100-g) * saturation); if (b > d) b = b + (int) ((b - d) * (0xff-b)/(0x100-d) * saturation); else b = b + (int) ((b - d) * (0xff-d)/(0x100-b) * saturation); data[x+0] = CLAMP(r); data[x+1] = CLAMP(g); data[x+2] = CLAMP(b); } } return 0; }
int white_balance (unsigned char *data, unsigned int size, float saturation) { int x, r, g, b, max, d; double r_factor, g_factor, b_factor, max_factor, MAX_FACTOR=1.6; int htable_r[256], htable_g[256], htable_b[256]; unsigned char gtable[256]; double new_gamma, gamma; /* ------------------- GAMMA CORRECTION ------------------- */ histogram(data, size, htable_r, htable_g, htable_b); x = 1; for (r = 64; r < 192; r++) { x += htable_r[r]; x += htable_g[r]; x += htable_b[r]; } gamma = sqrt((double) (x ) / (double) (size * 2)); GP_DEBUG("Provisional gamma correction = %1.2f\n", gamma); if(gamma < .1) { new_gamma = .50; MAX_FACTOR=1.2; } else if (gamma < 0.60) new_gamma = 0.60; else new_gamma = gamma; if (new_gamma > 1.2) new_gamma = 1.2; GP_DEBUG("Gamma correction = %1.2f\n", new_gamma); gp_gamma_fill_table(gtable, new_gamma); gp_gamma_correct_single(gtable,data,size); /* ---------------- BRIGHT DOTS ------------------- */ max = size / 200; histogram(data, size, htable_r, htable_g, htable_b); for (r=254, x=0; (r > 64) && (x < max); r--) x += htable_r[r]; for (g=254, x=0; (g > 64) && (x < max); g--) x += htable_g[g]; for (b=254, x=0; (b > 64) && (x < max); b--) x += htable_b[b]; r_factor = (double) 254 / r; g_factor = (double) 254 / g; b_factor = (double) 254 / b; max_factor = r_factor; if (g_factor > max_factor) max_factor = g_factor; if (b_factor > max_factor) max_factor = b_factor; if (max_factor > MAX_FACTOR) { r_factor = (r_factor / max_factor) * MAX_FACTOR; g_factor = (g_factor / max_factor) * MAX_FACTOR; b_factor = (b_factor / max_factor) * MAX_FACTOR; } GP_DEBUG("White balance (bright): r=%1d, g=%1d, b=%1d, fr=%1.3f, fg=%1.3f, fb=%1.3f\n", r, g, b, r_factor, g_factor, b_factor); for (x = 0; x < (size * 3); x += 3) { d = (int) data[x+0] * r_factor; if (d > 255) { d = 255; } data[x+0] = d; d = (int) data[x+1] * g_factor; if (d > 255) { d = 255; } data[x+1] = d; d = (int) data[x+2] * b_factor; if (d > 255) { d = 255; } data[x+2] = d; } /* ---------------- DARK DOTS ------------------- */ max = size / 200; /* 1/200 = 0.5% */ histogram(data, size, htable_r, htable_g, htable_b); for (r=0, x=0; (r < 64) && (x < max); r++) x += htable_r[r]; for (g=0, x=0; (g < 64) && (x < max); g++) x += htable_g[g]; for (b=0, x=0; (b < 64) && (x < max); b++) x += htable_b[b]; r_factor = (double) 254 / (255-r); g_factor = (double) 254 / (255-g); b_factor = (double) 254 / (255-b); GP_DEBUG("White balance (dark): r=%1d, g=%1d, b=%1d, fr=%1.3f, fg=%1.3f, fb=%1.3f\n", r, g, b, r_factor, g_factor, b_factor); for (x = 0; x < (size * 3); x += 3) { d = (int) 255-((255-data[x+0]) * r_factor); if (d < 0) { d = 0; } data[x+0] = d; d = (int) 255-((255-data[x+1]) * g_factor); if (d < 0) { d = 0; } data[x+1] = d; d = (int) 255-((255-data[x+2]) * b_factor); if (d < 0) { d = 0; } data[x+2] = d; } /* ------------------ COLOR ENHANCE ------------------ */ for (x = 0; x < (size * 3); x += 3) { r = data[x+0]; g = data[x+1]; b = data[x+2]; d = (int) (r + 2*g + b) / 4.; if ( r > d ) r = r + (int) ((r - d) * (255-r)/(256-d) * saturation); else r = r + (int) ((r - d) * (255-d)/(256-r) * saturation); if (g > d) g = g + (int) ((g - d) * (255-g)/(256-d) * saturation); else g = g + (int) ((g - d) * (255-d)/(256-g) * saturation); if (b > d) b = b + (int) ((b - d) * (255-b)/(256-d) * saturation); else b = b + (int) ((b - d) * (255-d)/(256-b) * saturation); if (r < 0) { r = 0; } if (r > 255) { r = 255; } data[x+0] = r; if (g < 0) { g = 0; } if (g > 255) { g = 255; } data[x+1] = g; if (b < 0) { b = 0; } if (b > 255) { b = 255; } data[x+2] = b; } return 0; }
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); }
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; }
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) { 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; }
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; }
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; }