-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a grayscale format and tweak. (#2)
- Loading branch information
1 parent
d9335c2
commit 543c000
Showing
12 changed files
with
292 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
part of '../format.dart'; | ||
|
||
/// 8-bit grayscale pixel format. | ||
/// | ||
/// Colors in this format are represented as follows: | ||
/// | ||
/// Color | Value | ||
/// --------------|------ | ||
/// [Gray8.black] | `0x00` | ||
/// [Gray8.white] | `0xFF` | ||
/// | ||
/// {@category Pixel Formats} | ||
const gray8 = Gray8._(); | ||
|
||
/// 8-bit grayscale pixel format. | ||
/// | ||
/// For a singleton instance of this class, and further details, see [gray8]. | ||
/// | ||
/// {@category Pixel Formats} | ||
final class Gray8 extends _GrayInt { | ||
const Gray8._(); | ||
|
||
@override | ||
String get name => 'GRAY8'; | ||
|
||
@override | ||
int get bytesPerPixel => Uint8List.bytesPerElement; | ||
|
||
@override | ||
int get maxGray => 0xFF; | ||
|
||
@override | ||
int get max => maxGray; | ||
|
||
@override | ||
int copyWith(int pixel, {int? gray}) { | ||
var output = pixel; | ||
if (gray != null) { | ||
output = gray & 0xFF; | ||
} | ||
return output; | ||
} | ||
|
||
@override | ||
int copyWithNormalized(int pixel, {double? gray}) { | ||
return copyWith( | ||
pixel, | ||
gray: gray != null ? (gray.clamp(0.0, 1.0) * 0xFF).floor() : null, | ||
); | ||
} | ||
|
||
@override | ||
int getGray(int pixel) => pixel & 0xFF; | ||
|
||
@override | ||
int fromAbgr8888(int pixel) { | ||
return _luminanceRgb888( | ||
abgr8888.getRed(pixel), | ||
abgr8888.getGreen(pixel), | ||
abgr8888.getBlue(pixel), | ||
); | ||
} | ||
|
||
@override | ||
int toAbgr8888(int pixel) { | ||
// Isolate the least significant 8 bits. | ||
final value = pixel & 0xFF; | ||
|
||
// Replicate the value across all channels (R, G, B). | ||
final asRgb = value * 0x010101; | ||
|
||
// Set the alpha channel to 0xFF. | ||
return asRgb | 0xFF000000; | ||
} | ||
|
||
@override | ||
Float32x4 toFloatRgba(int pixel) { | ||
final g = getGray(pixel) / 255.0; | ||
return Float32x4(g, g, g, 1.0); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
part of '../format.dart'; | ||
|
||
/// A mixin for pixel formats that represent _graysacle_ pixels. | ||
base mixin Grayscale<P, C> implements PixelFormat<P, C> { | ||
/// Creates a new pixel with the given channel values. | ||
/// | ||
/// The [gray] value is optional. | ||
/// | ||
/// If omitted, the channel value is set to the minimum value. | ||
/// | ||
/// ## Example | ||
/// | ||
/// ```dart | ||
/// // Creating a full gray pixel. | ||
/// final pixel = grayscale.create(gray: 0xFF); | ||
/// ``` | ||
P create({C? gray}) => copyWith(zero, gray: gray ?? minGray); | ||
|
||
@override | ||
P copyWith(P pixel, {C? gray}); | ||
|
||
/// Creates a new pixel with the given channel value normalized to the range | ||
/// `[0.0, 1.0]`. | ||
/// | ||
/// The [gray] value is optional. | ||
/// | ||
/// If omitted, the channel value is set to `0.0`. | ||
/// | ||
/// ## Example | ||
/// | ||
/// ```dart | ||
/// // Creating a full gray pixel. | ||
/// final pixel = grayscale.createNormalized(gray: 1.0); | ||
/// ``` | ||
P createNormalized({double gray = 0.0}) { | ||
return copyWithNormalized(zero, gray: gray); | ||
} | ||
|
||
@override | ||
P copyWithNormalized(P pixel, {double? gray}); | ||
|
||
/// The minimum value for the gray channel. | ||
C get minGray; | ||
|
||
/// The maximum value for the gray channel. | ||
C get maxGray; | ||
|
||
/// Black pixel. | ||
P get black; | ||
|
||
/// White pixel. | ||
P get white => max; | ||
|
||
/// Returns the gray channel value of the [pixel]. | ||
C getGray(P pixel); | ||
|
||
@override | ||
P fromFloatRgba(Float32x4 pixel) { | ||
final (g, _) = _luminanceFloatRgba(pixel); | ||
return createNormalized(gray: g); | ||
} | ||
} | ||
|
||
abstract final class _GrayInt extends PixelFormat<int, int> | ||
with Grayscale<int, int> { | ||
const _GrayInt(); | ||
|
||
@override | ||
double distance(int a, int b) => (a - b).abs().toDouble(); | ||
|
||
@override | ||
double compare(int a, int b) => 1.0 - (a - b).abs() / maxGray.toDouble(); | ||
|
||
@override | ||
@nonVirtual | ||
int get zero => 0x0; | ||
|
||
@override | ||
@nonVirtual | ||
int get minGray => 0x0; | ||
|
||
@override | ||
@nonVirtual | ||
int clamp(int pixel) => pixel & max; | ||
|
||
@override | ||
int get black => create(gray: minGray); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
import 'dart:typed_data'; | ||
|
||
import 'package:pxl/pxl.dart'; | ||
|
||
import '../src/prelude.dart'; | ||
|
||
void main() { | ||
test('smoke test of GRAY8 <> ABGR8888', () { | ||
check(gray8.name).equals('GRAY8'); | ||
check(gray8.bytesPerPixel).equals(1); | ||
check(gray8.maxGray).equals(255); | ||
check(gray8.max).equals(255); | ||
|
||
check(gray8.getGray(0x00)).equals(0); | ||
check(gray8.getGray(0x1d)).equals(29); | ||
check(gray8.getGray(0x96)).equals(150); | ||
|
||
check(gray8.fromAbgr8888(abgr8888.black)).equals(0); | ||
check(gray8.fromAbgr8888(abgr8888.blue)).equals(29); | ||
check(gray8.fromAbgr8888(abgr8888.green)).equals(150); | ||
check(gray8.fromAbgr8888(abgr8888.red)).equals(76); | ||
check(gray8.fromAbgr8888(abgr8888.white)).equals(255); | ||
|
||
check(gray8.fromFloatRgba(floatRgba.black)).equals(0); | ||
check(gray8.fromFloatRgba(floatRgba.blue)).equals(29); | ||
check(gray8.fromFloatRgba(floatRgba.green)).equals(150); | ||
check(gray8.fromFloatRgba(floatRgba.red)).equals(76); | ||
check(gray8.fromFloatRgba(floatRgba.white)).equals(255); | ||
|
||
check(gray8.toAbgr8888(0)).equalsHex(abgr8888.black); | ||
check(gray8.toAbgr8888(29)).equalsHex(0xff1d1d1d); | ||
check(gray8.toAbgr8888(150)).equalsHex(0xff969696); | ||
check(gray8.toAbgr8888(76)).equalsHex(0xff4c4c4c); | ||
check(gray8.toAbgr8888(255)).equalsHex(abgr8888.white); | ||
|
||
check(gray8.toFloatRgba(0)).equals(floatRgba.black); | ||
check(gray8.toFloatRgba(29)).equals( | ||
Float32x4(0.113725, 0.113725, 0.113725, 1.0), | ||
); | ||
check(gray8.toFloatRgba(150)).equals( | ||
Float32x4(0.588235, 0.588235, 0.588235, 1.0), | ||
); | ||
check(gray8.toFloatRgba(76)).equals( | ||
Float32x4(0.298039, 0.298039, 0.298039, 1.0), | ||
); | ||
check(gray8.toFloatRgba(255)).equals(floatRgba.white); | ||
}); | ||
|
||
test('create', () { | ||
check(gray8.create(gray: 0)).equals(gray8.black); | ||
check(gray8.create(gray: 29)).equals(29); | ||
check(gray8.create(gray: 150)).equals(150); | ||
check(gray8.create(gray: 76)).equals(76); | ||
check(gray8.create(gray: 255)).equals(gray8.white); | ||
}); | ||
|
||
test('distance', () { | ||
check(gray8.distance(0, 0)).equals(0); | ||
check(gray8.distance(0, 29)).equals(29); | ||
}); | ||
|
||
test('compare', () { | ||
check(gray8.compare(0, 0)).equals(1.0); | ||
check(gray8.compare(0, 29)).equals(0.8862745098039215); | ||
check(gray8.compare(29, 0)).equals(0.8862745098039215); | ||
check(gray8.compare(29, 29)).equals(1.0); | ||
}); | ||
|
||
test('minGray', () { | ||
check(gray8.minGray).equals(0); | ||
}); | ||
|
||
test('clamp', () { | ||
check(gray8.clamp(-1)).equals(255); | ||
check(gray8.clamp(0)).equals(0); | ||
check(gray8.clamp(29)).equals(29); | ||
check(gray8.clamp(150)).equals(150); | ||
check(gray8.clamp(76)).equals(76); | ||
check(gray8.clamp(255)).equals(255); | ||
check(gray8.clamp(256)).equals(0); | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters