Registering new file formats in extensions

Hello, a couple of days ago I started working on implementing the plugin.newFileFormat function (related issues: #54, #1403, #1949) that adds the ability to register new file formats from plugins / extensions.

I already have a working prototype that add the custom file formats to the Open..., Save and Save as... dialogs and call the appropriate functions depending on the action (see the images below). But before continuing with my implementation I want to discuss a problem I encountered.

There is a problem related to how a file format is detected when opening a file, right now the the dio::detect_format function is used, this function first calls the dio::detect_format_by_file_content which fails to detect the file format because this function is designed to detect only known internal file formats by comparing some bytes from the file to some know magic numbers, after that, the function call the dio::detect_format_by_file_extension which grabs the extension of the file that the user is trying to load, and compares it with some know file extension (ase, aseprite, bmp, png, etc), this function also fails to determine the format and returns the FileFormat::UNKNOWN enum value, the problem is that custom file formats can’t have their own dio::FileFormat value because you can’t add new values to an enum at runtime.

I have multiple ideas on how to solve this problem, please, let me know what you think of them:

  1. Move the responsibility of detecting if the file contents matches a particular format to the FileFormat class itself, for this I propose a new method called FileFormat::detect or FileFormat::validate which reads a small portion of the file and compares it with a know magic number or simply parses some of the headers to see if it makes sense.

  2. Refactor the dio::detect_format_by_file_extension function to compare the extensions from the file the user is trying to open to the extensions of all the registered file formats, if the extensions matches the file format gets returned.

Some images from aseprite with the new file formats added from lua

The new registered file formats as seen in the open file dialog:
image
The new registered file formats as seen in the native open file dialog (On Windows)
image

An example plugin designed to test the new API:

function init(plugin)
  plugin:newFileFormat({
    id="lod",
    extensions="lod",
    flags=FileSupport.LOAD,
    onload=function()
    end
  })
      
  plugin:newFileFormat({
    id="sav",
    extensions="sav",
    flags=FileSupport.SAVE,
    onsave=function()
    end
  })
      
  plugin:newFileFormat({
    id="las",
    extensions={"las","load-save"},
    flags=FileSupport.LOAD | FileSupport.SAVE,
    onload=function()
    end,
    onsave=function()
    end
  })
end
1 Like