FastLED 3.9.15
Loading...
Searching...
No Matches
libnsgif Directory Reference
+ Directory dependency graph for libnsgif:

Directories

 include
 
 src
 

Files

 _build.cpp.hpp
 
 software_decoder.cpp.hpp
 
 software_decoder.h
 

Detailed Description

Pulled from: https://www.netsurf-browser.org/projects/libnsgif/

Current Status

FastLED Third-Party Namespace Architecture

FastLED mandates that all third-party libraries be wrapped in the fl::third_party namespace to:

1. Prevent Global Namespace Pollution

// Before: Global namespace collision risk
struct nsgif { /* ... */ };
// After: Safely namespaced
namespace fl {
namespace third_party {
struct nsgif { /* ... */ };
}
}
Base definition for an LED controller.
Definition crgb.hpp:179

2. Clear Ownership and Licensing Boundaries

The fl::third_party namespace makes it immediately clear:

3. Controlled Integration Points

// Third-party code stays isolated
namespace fl::third_party {
struct nsgif { /* Original C API */ };
nsgif_error nsgif_create(nsgif **gif, nsgif_bitmap_cb_vt *bitmap_callbacks);
// Software decoder implementation within third-party namespace
class SoftwareGifDecoder : public fl::IDecoder {
nsgif* decoder_; // Direct access to nsgif within same namespace
// IDecoder interface implementation for animated GIFs
};
}
// FastLED provides clean factory interface
namespace fl {
// GIF decoder factory (following MPEG1 pattern for multi-frame formats)
class Gif {
public:
// Create a GIF decoder for the current platform
static fl::shared_ptr<IDecoder> createDecoder(const GifConfig& config, fl::string* error_message = nullptr);
// Check if GIF decoding is supported on this platform
static bool isSupported();
};
}
static IDecoderPtr createDecoder(const GifConfig &config, fl::string *error_message=nullptr)
Definition gif.cpp.hpp:9
static bool isSupported()
Definition gif.cpp.hpp:23
Definition gif.h:42
nsgif_error
LibNSGIF return codes.
Definition nsgif.hpp:58
struct fl::third_party::nsgif_bitmap_cb_vt nsgif_bitmap_cb_vt
Bitmap callbacks function table.
nsgif_error nsgif_create(const nsgif_bitmap_cb_vt *bitmap_vt, nsgif_bitmap_fmt_t bitmap_fmt, nsgif_t **gif_out) FL_NOEXCEPT
Create the NSGIF object.
Definition gif.cpp.hpp:1493

4. Implementation Benefits

Namespace Isolation

API Transformation

Maintenance Advantages

5. Libnsgif Example

The libnsgif implementation will demonstrate this pattern:

// File: nsgif.h
namespace fl {
namespace third_party {
// Original libnsgif API preserved
typedef struct nsgif nsgif;
typedef enum {
NSGIF_INSUFFICIENT_MEMORY,
NSGIF_DATA_ERROR,
// ... other error codes
nsgif_error nsgif_create(nsgif **gif, nsgif_bitmap_cb_vt *bitmap_callbacks);
nsgif_error nsgif_data_scan(nsgif *gif, size_t size, const uint8_t *data);
nsgif_error nsgif_frame_decode(nsgif *gif, uint32_t frame, nsgif_bitmap_t **bitmap);
}
}
// File: fl/codec/gif.h
namespace fl {
// GIF-specific configuration
struct GifConfig {
bool looping = true;
fl::u16 maxWidth = 1920;
fl::u16 maxHeight = 1080;
fl::u8 bufferFrames = 3; // For smooth animation
};
// GIF decoder factory
class Gif {
public:
// Create a GIF decoder for the current platform
static fl::shared_ptr<IDecoder> createDecoder(const GifConfig& config, fl::string* error_message = nullptr);
// Check if GIF decoding is supported on this platform
static bool isSupported();
};
// Software GIF decoder implementation (in fl::third_party namespace)
namespace third_party {
class SoftwareGifDecoder : public IDecoder {
nsgif* decoder_; // Direct access to nsgif within same namespace
// Complete IDecoder interface implementation for animated GIFs
};
}
}
Software GIF decoder implementation using libnsgif.
unsigned char u8
Definition s16x16x4.h:132
fl::u32 uint32_t
Definition coder.h:219
@ NSGIF_OK
Success.
Definition nsgif.hpp:62
nsgif_error nsgif_data_scan(nsgif_t *gif, fl::size size, const fl::u8 *data) FL_NOEXCEPT
Scan the source image data.
Definition gif.cpp.hpp:1616
nsgif_error nsgif_frame_decode(nsgif_t *gif, fl::u32 frame, nsgif_bitmap_t **bitmap) FL_NOEXCEPT
Decodes a GIF frame.
Definition gif.cpp.hpp:1953
void nsgif_bitmap_t
Client bitmap type.
Definition nsgif.hpp:175
unsigned char uint8_t
Definition coder.h:209
PixelFormat
Definition pixel.h:7
@ Streaming
Definition gif.h:30
@ SingleFrame
Definition gif.h:30
PixelFormat format
Definition gif.h:33
fl::u8 bufferFrames
Definition gif.h:34
FrameMode mode
Definition gif.h:32

6. Guidelines for Third-Party Integration

When adding new third-party libraries to FastLED:

  1. Always use fl::third_party namespace - Non-negotiable requirement
  2. Preserve original APIs - Don't modify third-party code unnecessarily
  3. Create FastLED wrappers - Provide clean C++ APIs following project conventions
  4. Document boundaries clearly - Make it obvious what's third-party vs. FastLED native
  5. Handle type conversions - Bridge between third-party types and FastLED types
  6. Manage memory correctly - Use FastLED memory management patterns in wrappers

This architecture ensures FastLED remains maintainable, extensible, and free from the complexities often introduced by direct third-party library integration.

Implementation Plan

🔄 Phase 1: Library Modernization (PENDING)

  1. C++ Conversion
    • gif.cgif.cpp
    • lzw.clzw.cpp
    • ⏳ Updated includes and linkage
  2. Namespace Wrapping
    namespace fl {
    namespace third_party {
    // All libnsgif code wrapped here
    }
    }
    • ⏳ All libnsgif structures and functions properly namespaced
  3. Dependency Cleanup
    • ⏳ Platform-specific includes cleaned up
    • ⏳ Integration with FastLED type system
    • ⏳ ByteStream compatibility implemented

🔄 Phase 2: FastLED Integration (PENDING)

  1. Bridge Implementation (src/third_party/libnsgif/software_decoder.h)
    namespace fl::third_party {
    class SoftwareGifDecoder : public fl::IDecoder {
    nsgif* decoder_;
    fl::GifConfig config_;
    // Complete IDecoder interface implementation
    bool begin(fl::ByteStreamPtr stream) override;
    DecodeResult decode() override;
    Frame getCurrentFrame() override;
    bool hasMoreFrames() const override;
    fl::u32 getFrameCount() const override;
    bool seek(fl::u32 frameIndex) override;
    };
    }
    fl::u32 getFrameCount() const FL_NOEXCEPT override
    fl::Frame getCurrentFrame() FL_NOEXCEPT override
    fl::DecodeResult decode() FL_NOEXCEPT override
    bool hasMoreFrames() const FL_NOEXCEPT override
    bool seek(fl::u32 frameIndex) FL_NOEXCEPT override
    bool begin(fl::filebuf_ptr stream) FL_NOEXCEPT override
    DecodeResult
    Definition idecoder.h:18
    • ⏳ Full IDecoder interface implementation in third-party namespace
  2. Factory Class Implementation (src/fl/codec/gif.cpp)
    namespace fl {
    fl::shared_ptr<IDecoder> Gif::createDecoder(const GifConfig& config, fl::string* error_message) {
    // Create and return fl::third_party::SoftwareGifDecoder instance
    }
    return true; // libnsgif is always available
    }
    }
    shared_ptr< T > make_shared(Args &&... args) FL_NOEXCEPT
    Definition shared_ptr.h:414
    • ⏳ Factory class following MPEG1 pattern for multi-frame formats
  3. Configuration Mapping
    • GifConfig::looping → GIF animation loop handling
    • GifConfig::format → pixel format conversion
    • GifConfig::maxWidth/Height → size validation
    • GifConfig::mode → SingleFrame vs Streaming animation
    • GifConfig::bufferFrames → animation frame buffering
  4. Memory Management
    • ⏳ C memory allocation replaced with FastLED patterns
    • fl::scoped_array and buffer management implemented
    • ⏳ Callback-based bitmap creation converted to frame buffer approach

🔄 Phase 3: Integration & Testing (PENDING)

  1. Factory Class Implementation
    • Gif::createDecoder() factory function implemented
    • Gif::isSupported() platform detection function
    • ⏳ Clean public API in fl/codec/gif.h
    • ⏳ Integration with existing codec framework
  2. IDecoder Interface Implementation
    • begin() - Initialize with ByteStream for streaming GIF data
    • decode() - Decode next frame with proper state management
    • getCurrentFrame() - Return current decoded frame
    • hasMoreFrames() - Check for additional animation frames
    • getFrameCount() - Total frame count for animations
    • seek() - Jump to specific frame index
  3. Error Handling
    • nsgif_error codes mapped to FastLED DecodeResult enum
    • ⏳ Comprehensive error message reporting via hasError()
    • ⏳ Graceful handling of malformed GIF data
  4. Advanced Features
    • ⏳ Multiple pixel format support (RGB888, RGB565, RGBA8888)
    • ⏳ Animation frame iteration and timing
    • ⏳ Transparency and disposal method handling
    • ⏳ Memory-efficient streaming decode with frame buffering

Key Challenges (TO BE ADDRESSED)

Planned API

The GIF decoder will provide comprehensive animated GIF support using the IDecoder interface:

Basic Usage

#include "fl/codec/gif.h"
// Create GIF decoder for animated content
config.mode = fl::GifConfig::Streaming; // For animations
config.looping = true;
fl::string error;
auto decoder = fl::Gif::createDecoder(config, &error);
if (!decoder) {
printf("GIF decoder creation failed: %s\n", error.c_str());
return;
}
// Initialize with GIF data stream
auto stream = fl::ByteStream::fromSpan(gif_data_span);
if (!decoder->begin(stream)) {
printf("Failed to initialize GIF decoder\n");
return;
}
const char * c_str() const FL_NOEXCEPT

Animation Support

// Decode animation frames
while (decoder->hasMoreFrames()) {
auto result = decoder->decode();
if (result == fl::DecodeResult::Success) {
fl::Frame frame = decoder->getCurrentFrame();
// Display or process the frame
displayFrame(frame);
// Get current frame info
fl::u32 currentIndex = decoder->getCurrentFrameIndex();
printf("Displaying frame %u of %u\n", currentIndex, decoder->getFrameCount());
} else if (result == fl::DecodeResult::EndOfStream) {
// Animation complete
break;
} else if (result == fl::DecodeResult::Error) {
fl::string error;
decoder->hasError(&error);
printf("Decode error: %s\n", error.c_str());
break;
}
}
// Cleanup
decoder->end();

Random Access Support

// Jump to specific frame
fl::u32 targetFrame = 10;
if (decoder->seek(targetFrame)) {
auto result = decoder->decode();
if (result == fl::DecodeResult::Success) {
fl::Frame frame = decoder->getCurrentFrame();
// Process frame 10
}
}

Advanced Configuration

// Custom configuration for memory-constrained environments
config.format = fl::PixelFormat::RGB565; // 16-bit color to save memory
config.maxWidth = 800; // Size limits
config.maxHeight = 600;
config.bufferFrames = 2; // Minimal buffering
config.mode = fl::GifConfig::SingleFrame; // Just decode one frame

Platform Support

// Check if GIF decoding is available
// GIF decoding available
} else {
// Platform doesn't support GIF
}

Integration with FastLED Codecs

The GIF decoder integrates seamlessly with FastLED's codec architecture:

Unit Test Design

Planned test framework: tests/codec_gif.cpp

Required Test Coverage

Phase 1: Basic Functionality

TEST_CASE("GIF libnsgif decoder initialization") {
// Test NsGifDecoder specific initialization
// Verify callback setup and memory allocation
// Check namespace wrapping
}
TEST_CASE("GIF valid file decoding") {
// Test with minimal valid GIF data
// Verify frame dimensions and pixel data
// Check memory allocation patterns
}

Phase 2: Animation Support

TEST_CASE("GIF animation frame handling") {
// Test multi-frame GIF decoding
// Verify frame count detection
// Check frame-by-frame decoding accuracy
}
TEST_CASE("GIF transparency and disposal") {
// Test transparent GIF handling
// Verify background disposal methods
// Check alpha channel preservation
}

Phase 3: Format Support

TEST_CASE("GIF pixel format conversion") {
// Test RGB888, RGB565, RGBA8888 output formats
// Verify color palette conversion accuracy
// Check byte ordering and alignment
}
TEST_CASE("GIF interlaced decoding") {
// Test interlaced GIF support
// Verify progressive rendering capability
// Performance benchmarks for different settings
}

Phase 4: Edge Cases & Performance

TEST_CASE("GIF large animation handling") {
// Test maxWidth/maxHeight enforcement
// Memory usage validation with many frames
// Animation timing accuracy
}
TEST_CASE("GIF malformed data") {
// Truncated files, invalid headers
// Corrupted frame data recovery
// Memory leak detection
}
TEST_CASE("GIF stress testing") {
// Multiple decode operations
// Concurrent decoder instances
// Large animation sequences
}

Test Data Requirements

Integration with Existing Test Suite

Status: Test suite to be created

  1. ⏳ Create tests/codec_gif.cpp following existing codec test patterns
  2. ⏳ Add libnsgif-specific test cases alongside generic codec tests
  3. ⏳ Integration with FastLED test runner

API Integration (PLANNED)

File Structure

API Components

Libnsgif Library Overview

Libnsgif is a decoding library for GIF image format, originally developed for the NetSurf web browser. Key features include:

Core Capabilities

Technical Specifications

Integration Advantages

Summary

The libnsgif integration is PLANNED and represents the next step in FastLED's codec expansion. Once complete, the GIF decoder will provide:

  1. Full GIF format support including animations and transparency
  2. Clean C++ API following FastLED conventions
  3. Multiple pixel formats (RGB888, RGB565, RGBA8888)
  4. Animation frame control with timing and sequencing
  5. Memory-efficient operation using FastLED buffer management
  6. Comprehensive error handling with descriptive messages
  7. Full test coverage and validation

The implementation will follow the established third-party integration pattern used successfully with TJpg_Decoder, ensuring consistent architecture and maintainability across FastLED's codec ecosystem.