Last active
July 15, 2024 04:15
-
-
Save AmirArani/b19d13be3f2c34de9196ae9495cb2b93 to your computer and use it in GitHub Desktop.
Extract BMP file "ColorTable" w/ Dart🎯
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
import 'dart:typed_data'; | |
import 'package:file_picker/file_picker.dart'; | |
import 'package:flutter/material.dart'; | |
import 'package:image/image.dart' as img; | |
class ColorTableData { | |
final List<ColorTableListItem> colorTableList; | |
final int totalPixelCount; | |
ColorTableData({ | |
required this.colorTableList, | |
required this.totalPixelCount, | |
}); | |
} | |
class ColorTableListItem { | |
final Color color; | |
final int count; | |
ColorTableListItem({required this.color, required this.count}); | |
} | |
class ColorTableExtractTestScreen extends StatefulWidget { | |
const ColorTableExtractTestScreen({super.key}); | |
@override | |
State<ColorTableExtractTestScreen> createState() => _ColorTableExtractTestScreenState(); | |
} | |
class _ColorTableExtractTestScreenState extends State<ColorTableExtractTestScreen> { | |
ColorTableData colorTable = ColorTableData(totalPixelCount: 0, colorTableList: []); | |
@override | |
Widget build(BuildContext context) { | |
return Center( | |
child: Column( | |
mainAxisAlignment: MainAxisAlignment.center, | |
children: [ | |
ElevatedButton( | |
onPressed: () async { | |
/// pick file | |
PlatformFile imageFile = await pickImage(); | |
/// convert file to bmpImage | |
img.Image? bmpImage = convertFileToBmpImage(imageFile); | |
/// extract color table of bmpImage | |
List<Color> colorTableListItemColors = | |
extractColorTableColors(palette: bmpImage?.palette); | |
/// calculate pixel count of each color of color table | |
List<int> colorTableListItemPixelCount = calculateColorTableColorPixelCount( | |
bmpImage: bmpImage!, colorTableList: colorTableListItemColors); | |
/// bind each color count to each color value and make a list of them. | |
List<ColorTableListItem> colorTableList = colorTableListGenerator( | |
colorTableListItemColors, | |
colorTableListItemPixelCount, | |
); | |
/// create ColorTableData model. | |
colorTable = ColorTableData( | |
colorTableList: colorTableList, | |
totalPixelCount: calculateTotalPixelCount(bmpImage: bmpImage), | |
); | |
setState(() { | |
colorTable; | |
}); | |
}, | |
child: const Text('Pick and Extract Color Table'), | |
), | |
const SizedBox(height: 40), | |
const Text('Extracted ColorTable', | |
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)), | |
const SizedBox(height: 10), | |
Wrap( | |
spacing: 10, | |
children: colorTable.colorTableList.map((ColorTableListItem colorTableItem) { | |
return Column( | |
children: [ | |
Container( | |
width: 30, | |
height: 30, | |
color: colorTableItem.color, | |
), | |
Text('Count: ${colorTableItem.count}'), | |
Text('Percent${colorTableItem.count / colorTable.totalPixelCount}'), | |
], | |
); | |
}).toList(), | |
), | |
], | |
), | |
); | |
} | |
} | |
Future<PlatformFile> pickImage() async { | |
FilePickerResult? result = await FilePicker.platform.pickFiles( | |
type: FileType.image, | |
withData: true, | |
allowedExtensions: ['bmp'], | |
); | |
if (result != null) { | |
PlatformFile file = result.files.first; | |
return file; | |
} else { | |
// Handle the case where file.bytes is null | |
throw Exception('File is null!!!'); | |
} | |
} | |
img.Image? convertFileToBmpImage(PlatformFile file) { | |
if (file.bytes != null) { | |
Uint8List fileBytes = file.bytes!; | |
img.Image? bmpImage = img.decodeBmp(fileBytes); | |
return bmpImage; | |
} else { | |
throw Exception('File byte is null!!!'); | |
} | |
} | |
List<Color> extractColorTableColors({required img.Palette? palette}) { | |
List<Color> colorTable = []; | |
for (int i = 0; i < palette!.numColors; i++) { | |
num r = palette.getRed(i); | |
num g = palette.getGreen(i); | |
num b = palette.getBlue(i); | |
num a = palette.getAlpha(i); | |
Color color = Color.fromARGB(a as int, r as int, g as int, b as int); | |
colorTable.add(color); | |
} | |
return colorTable; | |
} | |
List<int> calculateColorTableColorPixelCount( | |
{required img.Image bmpImage, required List<Color> colorTableList}) { | |
final List<int> colorsCount = List<int>.filled(colorTableList.length, 0); | |
for (int y = 0; y < bmpImage.height; y++) { | |
for (int x = 0; x < bmpImage.width; x++) { | |
for (int z = 0; z < colorTableList.length; z++) { | |
var pixel = bmpImage.getPixel(x, y).toList(); | |
if (pixel[0] == colorTableList[z].red && | |
pixel[1] == colorTableList[z].green && | |
pixel[2] == colorTableList[z].blue) { | |
colorsCount[z]++; | |
break; | |
} | |
} | |
} | |
} | |
return colorsCount; | |
} | |
List<ColorTableListItem> colorTableListGenerator(List<Color> colors, List<int> counts) { | |
List<ColorTableListItem> colorTableList = []; | |
if (colors.length == counts.length) { | |
for (int i = 0; i < colors.length; i++) { | |
colorTableList.add( | |
ColorTableListItem( | |
color: colors[i], | |
count: counts[i], | |
), | |
); | |
} | |
return colorTableList; | |
} else { | |
throw Exception('Length of ColorTable and Counts are not Same!!!'); | |
} | |
} | |
int calculateTotalPixelCount({required img.Image bmpImage}) => bmpImage.width * bmpImage.height; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment