Add support for non-square heightmaps. Improve import dialog. Fix various import export bugs.
ClosedPublic

Authored by victorw on Jul 1 2017, 3:35 PM.

Details

Summary

New Import/Export dialog + rewrote how loading and saving is done for related file types. Fixes issues 381774, 381830, and 381866.

These formats have no official spec and no standard file extension, so I used output from World Machine to test it. World Machine can output .r16 for 16bit integer heightmaps and .raw for 8bit integer heightmaps. .raw files have to be renamed to .r8 for Krita to handle them.

Will add unit tests if it makes sense.

Diff Detail

Repository
R37 Krita
Lint
Automatic diff as part of commit; lint not applicable.
Unit
Automatic diff as part of commit; unit tests not applicable.
victorw created this revision.Jul 1 2017, 3:35 PM
victorw added inline comments.Jul 1 2017, 3:45 PM
plugins/impex/heightmap/kis_wdg_options_heightmap.cpp
55

This turned out to be a bit overkill. Originally I had plans for making a generic raw data import/export dialog, but since Krita is heavily tied to file extensions this is not really feasible right now.

If you feel strongly about it I could create a custom export dialog that only has the bare minimum functionality for exporting.

Screenshot of the new import dialog:

rempt edited edge metadata.Jul 3 2017, 8:52 AM

Can the endianness still really be described by PC vs Mac? Mac have been x86 for ages now.

In D6460#121238, @rempt wrote:

Can the endianness still really be described by PC vs Mac? Mac have been x86 for ages now.

I guess some programs still refer to it that way, but it's indeed pretty misleading nowadays. :)

Considering the context, it's not unreasonable to expect users to know the difference between little and big endian when working with heightmaps. If they don't they can always guess and see if the result looks OK.

I'll get rid of the PC/Mac references!

victorw updated this revision to Diff 16186.Jul 4 2017, 9:55 PM
  • Removed references of PC and Mac from the UI.
  • Added standard file diff unit tests (disabled because the function is broken?)

Actual test files omitted from review, will commit with the rest of the code.

Updated screenshot of import dialog:

dkazakov edited edge metadata.Jul 6 2017, 10:34 AM

The patch looks fine. Though I'd suggest two small fixes to make UIX more obvious:

  1. When importing and exporting set endianness to the default endianness of the currently running system. Or at least save the last used value and reuse it next time. Right now the UIX is not very smooth:
    1. User saves .r16 map in big-endian mode
    2. User opens the file, the dialog suggests him that the file is little-endian (not nice, but okay)
    3. User opens the same file again, and the dialog suggests him that the file is little-endian again (already not okay, can make people furious :) )
  2. [disputable] The size fields could make some initial guess about the files, not just plain zeros. Though it is more wish than a big.
plugins/impex/heightmap/kis_heightmap_export.cpp
55
  1. Please use const iterators for reading data. It saves memory and time, due to absence copy-on-write operation.
  2. You can also use KisSequentialContIterator for this purpose. It is easier and almost twice faster that usual hline iterator.

The patch looks fine. Though I'd suggest two small fixes to make UIX more obvious:

  1. When importing and exporting set endianness to the default endianness of the currently running system. Or at least save the last used value and reuse it next time. Right now the UIX is not very smooth:
    1. User saves .r16 map in big-endian mode
    2. User opens the file, the dialog suggests him that the file is little-endian (not nice, but okay)
    3. User opens the same file again, and the dialog suggests him that the file is little-endian again (already not okay, can make people furious :) )

Yes, I agree! I have a list of smaller improvements I'd like to make, though at some point I'd also like to push what I have since it's fixing stuff and not introducing regressions.

I made a small attempt at keeping state in the dialog, though I admit I didn't spend much time on it.

Some thoughts I had while I wrote this:

  1. It's hard to give solid defaults for this; you can't tell what the user wants by just looking at the file, since there is zero metadata.
  2. I don't think there is going to be much correlation between the user's hardware and the format of the file; it's entirely arbitrary and more likely to be decided by the project you work on. If anything it'll likely depend on the source of the data. I'd like to say little endian is by far more common, but that's based on my own experience which is limited to a subset of one industry.
  3. I'd like for the dialog to have some memory, but then I started thinking about use-cases. Ultimately what we want is to minimize the amount of times the user has to change values in the dialog, so I came up with two options:
    1. Remember the last used setting. This might be good if you work on a project where all files are created with the same settings. Going by my own experience, this would be reasonable. However:
    2. If you open a lot of different heightmaps, all with different endianness, then you will hate the state tracking feature. That said I don't think this scenario is very common; if you work with lots of source files of arbitrary endianness, then one of the first things you'd do is convert everything to the same endianness. If only because that would make your life a whole lot simpler... Even so, if we want to target this scenario, then we have to track different dialog states for different file paths. This would just add complexity and introduce a bunch of new problems for what is currently only a hypothetical scenario.

So, I'll give the dialog state tracking another go. As I don't have anything but my own experience to go on, I'll aim for this:

  1. Default to little endian, no heuristics, no added complexity (this also makes the behaviour more predictable)
  2. Remember states, no file tracking or other heuristics; if you change the endianness it will stay that way until you change it back (or clear your settings). This accommodates those who primarily works with big endian files.
  3. Separate states for the import and export dialog. That way it'll be able to accommodate a scenario where Krita is used to convert heightmaps from one endianness to another.
  1. [disputable] The size fields could make some initial guess about the files, not just plain zeros. Though it is more wish than a big.

I assume you're talking about the width/height input fields? I thought about that as well, and while it might save one click there are two reasons I decided against it:

  1. If the heightmap is not square, then the risk of providing false positives is too big.
  2. Filling in defaults that might be incorrect can give users the impression that the program knows best, and that changing them is not something you should do.

By disabling the OK button until acceptable values have been filled in, my hope was that the first thing a user would do is try clicking on the guess button to see what it does (I like interfaces that encourages you to explore and try things!)

victorw added inline comments.Jul 6 2017, 10:08 PM
plugins/impex/heightmap/kis_heightmap_export.cpp
55
  1. Oops. Thanks for catching that!
  2. Looks neat, I'll switch to it.

I'm still fumbling around in the code base, and have no idea about Krita specific best practices. I really appreciate these recommendations!

victorw updated this revision to Diff 16366.Jul 8 2017, 8:47 PM
  • Added importConfiguration helper functions to KisConfig that mimics exportConfiguration, but with a different tag
  • Remember endianness for import and export heightmap dialog separately, per mime type
  • Use KisSequentialConstIterator when exporting data
victorw added inline comments.Jul 8 2017, 9:06 PM
libs/ui/kis_config.cc
1222

Oops, I've renamed this to importConfig (won't update diff).

Copy/pasted from exportConfiguration() and setExportConfiguration(), but with a different tag.

libs/ui/kis_config.h
328

I'm guessing there has never been a need for user input during import.

If you feel that this is not the right direction to go in, feel free to suggest other ways of storing import settings. For now I'm just imitating the behaviour so import and export settings follow similar patterns in kritarc.

dkazakov accepted this revision.Jul 14 2017, 10:41 AM

Hi, @victorw!

The patch works perfectly fine now! Please push! :)

This revision is now accepted and ready to land.Jul 14 2017, 10:41 AM
This revision was automatically updated to reflect the committed changes.