kopia lustrzana https://gitlab.com/sane-project/backends
Minor bug fixes and cosmetic cleanup
rodzic
222a47fa6c
commit
01cca8ef39
|
@ -5,7 +5,7 @@
|
|||
* which happens to be the only camera I have. I'm very interested
|
||||
* in learning what it would take to support more cameras. In
|
||||
* particular, the current incarnation will only support cameras
|
||||
* the generate jpeg files.
|
||||
* that directly generate jpeg files.
|
||||
*
|
||||
* However, having said that, I've already found it to be quite useful
|
||||
* even in its current form - one reason is that gphoto2 provides access
|
||||
|
@ -323,7 +323,7 @@ static SANE_Char cmdbuf[256];
|
|||
static CameraAbilities *abilities;
|
||||
static CameraFile *data_file;
|
||||
static const char *data_ptr;
|
||||
static long data_size, data_cur;
|
||||
static long data_file_total_size, data_file_current_index;
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
@ -334,7 +334,7 @@ static long data_size, data_cur;
|
|||
static SANE_Int
|
||||
init_gphoto2 (void)
|
||||
{
|
||||
SANE_Int n, entries;
|
||||
SANE_Int n;
|
||||
CameraList *list;
|
||||
|
||||
DBG (1, "GPHOTO2 Backend 05/16/01\n");
|
||||
|
@ -745,8 +745,8 @@ sane_exit (void)
|
|||
static const SANE_Device dev[] = {
|
||||
{
|
||||
"0",
|
||||
"Kodak",
|
||||
"DC-240",
|
||||
"Gphoto2",
|
||||
"Supported",
|
||||
"still camera"},
|
||||
};
|
||||
|
||||
|
@ -1100,17 +1100,17 @@ METHODDEF (boolean) jpeg_fill_input_buffer (j_decompress_ptr cinfo)
|
|||
|
||||
my_src_ptr src = (my_src_ptr) cinfo->src;
|
||||
|
||||
if (data_cur + 512 > data_size)
|
||||
if (data_file_current_index + 512 > data_file_total_size)
|
||||
{
|
||||
n = data_size - data_cur;
|
||||
n = data_file_total_size - data_file_current_index;
|
||||
}
|
||||
else
|
||||
{
|
||||
n = 512;
|
||||
}
|
||||
|
||||
memcpy (src->buffer, data_ptr + data_cur, n);
|
||||
data_cur += n;
|
||||
memcpy (src->buffer, data_ptr + data_file_current_index, n);
|
||||
data_file_current_index += n;
|
||||
|
||||
src->pub.next_input_byte = src->buffer;
|
||||
src->pub.bytes_in_buffer = n;
|
||||
|
@ -1147,10 +1147,7 @@ jpeg_term_source (j_decompress_ptr UNUSEDARG cinfo)
|
|||
SANE_Status
|
||||
sane_start (SANE_Handle handle)
|
||||
{
|
||||
my_src_ptr src;
|
||||
SANE_String_Const filename, mime_type;
|
||||
struct jpeg_error_mgr jerr;
|
||||
SANE_Int row_stride;
|
||||
|
||||
DBG (127, "sane_start called\n");
|
||||
if (handle != MAGIC || !is_open ||
|
||||
|
@ -1208,41 +1205,10 @@ sane_start (SANE_Handle handle)
|
|||
exit (1);
|
||||
}
|
||||
|
||||
CHECK_RET (gp_file_get_data_and_size (data_file, &data_ptr, &data_size));
|
||||
CHECK_RET (gp_file_get_data_and_size
|
||||
(data_file, &data_ptr, &data_file_total_size));
|
||||
|
||||
data_cur = 0;
|
||||
|
||||
cinfo.err = jpeg_std_error (&jerr);
|
||||
jpeg_create_decompress (&cinfo);
|
||||
|
||||
cinfo.src =
|
||||
(struct jpeg_source_mgr *) (*cinfo.mem->
|
||||
alloc_small) ((j_common_ptr) & cinfo,
|
||||
JPOOL_PERMANENT,
|
||||
sizeof (my_source_mgr));
|
||||
src = (my_src_ptr) cinfo.src;
|
||||
|
||||
src->buffer = (JOCTET *) (*cinfo.mem->alloc_small) ((j_common_ptr) &
|
||||
cinfo,
|
||||
JPOOL_PERMANENT,
|
||||
1024 * sizeof (JOCTET));
|
||||
src->pub.init_source = jpeg_init_source;
|
||||
src->pub.fill_input_buffer = jpeg_fill_input_buffer;
|
||||
src->pub.skip_input_data = jpeg_skip_input_data;
|
||||
src->pub.resync_to_restart = jpeg_resync_to_restart; /* default */
|
||||
src->pub.term_source = jpeg_term_source;
|
||||
src->pub.bytes_in_buffer = 0;
|
||||
src->pub.next_input_byte = NULL;
|
||||
|
||||
(void) jpeg_read_header (&cinfo, TRUE);
|
||||
dest_mgr = sanei_jpeg_jinit_write_ppm (&cinfo);
|
||||
(void) jpeg_start_decompress (&cinfo);
|
||||
|
||||
row_stride = cinfo.output_width * cinfo.output_components;
|
||||
|
||||
parms.bytes_per_line = cinfo.output_width * 3; /* 3 colors */
|
||||
parms.pixels_per_line = cinfo.output_width;
|
||||
parms.lines = cinfo.output_height;
|
||||
converter_init ();
|
||||
|
||||
/* Check if a linebuffer has been allocated. Assumes that highres_width
|
||||
* is also large enough to hold a lowres or thumbnail image
|
||||
|
@ -1268,11 +1234,6 @@ SANE_Status
|
|||
sane_read (SANE_Handle UNUSEDARG handle, SANE_Byte * data,
|
||||
SANE_Int max_length, SANE_Int * length)
|
||||
{
|
||||
SANE_Int lines = 0;
|
||||
SANE_String_Const filename;
|
||||
CameraList *tmp_list;
|
||||
SANE_Int i;
|
||||
|
||||
/* If there is anything in the buffer, satisfy the read from there */
|
||||
if (linebuffer_size && linebuffer_index < linebuffer_size)
|
||||
{
|
||||
|
@ -1288,94 +1249,16 @@ sane_read (SANE_Handle UNUSEDARG handle, SANE_Byte * data,
|
|||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
if (cinfo.output_scanline >= cinfo.output_height)
|
||||
if (converter_scan_complete ())
|
||||
{
|
||||
gp_file_unref (data_file);
|
||||
|
||||
if (gphoto2_opt_erase)
|
||||
SANE_Status retval = converter_do_scan_complete_cleanup ();
|
||||
if (retval != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (127, "sane_read bp%d, erase image\n", __LINE__);
|
||||
if (erase () == -1)
|
||||
{
|
||||
DBG (1, "Failed to erase memory\n");
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
|
||||
|
||||
sprintf (cmdbuf, "%s/%s", (char *) TopFolder,
|
||||
(const char *) folder_list[current_folder]);
|
||||
CHECK_RET (gp_list_get_name
|
||||
(dir_list, Cam_data.current_picture_number - 1,
|
||||
&filename));
|
||||
|
||||
Cam_data.pic_taken--;
|
||||
Cam_data.pic_left++;
|
||||
if ( Cam_data.current_picture_number > Cam_data.pic_taken ) {
|
||||
Cam_data.current_picture_number = Cam_data.pic_taken;
|
||||
}
|
||||
image_range.max--;
|
||||
if (image_range.max == 0)
|
||||
{
|
||||
sod[GPHOTO2_OPT_IMAGE_NUMBER].cap |= SANE_CAP_INACTIVE;
|
||||
}
|
||||
myinfo |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
|
||||
|
||||
/* Too bad we don't have an API function for deleting a
|
||||
* list item. Instead, we copy all the entries in the
|
||||
* current list, skipping over the deleted entry, and then
|
||||
* replace the current list with the new list.
|
||||
*/
|
||||
gp_list_new (&tmp_list);
|
||||
|
||||
for (i = 0; i < gp_list_count (dir_list); i++)
|
||||
{
|
||||
SANE_String_Const tfilename;
|
||||
|
||||
CHECK_RET (gp_list_get_name (dir_list, i, &tfilename));
|
||||
/* If not the one to delete, copy to the new list */
|
||||
if (strcmp (tfilename, filename) != 0)
|
||||
{
|
||||
CHECK_RET (gp_list_append (tmp_list, tfilename, NULL));
|
||||
}
|
||||
}
|
||||
gp_list_free (dir_list);
|
||||
dir_list = tmp_list;
|
||||
|
||||
return retval;
|
||||
}
|
||||
if (gphoto2_opt_autoinc)
|
||||
{
|
||||
if (Cam_data.current_picture_number <= Cam_data.pic_taken)
|
||||
{
|
||||
Cam_data.current_picture_number++;
|
||||
|
||||
myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
|
||||
|
||||
/* get the image's resolution */
|
||||
/* OLD:
|
||||
set_res (Cam_data.Pictures[Cam_data.current_picture_number - 1].
|
||||
low_res);
|
||||
*/
|
||||
set_res (gphoto2_opt_lowres);
|
||||
}
|
||||
DBG (4, "Increment count to %d (total %d)\n",
|
||||
Cam_data.current_picture_number, Cam_data.pic_taken);
|
||||
}
|
||||
return SANE_STATUS_EOF;
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: Current implementation reads one scan line at a time. Part
|
||||
* of the reason for this is in the original code is to give the frontend
|
||||
* a chance to update * the progress marker periodically. Since the gphoto2
|
||||
* driver sucks in the whole image before decoding it, perhaps we could
|
||||
* come up with a simpler implementation.
|
||||
*/
|
||||
|
||||
lines = 1;
|
||||
(void) jpeg_read_scanlines (&cinfo, dest_mgr->buffer, lines);
|
||||
(*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, lines, (char *) linebuffer);
|
||||
|
||||
*length = cinfo.output_width * cinfo.output_components * lines;
|
||||
*length = converter_fill_buffer ();
|
||||
linebuffer_size = *length;
|
||||
linebuffer_index = 0;
|
||||
|
||||
|
@ -1425,7 +1308,9 @@ sane_get_select_fd (SANE_Handle UNUSEDARG handle, SANE_Int * UNUSEDARG fd)
|
|||
/*
|
||||
* get_pictures_info - load information about all pictures currently in
|
||||
* camera: Mainly the mapping of picture number
|
||||
* to picture name, and the resolution of each picture.
|
||||
* to picture name. We'ld like to get other
|
||||
* information such as image size, but the API
|
||||
* doesn't provide any support for that.
|
||||
*/
|
||||
static PictureInfo *
|
||||
get_pictures_info (void)
|
||||
|
@ -1479,7 +1364,8 @@ get_pictures_info (void)
|
|||
}
|
||||
|
||||
/*
|
||||
* sane_picture_info() - get info about picture p
|
||||
* sane_picture_info() - get info about picture p. Currently we have no
|
||||
* way to get information about a picture beyond it's name.
|
||||
*/
|
||||
static SANE_Int
|
||||
get_picture_info (PictureInfo * pic, SANE_Int p)
|
||||
|
@ -1587,6 +1473,8 @@ read_dir (SANE_String dir, SANE_Bool read_files)
|
|||
|
||||
/*
|
||||
* read_info - read the info block from camera for the specified file
|
||||
* NOT YET SUPPORTED - If it were we could use it to do things
|
||||
* like update the image size parameters displayed by the GUI
|
||||
*/
|
||||
static SANE_Int
|
||||
read_info (SANE_String_Const fname)
|
||||
|
@ -1622,3 +1510,179 @@ set_res (SANE_Int lowres)
|
|||
parms.lines = HIGHRES_HEIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* converter_do_scan_complete_cleanup - do everything that needs to be
|
||||
* once a "scan" has been completed: Unref the file, Erase the image,
|
||||
* and increment image number to point to next picture.
|
||||
*/
|
||||
static SANE_Status
|
||||
converter_do_scan_complete_cleanup (void)
|
||||
{
|
||||
CameraList *tmp_list;
|
||||
SANE_Int i;
|
||||
SANE_String_Const filename;
|
||||
|
||||
gp_file_unref (data_file);
|
||||
|
||||
if (gphoto2_opt_erase)
|
||||
{
|
||||
DBG (127, "sane_read bp%d, erase image\n", __LINE__);
|
||||
if (erase () == -1)
|
||||
{
|
||||
DBG (1, "Failed to erase memory\n");
|
||||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
|
||||
|
||||
sprintf (cmdbuf, "%s/%s", (char *) TopFolder,
|
||||
(const char *) folder_list[current_folder]);
|
||||
CHECK_RET (gp_list_get_name
|
||||
(dir_list, Cam_data.current_picture_number - 1, &filename));
|
||||
|
||||
Cam_data.pic_taken--;
|
||||
Cam_data.pic_left++;
|
||||
if (Cam_data.current_picture_number > Cam_data.pic_taken)
|
||||
{
|
||||
Cam_data.current_picture_number = Cam_data.pic_taken;
|
||||
}
|
||||
image_range.max--;
|
||||
if (image_range.max == 0)
|
||||
{
|
||||
sod[GPHOTO2_OPT_IMAGE_NUMBER].cap |= SANE_CAP_INACTIVE;
|
||||
}
|
||||
myinfo |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
|
||||
|
||||
/* Too bad we don't have an API function for deleting a
|
||||
* list item. Instead, we copy all the entries in the
|
||||
* current list, skipping over the deleted entry, and then
|
||||
* replace the current list with the new list.
|
||||
*/
|
||||
gp_list_new (&tmp_list);
|
||||
|
||||
for (i = 0; i < gp_list_count (dir_list); i++)
|
||||
{
|
||||
SANE_String_Const tfilename;
|
||||
|
||||
CHECK_RET (gp_list_get_name (dir_list, i, &tfilename));
|
||||
/* If not the one to delete, copy to the new list */
|
||||
if (strcmp (tfilename, filename) != 0)
|
||||
{
|
||||
CHECK_RET (gp_list_append (tmp_list, tfilename, NULL));
|
||||
}
|
||||
}
|
||||
gp_list_free (dir_list);
|
||||
dir_list = tmp_list;
|
||||
|
||||
}
|
||||
if (gphoto2_opt_autoinc)
|
||||
{
|
||||
if (Cam_data.current_picture_number <= Cam_data.pic_taken)
|
||||
{
|
||||
Cam_data.current_picture_number++;
|
||||
|
||||
myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
|
||||
|
||||
/* get the image's resolution */
|
||||
/* OLD:
|
||||
set_res (Cam_data.Pictures[Cam_data.current_picture_number - 1].
|
||||
low_res);
|
||||
*/
|
||||
set_res (gphoto2_opt_lowres);
|
||||
}
|
||||
DBG (4, "Increment count to %d (total %d)\n",
|
||||
Cam_data.current_picture_number, Cam_data.pic_taken);
|
||||
}
|
||||
return SANE_STATUS_EOF;
|
||||
}
|
||||
|
||||
/*
|
||||
* converter_fill_buffer - Fill line buffer with next input line from image.
|
||||
* Currently assumes jpeg, but this is where we would put the switch
|
||||
* to handle other image types.
|
||||
*/
|
||||
static SANE_Int
|
||||
converter_fill_buffer (void)
|
||||
{
|
||||
|
||||
/*
|
||||
* FIXME: Current implementation reads one scan line at a time. Part
|
||||
* of the reason for this is in the original code is to give the frontend
|
||||
* a chance to update * the progress marker periodically. Since the gphoto2
|
||||
* driver sucks in the whole image before decoding it, perhaps we could
|
||||
* come up with a simpler implementation.
|
||||
*/
|
||||
|
||||
SANE_Int lines = 1;
|
||||
|
||||
(void) jpeg_read_scanlines (&cinfo, dest_mgr->buffer, lines);
|
||||
(*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, lines, (char *) linebuffer);
|
||||
|
||||
return cinfo.output_width * cinfo.output_components * lines;
|
||||
}
|
||||
|
||||
/*
|
||||
* converter_scan_complete - Check if all the data for the image has been read.
|
||||
* Currently assumes jpeg, but this is where we would put the
|
||||
* switch to handle other image types.
|
||||
*/
|
||||
static SANE_Bool
|
||||
converter_scan_complete (void)
|
||||
{
|
||||
if (cinfo.output_scanline >= cinfo.output_height)
|
||||
{
|
||||
return SANE_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return SANE_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* converter_init - Initialize image conversion data.
|
||||
* Currently assumes jpeg, but this is where we would put the
|
||||
* switch to handle other image types.
|
||||
*/
|
||||
static void
|
||||
converter_init (void)
|
||||
{
|
||||
SANE_Int row_stride;
|
||||
struct jpeg_error_mgr jerr;
|
||||
my_src_ptr src;
|
||||
|
||||
data_file_current_index = 0;
|
||||
|
||||
cinfo.err = jpeg_std_error (&jerr);
|
||||
jpeg_create_decompress (&cinfo);
|
||||
|
||||
cinfo.src =
|
||||
(struct jpeg_source_mgr *) (*cinfo.mem->
|
||||
alloc_small) ((j_common_ptr) & cinfo,
|
||||
JPOOL_PERMANENT,
|
||||
sizeof (my_source_mgr));
|
||||
src = (my_src_ptr) cinfo.src;
|
||||
|
||||
src->buffer = (JOCTET *) (*cinfo.mem->alloc_small) ((j_common_ptr) &
|
||||
cinfo,
|
||||
JPOOL_PERMANENT,
|
||||
1024 * sizeof (JOCTET));
|
||||
src->pub.init_source = jpeg_init_source;
|
||||
src->pub.fill_input_buffer = jpeg_fill_input_buffer;
|
||||
src->pub.skip_input_data = jpeg_skip_input_data;
|
||||
src->pub.resync_to_restart = jpeg_resync_to_restart; /* default */
|
||||
src->pub.term_source = jpeg_term_source;
|
||||
src->pub.bytes_in_buffer = 0;
|
||||
src->pub.next_input_byte = NULL;
|
||||
|
||||
(void) jpeg_read_header (&cinfo, TRUE);
|
||||
dest_mgr = sanei_jpeg_jinit_write_ppm (&cinfo);
|
||||
(void) jpeg_start_decompress (&cinfo);
|
||||
|
||||
row_stride = cinfo.output_width * cinfo.output_components;
|
||||
|
||||
parms.bytes_per_line = cinfo.output_width * 3; /* 3 colors */
|
||||
parms.pixels_per_line = cinfo.output_width;
|
||||
parms.lines = cinfo.output_height;
|
||||
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue