Thank you for your interest in contributing to DitherIt! We welcome contributions from everyone, whether you're fixing bugs, adding features, improving documentation, or suggesting enhancements.
- Code of Conduct
- Getting Started
- Development Setup
- How to Contribute
- Pull Request Process
- Coding Standards
- Testing
- Documentation
- Commit Messages
- Issue Guidelines
- Algorithm Implementation
This project follows a Code of Conduct to ensure a welcoming environment for all contributors. Please read and follow our Code of Conduct.
- Fork the repository on GitHub
- Clone your fork locally:
git clone https://github.com/YOUR_USERNAME/dither_it.git cd dither_it - Add the original repository as upstream:
git remote add upstream https://github.com/Penfore/dither_it.git
- Dart SDK >= 3.0.0
- Git
-
Install dependencies:
dart pub get
-
Run tests to ensure everything works:
dart test -
Verify the library works (examples coming soon):
# Examples will be available in future releases # dart run example/basic_example.dart
-
🐛 Bug Fixes
- Find and fix bugs in existing algorithms
- Improve error handling
- Fix edge cases
-
✨ New Features
- Implement new dithering algorithms
- Add utility functions
- Improve performance
-
📚 Documentation
- Improve API documentation
- Add or improve examples
- Write tutorials
-
🧪 Testing
- Add test cases
- Improve test coverage
- Add benchmark tests
-
🎨 Examples
- Create new example applications
- Improve existing examples
-
Create a feature branch:
git checkout -b feature/your-feature-name # or git checkout -b fix/your-bug-fix -
Make your changes following our coding standards
-
Add or update tests for your changes
-
Update documentation if needed
-
Run the test suite:
dart test dart analyze dart format --set-exit-if-changed .
-
Commit your changes with descriptive commit messages
-
Push to your fork:
git push origin feature/your-feature-name
-
Create a Pull Request on GitHub with:
- Clear description of changes
- Reference to related issues
- Screenshots or examples if applicable
- Code follows project style guidelines
- Tests pass locally
- New code has appropriate test coverage
- Documentation is updated
- Commit messages are descriptive
- No merge conflicts with main branch
- Follow the official Dart style guide
- Use
dart formatto automatically format code - Run
dart analyzeto check for issues
- Functions should be small and focused (ideally < 20 lines)
- Use descriptive variable and function names
- Add DartDoc comments for public APIs
- Handle edge cases appropriately
- Avoid code duplication
/// Applies the Floyd-Steinberg dithering algorithm to the provided image.
///
/// This algorithm distributes quantization error to neighboring pixels
/// using the following error diffusion pattern:
/// ```
/// X 7/16
/// 3/16 5/16 1/16
/// ```
///
/// [image]: The input image to be dithered.
///
/// Returns the dithered image with reduced color depth.
///
/// Throws [ArgumentError] if the image is null or empty.
static Image floydSteinberg({required Image image}) {
ArgumentError.checkNotNull(image, 'image');
if (image.width == 0 || image.height == 0) {
throw ArgumentError('Image must have non-zero dimensions');
}
// Implementation details...
}- 100% test coverage for new features
- Edge case testing (empty images, single pixel, etc.)
- Performance regression tests for algorithms
- Integration tests for complete workflows
# Run all tests
dart test
# Run tests with coverage
dart test --coverage=coverage
dart pub global run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --report-on=lib
# Run specific test file
dart test test/dither_it_test.dartgroup('FloydSteinberg', () {
test('should handle single pixel image', () {
final image = Image(width: 1, height: 1);
image.setPixelRgb(0, 0, 128, 128, 128);
final result = DitherIt.floydSteinberg(image: image);
expect(result.width, equals(1));
expect(result.height, equals(1));
// Additional assertions...
});
test('should throw on null image', () {
expect(
() => DitherIt.floydSteinberg(image: null),
throwsA(isA<ArgumentError>()),
);
});
});- Use DartDoc comments (
///) for all public APIs - Include parameter descriptions
- Provide usage examples
- Document exceptions that can be thrown
- Update feature lists when adding new algorithms
- Add examples for new functionality
- Update performance comparisons
/// Applies ordered dithering using a Bayer matrix of the specified size.
///
/// Ordered dithering uses a threshold matrix to determine which pixels
/// should be quantized to which values, creating a regular pattern.
///
/// Example usage:
/// ```dart
/// final image = decodeImage(imageBytes)!;
/// final dithered = DitherIt.ordered(image: image, matrixSize: 4);
/// ```
///
/// [image]: The input image to process
/// [matrixSize]: Size of the Bayer matrix (must be 2, 4, or 8)
///
/// Returns a new image with ordered dithering applied.
///
/// Throws [ArgumentError] if matrixSize is not supported.
static Image ordered({required Image image, required int matrixSize}) {
// Implementation...
}Use the Conventional Commits format:
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
feat: New featurefix: Bug fixdocs: Documentation changestest: Adding or modifying testsrefactor: Code refactoringperf: Performance improvementschore: Maintenance tasks
feat(algorithms): add Jarvis-Judice-Ninke dithering algorithm
Implements the JJN error diffusion algorithm with 12-pixel
error distribution pattern for higher quality results.
Closes #15
fix(floyd-steinberg): handle edge pixels correctly
Previously, the algorithm could access pixels outside image
boundaries when processing edge pixels. Added boundary checks.
docs(readme): add performance comparison table
Added detailed comparison of algorithm performance characteristics
to help users choose the right algorithm for their needs.When reporting bugs, please include:
- Clear description of the issue
- Steps to reproduce the problem
- Expected vs actual behavior
- Dart version and platform
- Sample code or images if applicable
For new features, please provide:
- Clear description of the desired functionality
- Use case and motivation
- Proposed API if applicable
- References to algorithms or papers
**Bug Report**
- Dart version:
- Platform:
- Library version:
**Description:**
A clear description of the bug.
**Steps to Reproduce:**
1. Step one
2. Step two
3. Step three
**Expected Behavior:**
What should happen.
**Actual Behavior:**
What actually happens.
**Code Sample:**
```dart
// Minimal code to reproduce the issue
## 🧮 Algorithm Implementation
### Adding New Dithering Algorithms
When implementing new algorithms, follow this checklist:
1. **Research the algorithm** thoroughly
- Understand the mathematical foundation
- Find reference implementations
- Study performance characteristics
2. **Create the implementation**
- Add to `DitherIt` class
- Follow existing naming patterns
- Include comprehensive documentation
3. **Add comprehensive tests**
- Unit tests for the algorithm
- Edge case testing
- Performance benchmarks
4. **Update documentation**
- Add to README algorithm list
- Update comparison tables
- Create usage examples
### Algorithm Implementation Template:
```dart
/// Applies the [AlgorithmName] dithering algorithm to the provided image.
///
/// [Brief description of how the algorithm works and its characteristics]
///
/// Reference: [Link to paper or documentation]
///
/// [image]: The input image to be dithered.
/// [parameter]: Description of any algorithm-specific parameters.
///
/// Returns the dithered image.
///
/// Throws [ArgumentError] if parameters are invalid.
static Image algorithmName({
required Image image,
int parameter = defaultValue,
}) {
// Validate inputs
ArgumentError.checkNotNull(image, 'image');
if (parameter < minValue || parameter > maxValue) {
throw ArgumentError('parameter must be between $minValue and $maxValue');
}
// Implementation
final Image result = Image.from(image);
// Algorithm logic here...
return result;
}
Contributors are recognized in our README and release notes. Significant contributions may be highlighted in blog posts or social media.
If you have questions about contributing, feel free to:
- Open a GitHub Discussion
- Create an issue with the "question" label
- Reach out to maintainers
Every contribution, no matter how small, helps make DitherIt better. Thank you for taking the time to contribute!
Happy coding! 🎨✨