another machine Steganography GitHub

Stega64 encodes and decodes messages in image pixels.

Stega64.encode({ source: HTMLImageElement | HTMLCanvasElement; messages: string[]; encoding: Stega64Encoding; encodeMetadata: boolean; minWidth?: number; minHeight?: number; borderWidth?: number; }): HTMLCanvasElement

const source = await loadImageFromImageUrl({
  url: "./example.jpg" 
});
Stega64.encode({
  source,
  encoding: "",
  encodeMetadata: ,
  messages: [""],
  minWidth: ,
  minHeight: ,
  borderWidth: ,
  aspectRatio: 
})

Stega64.decode({ source: HTMLImageElement | HTMLCanvasElement; encoding: Stega64Encoding; borderWidth?: number; }): String

const result = Stega64.decode({ source });

Stegassette encodes multi-payload entries in image pixels using the STGC format.

Stegassette.encode({ source: HTMLImageElement | HTMLCanvasElement; entries: Entry[]; combine?: CombineName; keymap?: KeymapName; traversal?: TraversalName; bitsPerSample?: number; border?: number; aspectRatio?: number; }): HTMLCanvasElement

const audioBuffers = await loadAudioBuffersFromAudioUrl({
  url: "./example.mp3",
  audioContext,
  channels: ,
  sampleRate: ,
});
const audioEntry = Stegassette.buildAudioEntry({
  channels: audioBuffers,
  sampleRate: ,
  bitsPerSample: ,
});
const encoded = Stegassette.encode({
  source,
  entries: [audioEntry],
  combine: "",
  keymap: "",
  traversal: "",
  border: ,
  aspectRatio: ,
});
tap to play

Stegassette.decode({ source: HTMLImageElement | HTMLCanvasElement | StegaImageData }): { entries: DecodedEntry[]; opts: StgcOpts }

const { entries, opts } = Stegassette.decode({ source: encoded });
// opts: { combine, keymap, traversal } recovered from STGC header
const { channels, sampleRate } = Stegassette.parseAudioEntry(entries[0]);
const recon = Stegassette.reconstructCover(encoded, opts);
// recon develops on the canvas in sync with audio playback

Encoding audio waveforms in image pixels.

This is a demonstration of how waveforms are stored inside of pixels using StegaCassette.

Source waveform (drag to move the playhead)
64 sample waveform | 1.3ms of audio
24-bit | 64 colors with red, green, and blue channels separated above | 1 sample per pixel
64 sample waveform as a 8×8px image
Source waveform encoded into image

Animate steganographic image

new StegaAnimator({ resolution: number; source: HTMLImageElement | HTMLCanvasElement; fadeAmount?: number; rotationMode?: "2d" | "3d"; shape?: "circle" | "square" | "implicit"; })

const animator = new StegaAnimator({
  source,
  resolution: ,
  fadeAmount: ,
  rotationMode: "",
  shape: ""
});
document.body.appendChild(animator.canvas);
await animator.animate({
  from: { rotation: Math.PI, scale: 0.0, x: 0.5, y: 0.5, },
  to: { rotation: Math.PI * 4, scale: 0.5, x: 0.5, y: 0.5, },
  rate: 0.005,
});
const killLoop = animator.animationLoop([
  {
    from: { rotation: 0, scale: 0.5, x: 0.5, y: 0.5, },
    to: { rotation: Math.PI * 1, scale: 0.6, x: 0.5, y: 0.5, },
    rate: ,
  },
  {
    from: { rotation: Math.PI * 1, scale: 0.6, x: 0.5, y: 0.5, },
    to: { rotation: Math.PI * 2, scale: 0.5, x: 0.5, y: 0.5, },
    rate: ,
  },
]);
killLoop();

Load an audio buffer from a url string

async loadAudioBuffersFromAudioUrl({ url: string; audioContext: AudioContext; channels: StegaCassetteChannels; sampleRate?: number; }): Promise<Float32Array[]>

const audioContext = new AudioContext();
const audioBuffer = await loadAudioBuffersFromAudioUrl({
  url: "./example.mp3",
  audioContext,
  sampleRate: audioContext.sampleRate,
});

Load an image from a url string

async loadImageFromImageUrl({ url: string }): Promise<HTMLImageElement>

const audioBuffer = await loadImageFromImageUrl({
  url: "./example.jpg"
});

Play decoded audio buffers

async playDecodedAudioBuffers({ audioBuffers: Float32Array[]; audioContext: AudioContext; sampleRate?: number; }): Promise<AudioBufferSourceNode>

const source = await playDecodedAudioBuffers({
  audioBuffers,
  audioContext,
  sampleRate: audioContext.sampleRate,
});
source.stop();

Turn an HTML element into a file drop area

createDropReader({ element: HTMLElement; onSuccess: (element: HTMLImageElement | HTMLAudioElement) => void; onFailure?: (message: string) => void; onDragEnter?: () => void; onDragLeave?: () => void; onDrop?: () => void; types?: (AudioType | ImageType)[]; }): void

const element = document.body;
createDropReader({
  element,
  onSuccess: (image) => element.appendChild(image),
  onFailure: (message) => console.error(message),
  onDragEnter: () => element.classList.add("droppable"),
  onDragLeave: () => element.classList.remove("droppable"),
  onDrop: () => element.classList.remove("droppable"),
  types: ["image/*"]
});

Turn an HTML input into a file input

createFileReader({ element: HTMLInputElement; onSuccess: (element: HTMLImageElement | HTMLAudioElement) => void; onBinarySuccess?: (result: { data: Uint8Array; mimeType: string; fileName: string }) => void; onFailure?: (message: string) => void; types?: (AudioType | ImageType | VideoType | "*/*")[]; }): void

const element = document.createElement("input");
createFileReader({
  element,
  onSuccess: (image) => document.body.appendChild(image),
  onFailure: (message) => console.error(message),
  types: ["image/*"]
});

// Or for binary data (any file type)
createFileReader({
  element,
  onBinarySuccess: ({ data, mimeType, fileName }) => {
    console.log(`Loaded ${fileName} (${mimeType}): ${data.length} bytes`);
  },
  types: ["*/*"]
});

Read a file as binary bytes

readFileAsBytes({ file: File }): Promise<{ data: Uint8Array; mimeType: string; fileName: string }>

const input = document.createElement("input");
input.type = "file";
input.onchange = async () => {
  const file = input.files[0];
  const { data, mimeType, fileName } = await readFileAsBytes({ file });
  console.log(`Read ${fileName} (${mimeType}): ${data.length} bytes`);
};

Convert binary data to a Blob URL

bytesToBlobUrl({ data: Uint8Array; mimeType: string }): string

const url = bytesToBlobUrl({ data: myBytes, mimeType: "image/png" });
const img = document.createElement("img");
img.src = url;
document.body.appendChild(img);

// Remember to revoke when done
URL.revokeObjectURL(url);

Download binary data as a file

downloadBytes({ data: Uint8Array; mimeType: string; fileName: string }): void

downloadBytes({
  data: myBytes,
  mimeType: "application/pdf",
  fileName: "document.pdf"
});