eth_blockies/lib.rs
1//! A lightweight library in pure Rust to get Ethereum-style blocky identicon data,
2//! which can be used for generating blockies icon images, printing to terminal, etc.
3//!
4//! Useful when getting raw RGB data of Ethereum-style blockies, as well as complete png image files.
5//!
6//!
7//! # Basic Usage
8//!
9//!
10//! 1. Define a blockies type (size) to use
11//!
12//! * Make an alias type of [`Blockies`]
13//! ```
14//! use eth_blockies::{Blockies, BlockiesGenerator};
15//!
16//! // Blockies < size (const), T >
17//! type Icon<T> = Blockies<15, T>;
18//! ```
19//!
20//! * *Cf)* For Ethereum address blockies, [`EthBlockies`] is predefined as follows
21//! ```
22//! // use statement for Ethereum address blockies
23//! use eth_blockies::{EthBlockies, SeedInput, BlockiesGenerator};
24//! // type 'EthBlockies<T>' is predefined as 'Blockies<8, T>'
25//! ```
26//! ---
27//!
28//!
29//! 2. Select an input seed type
30//!
31//! * Check for [`SeedInput`] to get full list of input seed types
32//! ```
33//! # use eth_blockies::{Blockies, BlockiesGenerator};
34//! #
35//! # type Icon<T> = Blockies<15, T>;
36//! #
37//! // generate blockies from various input type
38//! let from_string = Icon::data("eth-blockies".to_string());
39//! let from_byte_vec = Icon::data(vec![0x0c, 0x93, 0xa3, 0x2e]);
40//! ```
41//!
42//! * *Cf)* For Ethereum address seeds, apply [`to_ethaddr_seed()`](global_type_helper::SeedInput::to_ethaddr_seed) before passing as input seed
43//! ```
44//! # use eth_blockies::{EthBlockies, SeedInput, BlockiesGenerator};
45//! #
46//! // generate Ethereum address blockies from various input type
47//!
48//! let seed_from_str = "0xe686c14FF9C11038F2B1c9aD617F2346CFB817dC"
49//! .to_ethaddr_seed();
50//! let from_str = EthBlockies::data(seed_from_str);
51//!
52//! let seed_from_bytes = [
53//! 0xe6, 0x86, 0xc1, 0x4f, 0xf9, 0xc1, 0x10, 0x38, 0xf2, 0xb1,
54//! 0xc9, 0xad, 0x61, 0x7f, 0x23, 0x46, 0xcf, 0xb8, 0x17, 0xdc,
55//! ].to_ethaddr_seed();
56//! let from_bytes = EthBlockies::data(seed_from_bytes);
57//! ```
58//! ---
59//!
60//!
61//! 3. Select an output data type
62//!
63//! * Check for [`BlockiesGenerator`] to get full list of output data types
64//! ```
65//! # use eth_blockies::{Blockies, BlockiesGenerator};
66//! #
67//! # type Icon<T> = Blockies<15, T>;
68//! #
69//! # fn to_gray((r, g, b): (u8, u8, u8)) -> u8 {
70//! # (r as f64 * 0.299 + g as f64 * 0.587 + b as f64 * 0.114) as u8
71//! # }
72//! #
73//! // generate blockies in various forms
74//! let in_rgb_2d_arr = Icon::data("eth-blockies");
75//! let in_indexed_2d_arr = Icon::indexed_data("eth-blockies");
76//! let in_gray_2d_arr = Icon::data_mapped("eth-blockies", to_gray);
77//! let in_png_data_vec = Icon::png_data("eth-blockies", (128, 128));
78//! ```
79//!
80//!
81//! # Example
82//!
83//! * Generate an Ethereum address blockies (with [`to_ethaddr_seed()`](global_type_helper::SeedInput::to_ethaddr_seed))
84//!
85//! ```no_run
86//! use eth_blockies::{EthBlockies, SeedInput, BlockiesGenerator};
87//!
88//! let seed = "0xe686c14FF9C11038F2B1c9aD617F2346CFB817dC"
89//! .to_ethaddr_seed(); // required for Ethereum address blockies
90//!
91//! // 8x8 2D-array of (r, g, b)
92//! {
93//! let eth_blockies_from_addr = EthBlockies::data(&seed);
94//! }
95//!
96//! // uncompressed png data in byte vector
97//! {
98//! let eth_blockies_png_from_addr =
99//! EthBlockies::png_data(&seed, (128, 128));
100//! // use below for compressed png
101//! // EthBlockies::compressed_png_data(&seed, (128, 128));
102//!
103//! // write data as png file
104//! use std::io::Write;
105//! std::fs::File::create("eth-blockies.png").unwrap()
106//! .write_all(ð_blockies_png_from_addr);
107//! }
108//! ```
109//!
110//!
111//! * Generate an html `img` blockies element, on wasm target
112//! ```ignore
113//! // addr to blockies data uri scheme,
114//! // which can be used directly in img elem 'src' or css 'url()'
115//! fn eth_blockies_data_uri(addr: &str) -> String {
116//! use eth_blockies::{EthBlockies, SeedInput, BlockiesGenerator};
117//!
118//! let addr_input = addr.to_ethaddr_seed();
119//! let output_dim = (128, 128);
120//! let data_uri_output = true;
121//!
122//! EthBlockies::png_data_base64(
123//! addr_input, output_dim, data_uri_output)
124//! }
125//!
126//! use web_sys::*;
127//!
128//! let addr = "0xe686c14FF9C11038F2B1c9aD617F2346CFB817dC";
129//!
130//! window()
131//! .and_then(|w| w.document())
132//! .and_then(|doc| doc.body().zip(doc.create_element("img").ok()))
133//! .and_then(|(body, img)| {
134//! // create a new img html element with generated data_uri
135//! img.set_attribute("src", ð_blockies_data_uri(addr))
136//! // then attach to body
137//! .and_then(|_| body.append_child(&img))
138//! .ok()
139//! });
140//! ```
141//!
142//!
143//! # Cargo Features
144//!
145//! * `compressed_png` (Enabled by default)
146//! * This feature enables following functions:
147//! * [`compressed_png_data()`](BlockiesGenerator::compressed_png_data)
148//! * [`compressed_png_data_base64()`](BlockiesGenerator::compressed_png_data_base64)
149//! * This feature adds a following external dependency:
150//! * [`deflate`] crate
151//! * If png compression is not needed,
152//! disable this feature as follows when adding the crate:
153//! * E.g.
154//! * Shell: `cargo add eth-blockies@1.1 --no-default-features`
155//! * Cargo.toml: `eth-blockies = { version = "1.1", default-features = false }`
156
157#![no_std]
158#![cfg_attr(docsrs, feature(doc_cfg))]
159
160mod blockies;
161pub use blockies::{Blockies, BlockiesHelper};
162mod global_type_helper;
163pub use global_type_helper::*;
164mod data_encoder;
165use data_encoder::*;
166
167extern crate alloc;
168use alloc::string::String;
169use alloc::vec::Vec;
170
171/// ( Alias of [`Blockies`]`<8, T>` ) Predefined [`Blockies`] for identicon of Ethereum address
172pub type EthBlockies<T> = Blockies<8, T>;
173
174/// Trait for generating a new [`Blockies`]
175///
176/// Used for generating data of a new blocky identicon in various form, including:
177/// * Raw blockies data
178/// * Terminal printable string (ANSI sequence)
179/// * Image file data (png)
180pub trait BlockiesGenerator<const S: usize> {
181 /// Generate an Ethereum-style blockies data
182 ///
183 /// # Arguments
184 ///
185 /// * `seed` - Input seed
186 ///
187 /// # Return
188 ///
189 /// * Blockies RGB data, in 2D [`RgbPixel`] array
190 ///
191 /// # Example
192 ///
193 /// * Generate RGB blockies data
194 ///
195 /// * General identicon
196 /// ```
197 /// use eth_blockies::{Blockies, BlockiesGenerator};
198 /// type Identicon<T> = Blockies<15, T>; // user-defined blockies type
199 ///
200 /// // args
201 /// let seed = "general string seed";
202 ///
203 /// // generate blockies
204 /// let icon_data_rgb = Blockies::<15>::data(seed);
205 /// let icon_data_rgb_alias = Identicon::data(seed);
206 ///
207 /// // test
208 /// {
209 /// assert_eq!(icon_data_rgb, icon_data_rgb_alias);
210 /// }
211 /// ```
212 ///
213 /// * Ethereum blockies
214 /// ```
215 /// use eth_blockies::{EthBlockies, SeedInput, BlockiesGenerator};
216 ///
217 /// // args
218 /// let addr = "0xe686c14FF9C11038F2B1c9aD617F2346CFB817dC"
219 /// .to_ethaddr_seed();
220 ///
221 /// // generate blockies
222 /// let blockies_data_rgb = EthBlockies::data(addr);
223 ///
224 /// // test
225 /// {
226 /// const P: eth_blockies::RgbPalette =
227 /// [(38, 173, 52), (132, 222, 77), (4, 201, 40)];
228 ///
229 /// assert_eq!(blockies_data_rgb, [
230 /// [ P[1], P[1], P[1], P[1], P[1], P[1], P[1], P[1] ],
231 /// [ P[1], P[0], P[0], P[2], P[2], P[0], P[0], P[1] ],
232 /// [ P[2], P[1], P[1], P[0], P[0], P[1], P[1], P[2] ],
233 /// [ P[0], P[0], P[2], P[0], P[0], P[2], P[0], P[0] ],
234 /// [ P[1], P[0], P[1], P[2], P[2], P[1], P[0], P[1] ],
235 /// [ P[1], P[2], P[1], P[2], P[2], P[1], P[2], P[1] ],
236 /// [ P[0], P[2], P[1], P[2], P[2], P[1], P[2], P[0] ],
237 /// [ P[1], P[0], P[0], P[1], P[1], P[0], P[0], P[1] ],
238 /// ]);
239 /// }
240 /// ```
241 ///
242 fn data<I: SeedInput>(seed: I) -> Blockies<S, RgbPixel>;
243
244 /// Generate an Ethereum-style blockies data, mapping each RGB color with `map_fn`
245 ///
246 /// Same with [`BlockiesGenerator::data`],
247 /// except that each [`RgbPixel`] output is mapped
248 /// with the function `map_fn` \(element mapping function\)
249 ///
250 /// # Arguments
251 ///
252 /// * `seed` - Input seed
253 /// * `map_fn` - Mapping function for each [`RgbPixel`] element in the returned array
254 ///
255 /// # Return
256 ///
257 /// * Mapped blockies data, in 2D `T` array
258 /// (`T`: type of each element returned by `map_fn`)
259 ///
260 /// # Example
261 ///
262 /// * Generate grayscale blockies data
263 ///
264 /// * General identicon
265 /// ```
266 /// use eth_blockies::{Blockies, BlockiesGenerator};
267 /// type Identicon<T> = Blockies<19, T>; // user-defined blockies type
268 ///
269 /// // args
270 /// let seed = "general string seed";
271 /// fn to_gray((r, g, b): (u8, u8, u8)) -> u8 {
272 /// (r as f64 * 0.299 + g as f64 * 0.587 + b as f64 * 0.114) as u8
273 /// }
274 ///
275 /// // generate blockies
276 /// let icon_data_gray = Blockies::<19>::data_mapped(seed, to_gray);
277 /// let icon_data_gray_alias = Identicon::data_mapped(seed, to_gray);
278 ///
279 /// // test
280 /// {
281 /// assert_eq!(icon_data_gray, icon_data_gray_alias);
282 /// }
283 /// ```
284 ///
285 /// * Ethereum blockies
286 /// ```
287 /// use eth_blockies::{EthBlockies, SeedInput, BlockiesGenerator};
288 ///
289 /// // args
290 /// let seed = "0xe686c14FF9C11038F2B1c9aD617F2346CFB817dC"
291 /// .to_ethaddr_seed();
292 /// fn to_gray((r, g, b): (u8, u8, u8)) -> u8 {
293 /// (r as f64 * 0.299 + g as f64 * 0.587 + b as f64 * 0.114) as u8
294 /// }
295 ///
296 /// // generate blockies
297 /// let blockies_data_gray = EthBlockies::data_mapped(seed, to_gray);
298 ///
299 /// // test
300 /// {
301 /// assert_eq!(blockies_data_gray, [
302 /// [ 178, 178, 178, 178, 178, 178, 178, 178 ],
303 /// [ 178, 118, 118, 123, 123, 118, 118, 178 ],
304 /// [ 123, 178, 178, 118, 118, 178, 178, 123 ],
305 /// [ 118, 118, 123, 118, 118, 123, 118, 118 ],
306 /// [ 178, 118, 178, 123, 123, 178, 118, 178 ],
307 /// [ 178, 123, 178, 123, 123, 178, 123, 178 ],
308 /// [ 118, 123, 178, 123, 123, 178, 123, 118 ],
309 /// [ 178, 118, 118, 178, 178, 118, 118, 178 ],
310 /// ]);
311 /// }
312 /// ```
313 ///
314 fn data_mapped<I: SeedInput, T: Clone, F: Fn(RgbPixel) -> T>(
315 seed: I,
316 map_fn: F,
317 ) -> Blockies<S, T>;
318
319 /// Generate an Ethereum-style blockies data in indexed image format
320 ///
321 /// # Arguments
322 ///
323 /// * `seed` - Input seed
324 ///
325 /// # Return
326 ///
327 /// * A tuple of [(](tuple) `RgbPalette`, `Blockies<S, ColorClass>` [)](tuple)
328 /// * `RgbPalette`: Array of [`RgbPixel`]
329 /// * `Blockies<S, ColorClass>`: 2D array of palette indices
330 ///
331 /// # Example
332 ///
333 /// * Get RGB blockies data, composed of (RGB palette, palette indices for each element)
334 ///
335 /// * General identicon
336 /// ```
337 /// use eth_blockies::{Blockies, BlockiesGenerator};
338 /// type Identicon<T> = Blockies<6, T>; // user-defined blockies type
339 ///
340 /// // args
341 /// let seed = "general string seed";
342 ///
343 /// // generate blockies
344 /// let (rgb_palette, palette_idx_bitmap) =
345 /// Blockies::<6>::indexed_data(seed);
346 /// let (rgb_palette_alias, palette_idx_bitmap_alias) =
347 /// Identicon::indexed_data(seed);
348 ///
349 /// // test
350 /// {
351 /// assert_eq!(rgb_palette, rgb_palette_alias);
352 /// assert_eq!(palette_idx_bitmap, palette_idx_bitmap_alias);
353 /// }
354 /// ```
355 ///
356 /// * Ethereum blockies
357 /// ```
358 /// use eth_blockies::{EthBlockies, SeedInput, BlockiesGenerator};
359 ///
360 /// // args
361 /// let seed = "0xe686c14FF9C11038F2B1c9aD617F2346CFB817dC"
362 /// .to_ethaddr_seed();
363 ///
364 /// // generate blockies
365 /// let (palette, palette_idx_bitmap) =
366 /// EthBlockies::indexed_data(seed);
367 ///
368 /// // test
369 /// {
370 /// use eth_blockies::ColorClass;
371 ///
372 /// // get (r, g, b) from palette
373 /// assert_eq!(palette[ColorClass::BgColor], (38, 173, 52));
374 /// assert_eq!(palette[ColorClass::Color], (132, 222, 77));
375 /// assert_eq!(palette[ColorClass::SpotColor], (4, 201, 40));
376 ///
377 /// // get color class from pixels
378 /// assert_eq!(palette_idx_bitmap[0][0], ColorClass::Color);
379 /// assert_eq!(palette_idx_bitmap[2][0], ColorClass::SpotColor);
380 /// assert_eq!(palette_idx_bitmap[1][1], ColorClass::BgColor);
381 ///
382 /// // get (r, g, b) from pixels
383 /// assert_eq!(palette[palette_idx_bitmap[0][0]], (132, 222, 77));
384 /// assert_eq!(palette[palette_idx_bitmap[2][0]], (4, 201, 40));
385 /// assert_eq!(palette[palette_idx_bitmap[1][1]], (38, 173, 52));
386 /// }
387 /// ```
388 ///
389 fn indexed_data<I: SeedInput>(seed: I) -> (RgbPalette, Blockies<S, ColorClass>);
390
391 /// Generate an Ethereum-style blockies data in indexed image format, mapping each RGB palette color with `map_fn`
392 ///
393 /// Same with [`BlockiesGenerator::indexed_data`],
394 /// except that each [`RgbPixel`] output in [`Palette`] is mapped
395 /// with the function `map_fn` \(element mapping function\)
396 ///
397 /// # Arguments
398 ///
399 /// * `seed` - Input seed
400 /// * `map_fn` - Mapping function for each [`RgbPixel`] element in the returned array
401 ///
402 /// # Return
403 ///
404 /// * A tuple of [(](tuple) `Palette<T>`, `Blockies<S, ColorClass>` [)](tuple)
405 /// * `Palette<T>`: Array of `T` returned by `map_fn`
406 /// * `Blockies<S, ColorClass>`: 2D array of palette indices
407 ///
408 /// # Example
409 ///
410 /// * Get grayscale blockies data, composed of (grayscale palette, palette indices for each element)
411 ///
412 /// * General identicon
413 /// ```
414 /// use eth_blockies::{Blockies, BlockiesGenerator};
415 /// type Identicon<T> = Blockies<6, T>; // user-defined blockies type
416 ///
417 /// // args
418 /// let seed = "general string seed";
419 /// fn to_gray((r, g, b): (u8, u8, u8)) -> u8 {
420 /// (r as f64 * 0.299 + g as f64 * 0.587 + b as f64 * 0.114) as u8
421 /// }
422 ///
423 /// // generate blockies
424 /// let (gray_palette, palette_idx_bitmap) =
425 /// Blockies::<6>::indexed_data_mapped(seed, to_gray);
426 /// let (gray_palette_alias, palette_idx_bitmap_alias) =
427 /// Identicon::indexed_data_mapped(seed, to_gray);
428 ///
429 /// // test
430 /// {
431 /// assert_eq!(gray_palette, gray_palette_alias);
432 /// assert_eq!(palette_idx_bitmap, palette_idx_bitmap_alias);
433 /// }
434 /// ```
435 ///
436 /// * Ethereum blockies
437 /// ```
438 /// use eth_blockies::{EthBlockies, SeedInput, BlockiesGenerator};
439 ///
440 /// // args
441 /// let seed = "0xe686c14FF9C11038F2B1c9aD617F2346CFB817dC"
442 /// .to_ethaddr_seed();
443 /// fn to_gray((r, g, b): (u8, u8, u8)) -> u8 {
444 /// (r as f64 * 0.299 + g as f64 * 0.587 + b as f64 * 0.114) as u8
445 /// }
446 ///
447 /// // generate blockies
448 /// let (palette, palette_idx_bitmap) =
449 /// EthBlockies::indexed_data_mapped(seed, to_gray);
450 ///
451 /// // test
452 /// {
453 /// use eth_blockies::ColorClass;
454 ///
455 /// // get grayscale value from palette
456 /// assert_eq!(palette[ColorClass::BgColor], 118);
457 /// assert_eq!(palette[ColorClass::Color], 178);
458 /// assert_eq!(palette[ColorClass::SpotColor], 123);
459 ///
460 /// // get color class from pixels
461 /// assert_eq!(palette_idx_bitmap[0][0], ColorClass::Color);
462 /// assert_eq!(palette_idx_bitmap[2][0], ColorClass::SpotColor);
463 /// assert_eq!(palette_idx_bitmap[1][1], ColorClass::BgColor);
464 ///
465 /// // get grayscale value from pixels
466 /// assert_eq!(palette[palette_idx_bitmap[0][0]], 178);
467 /// assert_eq!(palette[palette_idx_bitmap[2][0]], 123);
468 /// assert_eq!(palette[palette_idx_bitmap[1][1]], 118);
469 /// }
470 /// ```
471 ///
472 fn indexed_data_mapped<I: SeedInput, T: Clone, F: Fn(RgbPixel) -> T>(
473 seed: I,
474 map_fn: F,
475 ) -> (Palette<T>, Blockies<S, ColorClass>);
476
477 /// Generate an Ethereum-style blockies data in ANSI sequence format (terminal-printable)
478 ///
479 /// # Arguments
480 ///
481 /// * `seed` - Input seed
482 /// * `output_dim` - (width, height) of output png binary data.
483 /// Multiples of `const S` ([`SIZE`](BlockiesHelper::SIZE)) recommended for both width and height.
484 /// * `is_utf8` - Determine whether to print using UTF-8 characters.
485 /// * [`true`]: Output data contain UTF-8 characters,
486 /// which makes blockies printed in compact size.
487 /// * [`false`]: Output data do not contain any UTF-8 character,
488 /// but its size is bigger as one unit block is represented as two spaces ('0x20').
489 ///
490 /// # Return
491 ///
492 /// * A vector of ANSI sequnce string. Each string in the vector represents each line.
493 ///
494 /// # Example
495 ///
496 /// * Get RGB blockies data in ANSI sequence for terminal output
497 ///
498 /// * General identicon
499 /// ```
500 /// use eth_blockies::{Blockies, BlockiesGenerator};
501 /// type Identicon<T> = Blockies<20, T>; // user-defined blockies type
502 ///
503 /// // args
504 /// let seed = "general string seed";
505 /// let output_dim = (40, 40); // multiples of size recommended
506 /// let is_utf8 = true; // if false, print in less-compact format
507 ///
508 /// // generate blockies
509 /// let icon_ansiseq_string_joined =
510 /// Blockies::<20>::ansiseq_data(seed, output_dim, is_utf8)
511 /// .join("\n");
512 /// let icon_ansiseq_string_alias_joined =
513 /// Identicon::ansiseq_data(seed, output_dim, is_utf8)
514 /// .join("\n");
515 ///
516 /// // test
517 /// {
518 /// assert_eq!(icon_ansiseq_string_joined,
519 /// icon_ansiseq_string_alias_joined);
520 ///
521 /// println!("{}", icon_ansiseq_string_joined);
522 /// }
523 /// ```
524 ///
525 /// * Ethereum blockies
526 /// ```
527 /// use eth_blockies::{EthBlockies, SeedInput, BlockiesGenerator};
528 ///
529 /// // args
530 /// let seed = "0xe686c14ff9c11038f2b1c9ad617f2346cfb817dc"
531 /// .to_ethaddr_seed();
532 /// let output_dim = (8, 8); // multiples of size recommended
533 /// let is_utf8 = true; // if false, print in less-compact format
534 ///
535 /// // generate blockies
536 /// let ansi_string_joined = EthBlockies::ansiseq_data(
537 /// seed, output_dim, is_utf8).join("\n");
538 ///
539 /// // print
540 /// {
541 /// println!("{}", ansi_string_joined);
542 ///
543 /// // print to terminal in different manner
544 /// // use std::io::Write;
545 /// // writeln!(std::io::stdout(), "{}", ansi_string_joined);
546 /// }
547 /// ```
548 fn ansiseq_data<I: SeedInput>(
549 seed: I,
550 output_dim: (usize, usize),
551 is_utf8: bool,
552 ) -> Vec<String>;
553
554 /// Generate an Ethereum-style blockies data in uncompressed indexed png format
555 ///
556 /// # Arguments
557 ///
558 /// * `seed` - Input seed
559 /// * `output_dim` - (width, height) of output png binary data.
560 /// Multiples of `const S` ([`SIZE`](BlockiesHelper::SIZE)) recommended for both width and height.
561 ///
562 /// # Return
563 ///
564 /// * A byte vector of png binary data
565 ///
566 /// # Example
567 ///
568 /// * Get uncompressed png data of RGB blockies
569 ///
570 /// * General identicon
571 /// ```
572 /// use eth_blockies::{Blockies, BlockiesGenerator};
573 /// type Identicon<T> = Blockies<11, T>; // user-defined blockies type
574 ///
575 /// // args
576 /// let seed = "general string seed";
577 /// let output_dim = (64, 64); // multiples of size recommended
578 ///
579 /// // generate blockies
580 /// let icon_png_data = Blockies::<11>::png_data(seed, output_dim);
581 /// let icon_png_data_alias = Identicon::png_data(seed, output_dim);
582 ///
583 /// // test
584 /// {
585 /// assert_eq!(icon_png_data, icon_png_data_alias);
586 ///
587 /// // uncomment below to write to file
588 /// // use std::io::Write;
589 /// // std::fs::File::create("icon.png").unwrap()
590 /// // .write_all(&icon_png_data);
591 /// }
592 /// ```
593 ///
594 /// * Ethereum blockies
595 /// ```
596 /// use eth_blockies::{EthBlockies, SeedInput, BlockiesGenerator};
597 ///
598 /// // args
599 /// let seed = "0xe686c14FF9C11038F2B1c9aD617F2346CFB817dC"
600 /// .to_ethaddr_seed();
601 /// let output_dim = (16, 16); // multiples of size recommended
602 ///
603 /// // generate blockies
604 /// let img_png_data = EthBlockies::png_data(seed, output_dim);
605 ///
606 /// // test
607 /// {
608 /// assert_eq!(img_png_data,
609 /// b"\x89\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\
610 /// \x48\x44\x52\x00\x00\x00\x10\x00\x00\x00\x10\x02\x03\
611 /// \x00\x00\x00\x62\x9d\x17\xf2\x00\x00\x00\x09\x50\x4c\
612 /// \x54\x45\x26\xad\x34\x84\xde\x4d\x04\xc9\x28\xed\xf2\
613 /// \x1a\xc2\x00\x00\x00\x5b\x49\x44\x41\x54\x78\x01\x01\
614 /// \x50\x00\xaf\xff\x00\x55\x55\x55\x55\x00\x55\x55\x55\
615 /// \x55\x00\x50\x0a\xa0\x05\x00\x50\x0a\xa0\x05\x00\xa5\
616 /// \x50\x05\x5a\x00\xa5\x50\x05\x5a\x00\x00\xa0\x0a\x00\
617 /// \x00\x00\xa0\x0a\x00\x00\x50\x5a\xa5\x05\x00\x50\x5a\
618 /// \xa5\x05\x00\x5a\x5a\xa5\xa5\x00\x5a\x5a\xa5\xa5\x00\
619 /// \x0a\x5a\xa5\xa0\x00\x0a\x5a\xa5\xa0\x00\x50\x05\x50\
620 /// \x05\x00\x50\x05\x50\x05\x10\x15\x13\xed\x46\x70\x22\
621 /// \x4a\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82");
622 ///
623 /// // uncomment below to write to file
624 /// // use std::io::Write;
625 /// // std::fs::File::create("test.png").unwrap()
626 /// // .write_all(&img_png_data);
627 /// }
628 /// ```
629 fn png_data<I: SeedInput>(seed: I, output_dim: (usize, usize)) -> Vec<u8>;
630
631 /// Generate an Ethereum-style blockies data in compressed indexed png format
632 ///
633 /// # Arguments
634 ///
635 /// * `seed` - Input seed
636 /// * `output_dim` - (width, height) of output png binary data.
637 /// Multiples of `const S` ([`SIZE`](BlockiesHelper::SIZE)) recommended for both width and height.
638 ///
639 /// # Return
640 ///
641 /// * A byte vector of png binary data
642 ///
643 /// # Example
644 ///
645 /// * Get compressed png data of RGB blockies
646 ///
647 /// * General identicon
648 /// ```
649 /// use eth_blockies::{Blockies, BlockiesGenerator};
650 /// type Identicon<T> = Blockies<9, T>; // user-defined blockies type
651 ///
652 /// // args
653 /// let seed = "general string seed";
654 /// let output_dim = (64, 64); // multiples of size recommended
655 ///
656 /// // generate blockies
657 /// let icon_compressed_png_data =
658 /// Blockies::<9>::compressed_png_data(seed, output_dim);
659 /// let icon_compressed_png_data_alias =
660 /// Identicon::compressed_png_data(seed, output_dim);
661 ///
662 /// // test
663 /// {
664 /// assert_eq!(icon_compressed_png_data,
665 /// icon_compressed_png_data_alias);
666 ///
667 /// // uncomment below to write to file
668 /// // use std::io::Write;
669 /// // std::fs::File::create("icon.png").unwrap()
670 /// // .write_all(&icon_compressed_png_data);
671 /// }
672 /// ```
673 ///
674 /// * Ethereum blockies
675 /// ```
676 /// use eth_blockies::{EthBlockies, SeedInput, BlockiesGenerator};
677 ///
678 /// // args
679 /// let seed = "0xe686c14FF9C11038F2B1c9aD617F2346CFB817dC"
680 /// .to_ethaddr_seed();
681 /// let output_dim = (16, 16); // multiples of size recommended
682 ///
683 /// // generate blockies
684 /// let img_png_data =
685 /// EthBlockies::compressed_png_data(seed, output_dim);
686 ///
687 /// // print
688 /// {
689 /// // uncomment below to write to file
690 /// // use std::io::Write;
691 /// // std::fs::File::create("test.png").unwrap()
692 /// // .write_all(&img_png_data);
693 /// }
694 /// ```
695 #[cfg(feature = "compressed_png")]
696 #[cfg_attr(docsrs, doc(cfg(feature = "compressed_png")))]
697 fn compressed_png_data<I: SeedInput>(seed: I, output_dim: (usize, usize)) -> Vec<u8>;
698
699 /// Generate an Ethereum-style blockies data in base64 format of uncompressed indexed png
700 ///
701 /// # Arguments
702 ///
703 /// * `seed` - Input seed
704 /// * `output_dim` - (width, height) of output png binary data.
705 /// Multiples of `const S` ([`SIZE`](BlockiesHelper::SIZE)) recommended for both width and height.
706 /// * `data_uri_output` - Determine if the result output is prefixed with data URI scheme
707 ///
708 /// # Return
709 ///
710 /// * A string of base64-encoded png data
711 ///
712 /// # Example
713 ///
714 /// * Get uncompressed png data of RGB blockies in base64 format
715 ///
716 /// * General identicon
717 /// ```
718 /// use eth_blockies::{Blockies, BlockiesGenerator};
719 /// type Identicon<T> = Blockies<7, T>; // user-defined blockies type
720 ///
721 /// // args
722 /// let seed = "general string seed";
723 /// let output_dim = (64, 64); // multiples of size recommended
724 /// let data_uri = false; // true: prepend "data:image/png;base64,"
725 ///
726 /// // generate blockies
727 /// let icon_png_data_base64_string =
728 /// Blockies::<7>::png_data_base64(seed, output_dim, data_uri);
729 /// let icon_png_data_base64_alias_string =
730 /// Identicon::png_data_base64(seed, output_dim, data_uri);
731 ///
732 /// // test
733 /// {
734 /// assert_eq!(icon_png_data_base64_string,
735 /// icon_png_data_base64_alias_string);
736 /// }
737 /// ```
738 ///
739 /// * Ethereum blockies
740 /// ```
741 /// use eth_blockies::{EthBlockies, SeedInput, BlockiesGenerator};
742 ///
743 /// // args
744 /// let seed = "0xe686c14FF9C11038F2B1c9aD617F2346CFB817dC"
745 /// .to_ethaddr_seed();
746 /// let output_dim = (16, 16); // multiples of size recommended
747 ///
748 /// // generate blockies
749 /// {
750 /// // base64 data only
751 /// let data_uri = false;
752 /// let img_png_data_base64_string =
753 /// EthBlockies::png_data_base64(&seed, output_dim, data_uri);
754 ///
755 /// // test
756 /// assert_eq!(img_png_data_base64_string,
757 /// "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAgMAAABinRfyAAAACVBMVEU\
758 /// mrTSE3k0EySjt8hrCAAAAW0lEQVR4AQFQAK//AFVVVVUAVVVVVQBQCq\
759 /// AFAFAKoAUApVAFWgClUAVaAACgCgAAAKAKAABQWqUFAFBapQUAWlqlp\
760 /// QBaWqWlAApapaAAClqloABQBVAFAFAFUAUQFRPtRnAiSgAAAABJRU5E\
761 /// rkJggg==");
762 /// }
763 /// {
764 /// // base64 data with data uri scheme prefix
765 /// let data_uri = true;
766 /// let img_png_data_base64_uri_scheme_string =
767 /// EthBlockies::png_data_base64(&seed, output_dim, data_uri);
768 ///
769 /// // test
770 /// assert_eq!(img_png_data_base64_uri_scheme_string,
771 /// "data:image/png;base64,\
772 /// iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAgMAAABinRfyAAAACVBMVEU\
773 /// mrTSE3k0EySjt8hrCAAAAW0lEQVR4AQFQAK//AFVVVVUAVVVVVQBQCq\
774 /// AFAFAKoAUApVAFWgClUAVaAACgCgAAAKAKAABQWqUFAFBapQUAWlqlp\
775 /// QBaWqWlAApapaAAClqloABQBVAFAFAFUAUQFRPtRnAiSgAAAABJRU5E\
776 /// rkJggg==");
777 /// }
778 /// ```
779 fn png_data_base64<I: SeedInput>(
780 seed: I,
781 output_dim: (usize, usize),
782 data_uri_output: bool,
783 ) -> String;
784
785 /// Generate an Ethereum-style blockies data in base64 format of compressed indexed png
786 ///
787 /// # Arguments
788 ///
789 /// * `seed` - Input seed
790 /// * `output_dim` - (width, height) of output png binary data.
791 /// Multiples of `const S` ([`SIZE`](BlockiesHelper::SIZE)) recommended for both width and height.
792 /// * `data_uri_output` - Determine if the result output is prefixed with data URI scheme
793 ///
794 /// # Return
795 ///
796 /// * A string of base64-encoded png data
797 ///
798 /// # Example
799 ///
800 /// * Get compressed png data of RGB blockies in base64 format
801 ///
802 /// * General identicon
803 /// ```
804 /// use eth_blockies::{Blockies, BlockiesGenerator};
805 /// type Identicon<T> = Blockies<12, T>; // user-defined blockies type
806 ///
807 /// // args
808 /// let seed = "general string seed";
809 /// let output_dim = (64, 64); // multiples of size recommended
810 /// let data_uri = false; // true: prepend "data:image/png;base64,"
811 ///
812 /// // generate blockies
813 /// let icon_png_data_base64_string =
814 /// Blockies::<12>::compressed_png_data_base64(
815 /// seed, output_dim, data_uri);
816 /// let icon_png_data_base64_alias_string =
817 /// Identicon::compressed_png_data_base64(
818 /// seed, output_dim, data_uri);
819 ///
820 /// // test
821 /// {
822 /// assert_eq!(icon_png_data_base64_string,
823 /// icon_png_data_base64_alias_string);
824 /// }
825 /// ```
826 ///
827 /// * Ethereum blockies
828 /// ```
829 /// use eth_blockies::{EthBlockies, SeedInput, BlockiesGenerator};
830 ///
831 /// // args
832 /// let seed = "0xe686c14FF9C11038F2B1c9aD617F2346CFB817dC"
833 /// .to_ethaddr_seed();
834 /// let output_dim = (16, 16); // multiples of size recommended
835 ///
836 /// // generate blockies
837 /// {
838 /// // base64 data only
839 /// let data_uri_output = false;
840 /// let img_png_data_base64_string =
841 /// EthBlockies::compressed_png_data_base64(
842 /// &seed, output_dim, data_uri_output);
843 /// }
844 /// {
845 /// // base64 data with data uri scheme prefix
846 /// let data_uri_output = true;
847 /// let img_png_data_base64_uri_scheme_string =
848 /// EthBlockies::compressed_png_data_base64(
849 /// &seed, output_dim, data_uri_output);
850 /// }
851 /// ```
852 #[cfg(feature = "compressed_png")]
853 #[cfg_attr(docsrs, doc(cfg(feature = "compressed_png")))]
854 fn compressed_png_data_base64<I: SeedInput>(
855 seed: I,
856 output_dim: (usize, usize),
857 data_uri_output: bool,
858 ) -> String;
859}
860
861impl<const S: usize> BlockiesGenerator<S> for Blockies<S> {
862 fn data<I: SeedInput>(seed: I) -> Blockies<S, RgbPixel> {
863 Blockies::data_mapped(seed, |rgb_pixel| rgb_pixel)
864 }
865
866 fn data_mapped<I: SeedInput, T: Clone, F: Fn(RgbPixel) -> T>(
867 seed: I,
868 map_fn: F,
869 ) -> Blockies<S, T> {
870 let (palette, class_bitmap) = Blockies::indexed_data_mapped(seed, map_fn);
871
872 class_bitmap.map_2d(|class, _| palette[class].clone())
873 }
874
875 fn indexed_data<I: SeedInput>(seed: I) -> (RgbPalette, Blockies<S, ColorClass>) {
876 blockies::new_blockies(seed.as_seed_bytes())
877 }
878
879 fn indexed_data_mapped<I: SeedInput, T: Clone, F: Fn(RgbPixel) -> T>(
880 seed: I,
881 map_fn: F,
882 ) -> (Palette<T>, Blockies<S, ColorClass>) {
883 let (rgb_palette, class_bitmap) = Blockies::indexed_data(seed.as_seed_bytes());
884
885 (rgb_palette.map(map_fn), class_bitmap)
886 }
887
888 fn ansiseq_data<I: SeedInput>(
889 seed: I,
890 output_dim: (usize, usize),
891 is_utf8: bool,
892 ) -> Vec<String> {
893 let (palette, bitmap) = Blockies::<S>::indexed_data(seed);
894 match is_utf8 {
895 true => ansi_seq::indexed_data_to_ansiseq_utf8(
896 palette,
897 bitmap.scale(output_dim),
898 output_dim,
899 ),
900 false => ansi_seq::indexed_data_to_ansiseq_ascii(
901 palette,
902 bitmap.scale(output_dim),
903 output_dim,
904 ),
905 }
906 }
907
908 fn png_data<I: SeedInput>(seed: I, output_dim: (usize, usize)) -> Vec<u8> {
909 let (palette, bitmap) = Blockies::<S>::indexed_data(seed);
910 indexed_png::indexed_data_to_png(palette, bitmap.scale(output_dim), output_dim, false)
911 }
912
913 #[cfg(feature = "compressed_png")]
914 fn compressed_png_data<I: SeedInput>(seed: I, output_dim: (usize, usize)) -> Vec<u8> {
915 let (palette, bitmap) = Blockies::<S>::indexed_data(seed);
916 indexed_png::indexed_data_to_png(palette, bitmap.scale(output_dim), output_dim, true)
917 }
918
919 fn png_data_base64<I: SeedInput>(
920 seed: I,
921 output_dim: (usize, usize),
922 data_uri_output: bool,
923 ) -> String {
924 indexed_png::base64_wrapper(&Blockies::<S>::png_data(seed, output_dim), data_uri_output)
925 }
926
927 #[cfg(feature = "compressed_png")]
928 fn compressed_png_data_base64<I: SeedInput>(
929 seed: I,
930 output_dim: (usize, usize),
931 data_uri_output: bool,
932 ) -> String {
933 indexed_png::base64_wrapper(
934 &Blockies::<S>::compressed_png_data(seed, output_dim),
935 data_uri_output,
936 )
937 }
938}
939
940// deprecated functions from v1.0.0
941mod compat;
942pub use compat::*;