Exporting Adobe color swatche .ase file

hello all,

I am generating some color palettes that I would like to export as .ase file to make it easier to import in Adobe softwares.
tried to use the HYPE library, but the palettes are just empty, I asked ChatGPT and it suggested using a library " java-ase ". I can not find it anywhere.
exporting as JSON file and then converting it to .ase is a tedious way for such an “easy” task.
chatGPT gave me the code but I can not find the org.json library neither.
is there any library you can recommend?
thanx

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import org.json.*;

void setup() {
  // Define colors
  color[] colors = {
    color(255, 0, 0),  // Red
    color(0, 255, 0),  // Green
    color(0, 0, 255)   // Blue
  };

  // Create JSON array for colors
  JSONArray colorsArray = new JSONArray();

  for (int i = 0; i < colors.length; i++) {
    int r = (int) red(colors[I]);
    int g = (int) green(colors[I]);
    int b = (int) blue(colors[I]);

    JSONObject colorObject = new JSONObject();
    colorObject.put("name", "Color" + i);
    colorObject.put("r", r);
    colorObject.put("g", g);
    colorObject.put("b", b);
    colorsArray.put(colorObject);
  }

  // Convert JSON to binary ASE format
  byte[] aseBytes = createASEBinary(colorsArray);

  // Save ASE file
  String filePath = sketchPath("colors.ase");
  try (FileOutputStream fos = new FileOutputStream(filePath)) {
    fos.write(aseBytes);
    println("ASE file saved at: " + filePath);
  } catch (IOException e) {
    e.printStackTrace();
  }
}

byte[] createASEBinary(JSONArray colorsArray) {
  ByteArrayOutputStream baos = new ByteArrayOutputStream();
  try {
    // Write ASE header
    baos.write("ASEF".getBytes(StandardCharsets.US_ASCII)); // Signature
    baos.write(ByteBuffer.allocate(2).putShort((short) 1).array()); // Version major
    baos.write(ByteBuffer.allocate(2).putShort((short) 0).array()); // Version minor
    baos.write(ByteBuffer.allocate(4).putInt(colorsArray.length()).array()); // Number of blocks

    // Write color blocks
    for (int i = 0; i < colorsArray.length(); i++) {
      JSONObject colorObject = colorsArray.getJSONObject(i);

      // Block type (Color entry)
      baos.write(ByteBuffer.allocate(2).putShort((short) 1).array());

      // Block length
      int blockLength = 20 + 4 * 4; // Name length + 4 floats
      baos.write(ByteBuffer.allocate(4).putInt(blockLength).array());

      // Color name
      String colorName = colorObject.getString("name");
      baos.write(ByteBuffer.allocate(2).putShort((short) colorName.length()).array());
      baos.write(colorName.getBytes(StandardCharsets.US_ASCII));
      baos.write(0); // Null terminator

      // Color model (RGB)
      baos.write("RGB ".getBytes(StandardCharsets.US_ASCII));

      // RGB values
      baos.write(ByteBuffer.allocate(4).putFloat(colorObject.getFloat("r") / 255).array());
      baos.write(ByteBuffer.allocate(4).putFloat(colorObject.getFloat("g") / 255).array());
      baos.write(ByteBuffer.allocate(4).putFloat(colorObject.getFloat("b") / 255).array());

      // Color type (global)
      baos.write(ByteBuffer.allocate(2).putShort((short) 0).array());
    }
  } catch (IOException e) {
    e.printStackTrace();
  }
  return baos.toByteArray();
}

You might be able to get away with a basic exporter like below. I tested with Krita and Online ASE File Converter | carl.camera , as I don’t use Adobe software. A lot of importers have issues of their own, so ymmv. Bear in mind that differences in color profile – especially between sRGB and Adobe RGB – will change how colors appear.

import java.io.FileOutputStream;

String filePath = "path\\to\\test.ase"; // Replace with real path
color[] colors = {
  0xff_ff0000,
  0xff_ffff00,
  0xff_00ff00,
  0xff_00ffff,
  0xff_0000ff,
  0xff_ff00ff,
};
int colorsLen = colors.length;

void setup() {
  try {
    FileOutputStream fos = new FileOutputStream(filePath);

    byte[] colorsLenBytes = {
      (byte)((colorsLen >> 0x18) & 0xff),
      (byte)((colorsLen >> 0x10) & 0xff),
      (byte)((colorsLen >> 0x08) & 0xff),
      (byte)((colorsLen >> 0x00) & 0xff),
    };

    byte[] version = { 0, 1, 0, 0 };

    String signature = "ASEF"; // 0x41534546
    byte[] sigBytes = signature.getBytes("UTF-8");

    fos.write(sigBytes);
    fos.write(version);
    fos.write(colorsLenBytes);

    String colorFormat = "RGB "; // 0x52474220
    byte[] colorFormatBytes = colorFormat.getBytes("UTF-8");

    byte[] entryHeader = { 0, 1 };
    byte[] blockLen = { 0, 0, 0, 34 };
    byte[] lenChars16 = { 0, 7 };
    byte[] normalColorMode = { 0, 2 }; // global|spot|normal

    for (int i = 0; i < colorsLen; ++i) {
      fos.write(entryHeader);
      fos.write(blockLen);
      fos.write(lenChars16);

      color c = colors[i];

      // int a8 = (c >> 0x18) & 0xff;
      int r8 = (c >> 0x10) & 0xff;
      int g8 = (c >> 0x08) & 0xff;
      int b8 = (c >> 0x00) & 0xff;

      String name = String.format("%06x", r8 << 0x10 | g8 << 0x08 | b8);
      byte[] nameBytes = name.getBytes("UTF-8");
      int lenNameBytes = nameBytes.length;
      byte[] zeroTerm16 = new byte[14];
      for (int j = 0; j < lenNameBytes; ++j) {
        zeroTerm16[1 + j * 2] = nameBytes[j];
      }

      float r01 = r8 / 255.0;
      float g01 = g8 / 255.0;
      float b01 = b8 / 255.0;

      int r01Int = Float.floatToIntBits(r01);
      int g01Int = Float.floatToIntBits(g01);
      int b01Int = Float.floatToIntBits(b01);

      byte[] r01Bytes = {
        (byte)((r01Int >> 0x18) & 0xff),
        (byte)((r01Int >> 0x10) & 0xff),
        (byte)((r01Int >> 0x08) & 0xff),
        (byte)((r01Int >> 0x00) & 0xff),
      };
      byte[] g01Bytes = {
        (byte)((g01Int >> 0x18) & 0xff),
        (byte)((g01Int >> 0x10) & 0xff),
        (byte)((g01Int >> 0x08) & 0xff),
        (byte)((g01Int >> 0x00) & 0xff),
      };
      byte[] b01Bytes = {
        (byte)((b01Int >> 0x18) & 0xff),
        (byte)((b01Int >> 0x10) & 0xff),
        (byte)((b01Int >> 0x08) & 0xff),
        (byte)((b01Int >> 0x00) & 0xff),
      };

      fos.write(zeroTerm16);
      fos.write(colorFormatBytes);
      fos.write(r01Bytes);
      fos.write(g01Bytes);
      fos.write(b01Bytes);
      fos.write(normalColorMode);
    }

    fos.flush();
    fos.close();
  }
  catch(Exception e) {
    printArray(e.getStackTrace());
  }
}

[Edit: I wrote this without seeing the bottom half of the posted code, which looks like it does mostly the same.]

If you’d like to read about the ASE format structure, see

If you’d like to read more about converting between sRGB and Adobe RGB, see

1 Like

thanx, your code is working perfectly ! :ok_hand: