SANE V2 - past discussions. A summary.

becka@rz.uni-duesseldorf.de
Sun, 15 Aug 1999 02:17:31 +0200 (MEST)

Hi !

> a SANE driver for. However, I need some more complete frame types as
> this scanner produces JFIF and TIFF/G4 images (simultaneously) and I
> would *like* to just pass the JFIF data as a coded SANE frame.
> Once I do that, I'll have access to some high-speed document scanners
> that I would also like to write drivers for.
> Is there a place where I can see a draft of what SANE 2.x will contain,
> so that I (we) can comment?

O.K. - I will forward all mails I and David exchanged on that topic.
Maybe I'll add some rant at the end as well, reviewing them from a
greater distance.
Such rant will be marked with ###.

Here you are:

------------ snip --------------

O.k. - as the recent interest in doing compressed file transmission and
a TWAIN bridge show demand for that, I have written up a little summary on
what has been thought of as new features SANE 2.0

A. From the SANE docs: LEVEL2:
------------------------------

** Tue Jun 3 10:22:33 1997

Here are some ideas under discussion for the next major revision of
the SANE API:

o Additional image data types, such as JPEG, MPEG, FlashPix, raw.
These would be useful for devices that directly generate such
formats (still cameras, for example). The raw image format could
be used when no other format is applicable. This would allow to
at least read and save the data in a file. This would probably
have to be coupled with adding a function that lets a frontend
tell the backend what level it supports, something like
sane_set_level (int max_supported_level).
[Based on suggestion by Andreas Beck <becka@ggi-project.org>]

o Support for other multimedia types, such as audio. This probably
would also require adding a write() interface to the SANE API.
[Suggested by Erik Troan <ewt@redhat.com>.]

B. From some private communications I found in my backlog:
----------------------------------------------------------

** Tue Oct 20 22:02:03 1998: Andy:

> - when will there be JPEG support in the SANE interface? i guess
> other camera (such as the Kodak ones?) also use a format
> that's close to JPEG...

We should finally add that.

My idea about adding it would be to increase the version number, which
can be queried at sane_init() time.

If the frontend finds a sufficiently high version, it would assume
that the SANE_Parameters struct is extended by a few fields like:

SANE_String mime_type;
SANE_String suggested_filename;

This would effectively take care of all possible fileformats.

The frontend code would have to be changed a bit like this:

if (strcmp(param.mimetype,"application/SANE"))
save_directly_to_file(
make_path_suitable_for_host_os(
param.suggested_filename)));
else
do_the_same_as_before();

This would also take care of the second suggestion in the file to use SANE
for arbitrary datatypes.

File size could be handled in a compatible way, by setting bytes_per_line
and lines accordingly, that is usually to something like fsize(),1 or
1,fsize().

### using the lines==0 semantics that were resevred for handscanners,
### we could handle yet unknown filesizes, which might occur for
### compressed data formats.

This would only be a minor modification to frontends and backends
(even old frontends would handle new-style data somewhat correctly,
if they would save it to a file directly without trying to convert/
interpret it first). Most of our current front-ends afaik do a very
simplistic "convert to pnm" which could easily be undone afterwards
by a small script that simply removes the header.

** Fri Oct 23 18:58:38 1998: David:

What I'd like to see is the backend declaring what image format(s) it
supports. Similarly, the frontend would say what image format it
wants. Then you have a set of library routines that are filters,
e.g., (input: JPG, output: RAW), (input: RAW, output: JPG). So if
there is a mismatch between backend and frontend format, you call a
library routine that will construct a suitable pipeline of filters.

The biggest issue is probably what to do for filters that need
parameters (such as JPG smoothing & quality settings).

---david

** Sat Oct 24 12:42:25 1998: Andy:

> What I'd like to see is the backend declaring what image format(s) it
> supports.

O.K. - as the user might want to select the format (regardless of what his
frontend will understand), I suggest to just introduce a standard option
for that.

> Similarly, the frontend would say what image format it wants.

I'd say it should parse the constraint list of said option and preselect
the best of those it understands.

> Then you have a set of library routines that are filters,
> e.g., (input: JPG, output: RAW), (input: RAW, output: JPG). So if
> there is a mismatch between backend and frontend format, you call a
> library routine that will construct a suitable pipeline of filters.

Yes. Possible, though it might be hard to actually determine what the best
path would be, i.e. which frontend-format/backend-format combination
gives best quality. This might even depend on other source-options.

> The biggest issue is probably what to do for filters that need
> parameters (such as JPG smoothing & quality settings).

Regarding the filters issue I'd suggest to make use of one or more
"passthrough" pseudo middle-ends that simply add to the abovementioned
option and add their own options in as required by the conversion.

Let's make up an example:

We have a camera that outputs image/foo or image/bar type data on request.

The frontend only understands image/gif and application/sane.

We have a middle-end that can convert image/foo|bar to image/gif,
image/jpeg, image/bla and application/sane.

Now what happens:

The frontend starts up and queries the camera for options. It sees the
special option "transmission-format" and checks its constraint list.

As there is no match between understood formats and transmittable formats,
it tries (after asking the user ?) to reopen the selected source through
the filter middleend.

It again parses the special option which will now show foo,bar,gif,jpeg,bla
and sane.
Now it picks those it understands (in preferred order) and places them at
the top of the constraint list and somehow marks them to the user (say by
adding a "*" on text frontends or by making them green or whatever.

Now to the user the select list looks like "sane,gif,foo,bar,jpeg,bla".

Now say the user wants to have jpeg for some reason. So he selects the
appropriate option. The middleend sees that, selects the most suitable
source format (foo or bar) on the source and adds the required conversion
options to the option list.

If the user now asks for a scan, this request is passed through the
middleend which sets up its filters in sane_read and builds a suitable
parameter struct (as I suggested).

The frontend sees (from the parameter struct) that is doesn't know the
selected format, so it prompts the user for a filename (default from
params) and just saves it.

If the user had selected a known format, the frontend would proceed as
usual, displaying the image etc.

A reasonable addition to many frontends would be to have some kind of
"mime.types" file (maybe even use it ?) that can be used to direct output
to other programs as described there.

Say if we get a audio/wav file, we parse mime.types and ask
"I don't know mime-type audio/wav - what should I do ?
1. save to file
2. use mime.types (will run %s to display file)
3. cancel operation"

** Wed Oct 28 07:11:49 1998: david:

Hmmh, I see where you're coming from as far as support for different
image data formats are concerned, but I'm not sure I like what you're
proposing. Here are some constraints I think we (ideally) should
adhere to:

- existing frontends should continue to work (both in binary
form and in source form)

- existing backends should continue to work (both in binary
form and in source form)

- the user should not have to worry about image transmission
format

I think we should agree on a set of image formats supported by SANE.
E.g., format 0 is the existing "raw" format and uses a default file
extension of ".pnm". Format 1 could be GIF with file extension ".gif"
etc.

Suppose we introduce a new call:

SANE_Status sane_set_format (SANE_Word *format);

When calling the value *FORMAT gives the format the frontend wants the
image data in. A special value of SANE_IMAGE_FORMAT_ANY indicates
that the frontend can accept any format (as is the case for scanimage,
for example). Upon returning, *FORMAT gives the format that the
backend is actually returning. If the returned format doesn't match
the wanted format, the frontend can either accept the backends choice
(if the frontend can handle the format), abort with an error, or try
another sane_set_format() call with a different wanted format to see
if that format works better.

Let's try your example:

- camera returns either FOO or BAR format
- the conversion meta-backend "cnv" can convert from FOO or BAR
to GIF, JPEG, and RAW

Let's consider different frontends:

- In the case of GIMP, you always want RAW format so you'd
call sane_set_format() with a parameter of
SANE_IMAGE_FORMAT_RAW and if you don't get what you ask
for, you abort. Since "cnv" can convert both FOO and BAR
to RAW, no problem exists.

- In the case of scanimage, you'd let the user specify the
format. By default, you'd presumably pick the format based
on the filename extension (such as ".jpg") or through an
explicit option. Then scanimage performs the appropriate
sane_set_format() call. If the user doesn't care about the
format being used, scanimage could call sane_set_format()
with a value of SANE_IMAGE_FORMAT_ANY which lets the backend
pick the format that is most convenient (e.g., JPEG for a
JPG camera).

For example, if scanimage picks the JPEG format, cnv will
detect that the camera can't deliver JPEG (the camera
would return it's preferred format, e.g., FOO). It would
then arrange for a translation from FOO to JPEG.

Now, what happens if there is a version mismatch:

- if an old frontend talks to a new backend, the backend can
detect this since there won't be any calls to
sane_set_format(). In this case, the backend defaults to
returning the RAW format. If a backend doesn't support RAW
(as might be the case for a JPEG camera), an old frontend
would not be able to directly talk to such a backend.
However, as long as a suitable conversion meta-backend
is interspersed, things will work happily (the meta-backend
sees the lack of a call to sane_set_format and defaults
to returning RAW, independent of what the real backend
delivers)

- if a new frontend talks to an old backend the
sane_set_format() call always returns RAW

I think it would be nice to have a "cnv" meta-backend that would be
fairly generic in that it would be easy to add new filters. The
filters would either convert to or from RAW format, so there really
isn't much of an issue as to how to construct an "optimal" pipe (since
the pipe consists either of exactly 0, 1, or 2 elements).

** From davidm@mostang.com Fri Oct 30 06:54:23 1998

Andy> O.K. - would you mind using the mime-type ?

No, I think it makes some sense to use MIME.

Andy> My idea was, that a backend that offers formats that take
Andy> parameters also exports those as options.

Seems reasonable.

>> Also, I think we may want to pick the name of the image format to
>> be identical to the default filename extension

Andy> This is why I was proposing to have a type filed as well as a
Andy> "suggested filename". The latter especially makes sense for
Andy> picture archives or such.

Can't you get the suggested filename from the mime database? There is
an "exts" field. Besides, I'm not really sure having a suggested
filename extension is that important. I don't particularly like
programs that insist on using specific extensions (though it's OK if
the _default_ to a sensible extension).

Andy> Do we want SANE to be able to carry totally foreign or weird
Andy> formats like say audio ?

I think we shouldn't do anything that precludes this, but I also don't
think it's anything that's worth spending a lot of effort on right
now. Introducing realtime issues could quickly make SANE so
complicated that it's too bloated for simple scanning. On the other
hand, if for some reason video acquisition through SANE suddenly
becomes a hot topic, we may want to be able to have at least some
basic audio acquisition support. But I would say we worry about this
when we have a real need for it.

To summarize our discussion: I don't have much of a problem using the
"transmission-format" well-known option and whoever does the actual
work, gets the final say. If you want to do it (I won't have time any
time soon), go wild! Please be sure to update sane.tex etc as well so
the docs stay in sync with the code (oh, I also think we should run
things by sane-devel when there is a detailed proposal).

** From becka@rz.uni-duesseldorf.de Fri Oct 30 14:11:50 1998

> Andy> O.K. - would you mind using the mime-type ?
> No, I think it makes some sense to use MIME.

O.K. - so we consider that as "decided".

> Andy> My idea was, that a backend that offers formats that take
> Andy> parameters also exports those as options.
> Seems reasonable.

O.K. - see my comments below.

> >> Also, I think we may want to pick the name of the image format to
> >> be identical to the default filename extension
> Andy> This is why I was proposing to have a type filed as well as a
> Andy> "suggested filename". The latter especially makes sense for
> Andy> picture archives or such.
>
> Can't you get the suggested filename from the mime database?

Yes, I think you can. But that wasn't, what I was trying to achieve with
that. I wanted a full "suggested filename". That is, it should return
"nice_picture_of_something.jpg". This is probably reasonable for
transferring
pictures from archives or such. You automatically get a reasonable filename.

> There is an "exts" field. Besides, I'm not really sure having a suggested
> filename extension is that important. I don't particularly like
> programs that insist on using specific extensions (though it's OK if
> the _default_ to a sensible extension).

Yes. That is how I see it, too. You should get a reasonable default, but any
program insisting or not asking for confirmation is broken IMO.

> Andy> Do we want SANE to be able to carry totally foreign or weird
> Andy> formats like say audio ?
>
> I think we shouldn't do anything that precludes this, but I also don't
> think it's anything that's worth spending a lot of effort on right
> now.

Yes. Though I thought with using MIME, it should be pretty trivial.

> Introducing realtime issues could quickly make SANE so
> complicated that it's too bloated for simple scanning.

Yes. I do not care for things like "streaming" audio/video. This is far too
complex for SANE and requires too many changes. Just that you can transfer
anything that could also be in a file and doesn't have other prerequisites.

A bit of "netscape for scanners", you know. If someone build a file archive
using SANE, he should be able add a few sound files or whatever, too.

> On the other hand, if for some reason video acquisition through SANE
> suddenly becomes a hot topic,

I will probably write a driver for the Permedia II Graphics card I have
which includes a Video grabber. But I won't care for live video, just for
stills. SANE is just not suited to do that.

A read-type interface isn't good. Video demands high bandwidth, and is thus
best achieved via a mmap-type interface.

> we may want to be able to have at least some basic audio acquisition
> support. But I would say we worry about this when we have a real need
> for it.

Yes. I'd say for now, everything that resembles a file transfer is o.k.
Anything needing special transmission semantics like guaranteed bandwidth,
bandwidth negotiation, etc. is out of bounds for now.

------------ snap --------------

O.K. - looks like I hadn't much to rant about.

So the question is: Do you like the following general ideas:

1. Add a well-known option to backends that can transfer in nonstandard
formats, which allows to choose the format. This option shall be there,
even if it only has one possible setting, as it is used to identify backends
that use nonstandard formats.

2. Write one or more filtering "middleends", that - similar to the net
front-/backend - pass through a given source. Such Middleends would parse
and upgrade the option described in 1 to hold all native formats _plus_
all formats the middleend can convert the native formats to.

3. Frontends that support this extension shall scan for the well-known
option and mark up and default-select the format that is most convenient
to them.

4. Add a single new frametype SANE_MIME which describes a stream that looks
like the output of a CGI-script, that would transfer the corresponding
information. That is:

------ snip --------
Content-type: text/html
More-headers: some extra hints

data_in_free_streaming_format_until_eof.
------ snap --------

All headers are optional. Thus the minimal transmission consists of
a single newline character (which serves as a header/body separator)
followed by the raw data. It is not recommended to do so, though.
At least Content-type: should be given.

I propose two such headers that might be commonly used and should thus be
parsed by the frontend. They are the same as what MIME-aware mailhandlers
set for attachments :

a) Content-type: mimetype/subtype[; optional_attribute=value]

This header specifies the mimetype of the data that follows. The frontend
should use that to look the type up in mime.types and prompt the user
whether to "Save to file" (for which the extension info from the mime
database is useful), "Open using application %s." (also from mime.types),
or to cancel the transmission.
Some frontends may also add "use internal viewer".

Frontends that do not want to care about mime or asking the user should
simply save away the stream "as-is" to a file, which allows for later
processing with mime-aware tools.

b) Content-Disposition: attachment; filename="suggested_filename"

This header seems to be used to suggest a filename to mime-aware programs.
Note, that the filename should be mangled by the frontend to conform to
OS-dependent conventions and that care should be taken to:
- Avoid security breaches using path separators, .., absolute paths, ...
- Avoid similar attacks directed at creating files like .rhosts or
overwriting them.

c) as the transport stream in SANE is assumed to be 8 bit clean (otherwise
other frame formats won't work), I see little use for stuff like
Content-Transfer-Encoding: base64
and similar.

5. As an alternative to the "inband" transmission suggested in 4., it would
be possible to either add a new call to SANE or extend the get_parameters
call to hold that information.
Inband allows for an arbitrary number of Headers, while outband at getparm
time seems a more natural approach from the code-flow and simplicity of
parsing standpoint. In that case, we should simply limit ourselves to
two strings containing mimetype and suggested filename.

Comments very welcome.

CU, ANdy

-- 
= Andreas Beck                    |  Email :  <andreas.beck@ggi-project.org> =

--
Source code, list archive, and docs: http://www.mostang.com/sane/
To unsubscribe: echo unsubscribe sane-devel | mail majordomo@mostang.com