Skip to content

Commit

Permalink
feat: add generer-image-png.md
Browse files Browse the repository at this point in the history
  • Loading branch information
BoboTiG committed Feb 7, 2024
1 parent 7513744 commit 6ced331
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 0 deletions.
47 changes: 47 additions & 0 deletions sources/python/generer-image-png.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Générer des images PNG

Voici une fonction bien pratique pour créer une image au format PNG. La valeur ajoutée ici, c'est qu'on utilise seulement du Python pur, sans passer par de module tierce.

## Imports

```{literalinclude} snippets/generer-image-png.py
:caption: generer-image-png.py
:lines: 1-4
:language: python
```

## La fonction

```{literalinclude} snippets/generer-image-png.py
:caption: generer-image-png.py
:pyobject: generate_random_png
:language: python
```

## Validation

Pour vérifier la validité des fichiers générés :

```{literalinclude} snippets/generer-image-png.sh
:lines: 3-4
:language: shell
```

```{literalinclude} snippets/generer-image-png.sh
:lines: 6-7
:language: shell
```

---

## 📜 Historique

2024-02-07
: Déplacement de l'article depuis le [blog](https://www.tiger-222.fr/?d=2017/04/13/10/20/59-creer-des-images-png-valides-pour-vos-tests).

2017-05-17
: Le fichier généré contenait une erreur `IDAT:_uncompressed_data_too_small`.
: Ajout des commandes de [vérification](#validation).

2017-04-13
: Premier jet.
42 changes: 42 additions & 0 deletions sources/python/snippets/generer-image-png.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import random
import struct
import zlib
from pathlib import Path


def generate_random_png(filename: str = "", size: int = 0) -> bytes | None:
"""Generate a random PNG file.
:param filename: The output file name. If None, returns picture content.
:param size: The number of black pixels of the picture.
:return mixed: None if given filename else bytes
"""

size = max(1, size) if size else random.randint(1, 1024)

pack = struct.pack

def chunk(header: bytes, data: bytes) -> bytes:
return pack(">I", len(data)) + header + data + pack(">I", zlib.crc32(header + data) & 0xFFFFFFFF)

magic = pack(">8B", 137, 80, 78, 71, 13, 10, 26, 10)
png_filter = pack(">B", 0)
scanline = pack(f">{size * 3}B", *[0] * (size * 3))
content = [png_filter + scanline for _ in range(size)]
png = (
magic
+ chunk(b"IHDR", pack(">2I5B", size, size, 8, 2, 0, 0, 0))
+ chunk(b"IDAT", zlib.compress(b"".join(content)))
+ chunk(b"IEND", b"")
)

if filename:
Path(filename).write_bytes(png)
return None

return png


if __name__ == "__main__":
random_png = generate_random_png()
generate_random_png("test.png", size=42)
7 changes: 7 additions & 0 deletions sources/python/snippets/generer-image-png.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/bash

identify -quiet -ping -format '%m %w %h %z %[colorspace]' 'FILE.png'
# PNG 42 42 8 sRGB

pngfix 'FILE.png'
# IDAT OK default 15 15 28 5334 FILE.png

0 comments on commit 6ced331

Please sign in to comment.