[Development] Fwd: [Interest] Imageformats v2

Иван Комиссаров abbapoh at gmail.com
Wed May 20 17:14:20 CEST 2015

btw, wrong list again:(

---------- Forwarded message ----------
From: Иван Комиссаров <abbapoh at gmail.com>
Date: 2015-05-20 14:36 GMT+03:00
Subject: Re: [Interest] [Development] Imageformats v2
To: André Somers <andre at familiesomers.nl>
Cc: "interest at qt-project.org" <interest at qt-project.org>

2015-05-20 13:19 GMT+03:00 André Somers <andre at 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.

> 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?

> Not sure if that is a good idea. If you didn't open the device, you should
> not close it.

 Ok, i removed close()

> Fair enough. But that means I think that an ImageDocument should have a
> clear type at any time. That means you either create it with that type, get
> the type from the image you are reading, or convert to that type.

> Well, you can if you know the capabilities of the file you want to create,
> I'd say. I don't think I would allow adding resources to a file if the
> format can't support those resources.

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

> 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.

> 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.
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.

> 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
ImageMeta toFilter;
auto resources = doc->filter(toFilter); // returns one image

auto resources = doc->filter(toFilter); // returns all frames at depth 0

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?:)

> 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)

> 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.

> 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.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/development/attachments/20150520/948722af/attachment.html>

More information about the Development mailing list