Иван Комиссаров 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

Reply via email to