{"id":11489,"library":"omggif","title":"GIF 89a Encoder/Decoder","description":"omggif is a JavaScript library designed for low-level encoding and decoding of GIF 89a format images. It provides explicit `GifReader` and `GifWriter` classes that operate directly on byte buffers, typically `Uint8Array`s or Node.js `Buffer`s. This gives developers granular control over every aspect of GIF generation, including frame dimensions, color palettes, delays, and other GIF specification details. First released in 2013 and last updated to version 1.0.10 in June 2017, the package is considered abandoned and has received no further maintenance or feature updates. While historically useful for both browser and Node.js environments due to its lightweight and pure JavaScript implementation, modern projects might find it lacks contemporary features, active community support, or the high-level abstractions found in more actively maintained GIF manipulation libraries.","status":"abandoned","version":"1.0.10","language":"javascript","source_language":"en","source_url":"https://github.com/deanm/omggif","tags":["javascript","gif","gif89a","gif87a","plask"],"install":[{"cmd":"npm install omggif","lang":"bash","label":"npm"},{"cmd":"yarn add omggif","lang":"bash","label":"yarn"},{"cmd":"pnpm add omggif","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"omggif was published before widespread ESM adoption. It primarily exports CommonJS modules. Direct ESM `import` might fail without specific Node.js `--experimental-modules` flags, `type: \"module\"` in package.json with `import` compatibility layers, or a bundler to transpile.","wrong":"import { GifReader } from 'omggif';","symbol":"GifReader","correct":"const { GifReader } = require('omggif');"},{"note":"Similar to GifReader, `GifWriter` is exposed via CommonJS. For modern ESM projects, consider using dynamic `import('omggif').then(mod => mod.GifWriter)` or a build step if direct `import` causes errors.","wrong":"import { GifWriter } from 'omggif';","symbol":"GifWriter","correct":"const { GifWriter } = require('omggif');"},{"note":"This pattern imports the entire module object, which is robust for older CommonJS libraries that might not explicitly define named exports for destructuring, though `omggif` does support it.","symbol":"All exports (CommonJS)","correct":"const omggif = require('omggif');\nconst reader = new omggif.GifReader(...);"}],"quickstart":{"code":"const { GifWriter, GifReader } = require('omggif');\n\n// --- Encoding a simple GIF ---\nconst width = 100;\nconst height = 100;\nconst frameCount = 2;\n\n// A generous buffer size for a 2-frame, 100x100 GIF with a palette\n// Realistically, calculate based on (width * height * numFrames) + header/metadata overhead\nconst outputBuffer = new Uint8Array((width * height * frameCount * 2) + 768); \n\nconst writer = new GifWriter(outputBuffer, width, height, { loop: 0 });\n\n// Define a simple palette (red, blue)\nconst palette = [\n  0xFF0000, // Red\n  0x0000FF  // Blue\n];\n\n// Frame 1: All red pixels (index 0 in palette)\nconst pixels1 = new Uint8Array(width * height).fill(0);\nwriter.addFrame(0, 0, width, height, pixels1, { palette, delay: 20 }); // 20ms delay\n\n// Frame 2: All blue pixels (index 1 in palette)\nconst pixels2 = new Uint8Array(width * height).fill(1);\nwriter.addFrame(0, 0, width, height, pixels2, { palette, delay: 20 }); // 20ms delay\n\n// Finalize the GIF and get the actual size\nconst finalSize = writer.end();\nconst encodedGifBuffer = outputBuffer.slice(0, finalSize);\n\nconsole.log(`Generated GIF of size: ${finalSize} bytes`);\n// In a Node.js environment, you could save this:\n// require('fs').writeFileSync('output.gif', encodedGifBuffer);\n\n// --- Decoding a GIF (example with a dummy buffer) ---\n// For actual use, 'gifDataBuffer' would come from a file read or network request\n// This is a minimal valid 1x1 GIF (header + LSD + GCT + IMG descriptor + LZW data + trailer)\nconst dummyGifDataBuffer = new Uint8Array([\n  0x47, 0x49, 0x46, 0x38, 0x39, 0x61, // GIF89a\n  0x01, 0x00, 0x01, 0x00,             // 1x1 canvas\n  0x80, 0x00, 0x00,                   // GCT present, 2 colors (2^1)\n  0xFF, 0xFF, 0xFF,                   // White (index 0)\n  0x00, 0x00, 0x00,                   // Black (index 1)\n  0x2C, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, // Image Descriptor: 1x1 at 0,0\n  0x02,                               // LZW Minimum Code Size\n  0x02, 0x4C, 0x01,                   // LZW Data (clear, data, EOI)\n  0x3B                                // GIF Trailer\n]);\n\ntry {\n  const reader = new GifReader(dummyGifDataBuffer);\n  console.log(`Decoded GIF: ${reader.width}x${reader.height}, ${reader.numFrames()} frame(s)`);\n\n  if (reader.numFrames() > 0) {\n    const frameInfo = reader.frameInfo(0);\n    console.log(`  First frame dimensions: ${frameInfo.width}x${frameInfo.height}`);\n    // To get pixel data, you'd use decodeAndBlitFrameRGBA:\n    // const pixelsRGBA = new Uint8Array(frameInfo.width * frameInfo.height * 4);\n    // reader.decodeAndBlitFrameRGBA(0, pixelsRGBA);\n  }\n} catch (e) {\n  console.error(\"Error reading GIF data:\", e.message);\n}\n","lang":"javascript","description":"This quickstart demonstrates how to use `omggif` to encode a simple two-frame animated GIF from raw pixel data and then how to initialize a `GifReader` for a given GIF byte buffer to extract metadata like dimensions and frame count. It highlights the low-level byte buffer manipulation required by the library."},"warnings":[{"fix":"For new projects, consider actively maintained alternatives like `gif.js` (for browser-side encoding) or `gifencoder` (Node.js encoding) which provide more modern APIs and ongoing support. For decoding, `gifuct-js` is a popular alternative.","message":"The `omggif` package is abandoned and has not received updates since June 2017. This means it may not be compatible with newer JavaScript features, Node.js versions, or browser environments, and could contain unpatched bugs or security vulnerabilities.","severity":"breaking","affected_versions":">=1.0.10"},{"fix":"Ensure your project is configured to handle CommonJS modules (e.g., using `require('omggif')` or a bundler that transpiles). If forced to use ES modules, dynamic `import()` or wrapper files might be necessary. Avoid setting `\"type\": \"module\"` in package.json without understanding its implications for CJS dependencies.","message":"omggif was primarily designed for CommonJS (`require`) module systems prevalent when it was last updated. Directly using ES Modules (`import`) in modern Node.js projects without appropriate bundler configuration (`webpack`, `rollup`) or Node.js settings can lead to `TypeError: require is not defined` or module resolution errors.","severity":"gotcha","affected_versions":">=1.0.10"},{"fix":"Always allocate a buffer that is generously sized to accommodate all frames and GIF metadata, or implement logic to progressively write to a dynamic buffer if the exact size is unpredictable. The `getOutputBufferPosition()` method can help monitor current usage.","message":"The `GifWriter` requires a pre-allocated `Uint8Array` buffer for its output. If the buffer is too small, the `end()` method might return a size larger than the allocated buffer, potentially causing data truncation or errors if not handled, as there's no automatic buffer resizing.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Thoroughly understand the GIF palette specification. Ensure pixel data arrays contain indices that correctly map to the provided palette. Pre-process image data for color reduction and palette generation before passing it to `omggif` for optimal results.","message":"omggif operates at a very low level, requiring manual management of color palettes for each frame or a global palette. Incorrectly defining palettes or pixel indices can lead to corrupted or incorrectly colored GIF output. The library does not perform color quantization or optimization automatically.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Use CommonJS `require` syntax: `const { GifReader } = require('omggif');`. Alternatively, ensure your build tool (like Webpack or Rollup) is configured to handle CommonJS dependencies within an ESM project, or use dynamic `import('omggif')` for asynchronous loading.","cause":"Attempting to use `omggif` with ES module `import` syntax (`import { GifReader } from 'omggif';`) in an environment that doesn't correctly resolve CommonJS exports for a module declared as ESM, or when the `omggif` module itself is not correctly exposed for ESM imports.","error":"TypeError: omggif.GifReader is not a constructor"},{"fix":"Verify the integrity of the GIF data buffer being passed to `GifReader`. Ensure it's a complete and correctly formatted GIF byte stream. Add robust error handling around `GifReader` instantiation to gracefully manage invalid input.","cause":"The input `Uint8Array` provided to `GifReader` does not contain a valid GIF 89a header or is otherwise malformed according to the GIF specification. This often happens with corrupted files or incorrect data sources.","error":"Error: Invalid GIF 89a stream."},{"fix":"For `GifWriter`, ensure the initial `Uint8Array` buffer is sufficiently large to contain the entire GIF. For `GifReader`, confirm the input buffer actually contains a full GIF and is not truncated. Debug the offsets being accessed if manually manipulating the buffer.","cause":"This error can occur when `GifReader` tries to read beyond the provided buffer, or when `GifWriter` attempts to write more data than its pre-allocated buffer can hold, especially if the `end()` method returns a larger size than the buffer length.","error":"RangeError: offset is outside the bounds of the DataView"}],"ecosystem":"npm"}