Иван Комиссаров schreef op 20-5-2015 om 13:36:
2015-05-20 13:19 GMT+03:00 André Somers <an...@familiesomers.nl
<mailto:an...@familiesomers.nl>>:
Иван Комиссаров schreef op 20-5-2015 om 11:06:
Show different error messages for instance. Invalid data points to
a corrupted file. That is not the same as just not recognizing the
file format or having a network connection break in the middle of
reading.
Different messages can be show using QString error() :) Anyway, i can
add enum later.
Problem is that you cannot show your _own_ message anymore. I might want
to choose a different wording in a message that I'd like to show to my
end user than something a Qt engineer choose. I also might like to offer
different choices for different results: a Retry may make sense in case
of a network error, but not in case of an unrecognized file type error...
Perhaps it should just read the header directly when opening from
file/iodevice and have an isValid() method or something like that?
Ok, do we really need separately open/read imageformat? AFAIK, not
evry format has useful header. For example, Icns has Table of
Contents, but it can be missing. AFAIK, without ToC, there's no way to
know how many mipmaps file contains.
In that case the pair of read/write (open/save) functions will be
enough. What do you think?
I think that it makes sense to attempt to load a header if it exists. If
not... Not sure. Probably need to read the entire file in order to
determine what it contains?
Agreed. On the other side, making document bounded to a type means
that simple operation "open(typeA) -> save(typeB)" becomes more
complex: "document-reader -> storage -> document-writer". Storage
should be some user-defined class. And it's up to user to decide what
parts of a document he will drop. I was thinking about the document as
the storage, not about reader+writer.
You would not need a separate reader and writer. You would need to have
an ImageDocument be specific about the type of image it represents. Your
operation would, I think, look like this:
ImageDocument imageDoc("thefile.png"); //imageDoc gets type from file: png
qDebug() << imageDoc.mimeType(); //outputs "image/png"
imageDoc.convert("image/jpeg"); //convert in-place to jpg document
qDebug() << imageDoc.mimeType(); //outputs "image/jpeg"
imageDoc.saveAs("thefile.jpg");
or
ImageDocument imageDoc("thefile.png");
qDebug() << imageDoc.mimeType(); //outputs "image/png"
imageDoc.converted("image/jpeg").saveAs("thefile.jpg"); //convert
in-place to jpg document
qDebug() << imageDoc.mimeType(); //outputs "image/png" as imageDoc
itself did not change
No need to say goodbye to your ImageDocument design and create your own
storage?
Thinking about this, I think I'd make the conversion explicit. If
you loaded a multipage TIFF and want to save as a normal PNG, you
could either have a void convert(QMimeType type) that converts the
current document to the new value (dropping unsupported features
in the process) and/or have a ImageDocument converted(QMimeType
type) function that creates a new ImageDocument in the requested
format based on the current document. Then, save _that_ document.
That can be done silently by handler while saving. Why do you want to
make the convertion explicit? My idea was that we lose information
only while saving, but not while dealing with document.
I would not like it much if information is silently dropped. If you make
the conversion explicit, it is also explicit what features are available
for the type you have now. How else are you going to expose that
information?
Perhaps you/the file format plugin could even offer different
options of how to deal with the degradation. Layers might be
flattened to a single image, meta data from a specific image
stored in the main meta data or vise versa, pages glued together
to form a single image... Even if the current structure doesn't
offer it, it would be nice if the API were such that such
fine-tuning would be possible.
I think, those options should be hardcoded in the plugins.
It would be nice to (some day) expose API to insert custom conversions I
think.
While replying, i've got an idea. What if we change capabilities from
"format caps" to the "document caps" and allow to choose what formats
support provided caps. Say - you need to save an array of cubemabs.
This is provided by DDS and Valve Texture Format - VTF (for example).
Or you need to save 1D array of animated frames. Those are supported
by GIF, APNG, VTF. In case you want to save "array of cubemaps with
volume textures on each side" - ok, no format support that. In case
you force to save into format with "poor" capabilities - ok, format
drops what it doesn't support.
I think it is useful if it is possible to query what formats support
what feature(s), or what other formats support the features the current
document uses, but that is not a core feature I'd say.
With something like document.images().frame(10).mipmap(5)? That
would result in a list of 6 images for the requested frame and
mipmap.
If images() returns a QVector<QImage>, you could use the same
trick as used in QByteArrayList to add some special filtering
methods on it without actually subclassing QVector<QImage>.
frame() and mipmap() (and side() and page() and layer() and
whatever else one might come up with) could act as filtering
functions that again return a list of images that has these methods.
Ok, it's better provide an example:
Document doc("1.dds"); // has mipmaps, depth and "frames"
doc.open(); doc.read(); doc.fooBar() // read some how
Why open explicitly?
ImageMeta toFilter;
What do you need a ImageMeta object for?
toFilter.setMipmap(1);
toFilter.setFrame(0);
toFilter.setSlice(5);
auto resources = doc->filter(toFilter); // returns one image
What type would resources be then? QImage? Something else?
toFilter.setMipmap(2);
toFilter.setSlice(0);
auto resources = doc->filter(toFilter); // returns all frames at depth 0
toFilter.setMipmap(3);
auto resources = doc->filter(toFilter); // returns all frames of all
depths
So, i'm still forced to specify 2 coordinates to the filter function +
i have to create and pass a meta structure. Why is it better than
2D-array?:)
That is an artefact of your choices, not inherent in how it could be. If
I rewrite you example using my suggested API, you'd end up with
something like this:
Document doc("1.dds"); // has mipmaps, depth and "frames"
QVector<QImage> resources; //lets be explicit what we return when
discussing API...
resources = doc->images().slice(5).frame(0).mipmap(1); //in any order,
resources is QVector<QImage>
resources = doc->images().slice(0).mipmap(2); // returns all frames at
depth 0
resources = doc->images().mipmap(3); //returns all images of all depths
But also:
QImage firstPage = doc->images().page(0).first();
QImage secondPage = doc->images().page(1).first();
Well, I don't know how your Meta things work of course, so I
cannot comment on that. To me it makes little sense to set a meta
property that belongs to a specific image on a document directly,
but that may be my misunderstanding of your design.
Icns is an *array* of images. Typically those are mipmaps, however
there can be elements with the same size. What is important is that
each element can have it's own subtype - 1st element is 1024*1024 jp2
compressed image (quality, exif can be embedded into it), 1nd element
is a 512*512 PNG image (some other option), last element is 1x1 RGBA
image (no options at all)
If you want to set certain meta data attributes on all images in the
document in one go, then that still isn't the same as setting it on the
document itself, right? I'd keep them separate for now. You can always
add convenience API that does that later on. Start out with the minimum,
built up from there in later releases.
I think it is actually simpler than forcing a 2D array onto image
document formats that don't benefit from it.
What if i add another layer - Page/Frame: Document <>-- Page <>--
Resource. Page can (or cannot) have mipmaps and/or preview image.
if (doc->capabilities() & HasPages) {
for (int i = 0; i < doc->pageCount(); i++)
auto page = doc->page(i);
if (doc->capabilites() & hasPreview) {
auto preview = page.preview();
} else (hasMimpaps) {
for (mimpaps)
auto resource = page.resource(mipmapIndex);
} else {
auto resource = page.resource(); // aka page.resouce(0);
}
} else {
auto resource = doc->page().resource();
}
It's complicated, but a bit better than 2D array.
I don't think that helps. Now you are forcing a page paradigm on image
documents that don't support *that*. The problem is that there are
multiple orthagonal dimensions here (I think we have seen 'page',
'frame', 'mipmap', 'side', and 'depth' so far) and that which dimensions
really materialize depends on the image format. Imposing any of these in
the hard-coded structure of the document will hinder all other formats
interaction with it. If you tend to work with 3D stuff, you might want
to get the 3D aspects like sides, mipmaps and depth more to the front of
the API. If you want to show multi-page documents, you might think that
pages really need to be there, and if you build an image viewer you just
might need a quick way to query for something to use as a thumbnail
fast. I think that if you want to stay agnostic to the application of
ImageDocument, you should try to avoid pinning your API to any of these
dimensions.
How do i supposed to control that EACH mipmap have the same
number of frames as document->frameCount(). I didn't find
suitable solution.
Why would you need to control that? If an image format requires
it, then that image format should impose that limit (or even
auto-create the missing ones?) but I don't see why it should be a
general limitation. Perhaps there are formats where it is possible
that one page has a mipmap, while others don't? Just the first
page for instance to provide a quick preview?
Sure, we can generate missing mipmaps. We can even "generate" missing
sides of a cubemap (black/opaque image of the required size) or slices
of the volume texture. But we can't generate missing frames. Suppose
you've added (frame0, mipmap0) and (frame2, mipmap0) images. Frame 3
is missing and there's no way to generate it. More, such API allows to
add frame and mipmaps that are out of bounds.
So?
The image plugin would return an error on writing I'd think? Or even
isValid() would go to false? But it depends on the image format what is
to be considered valid right? As those are pluggable, I don't think your
generic API should restrict the options.
Andre
_______________________________________________
Interest mailing list
Interest@qt-project.org
http://lists.qt-project.org/mailman/listinfo/interest