or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

convenience.mdimage-container.mdindex.mdreading.mdwriting.md

convenience.mddocs/

0

# Convenience Functions

1

2

High-level utility functions for quick PNG creation and manipulation without requiring detailed format knowledge or class instantiation. These functions provide the simplest interface for common PNG operations.

3

4

## Capabilities

5

6

### Array to PNG Conversion

7

8

The primary convenience function for creating PNG images from Python data structures.

9

10

```python { .api }

11

def from_array(a, mode=None, info={}):

12

"""

13

Create PNG Image from 2D array or nested sequences.

14

15

Parameters:

16

- a: 2D array-like structure containing pixel data

17

- mode: str, color mode specification:

18

- 'L': Greyscale (1 value per pixel)

19

- 'LA': Greyscale with alpha (2 values per pixel)

20

- 'RGB': Red, green, blue (3 values per pixel)

21

- 'RGBA': Red, green, blue, alpha (4 values per pixel)

22

- None: Auto-detect based on data structure

23

- info: dict, additional PNG metadata options

24

25

Returns:

26

Image: PNG Image object with save() and write() methods

27

"""

28

29

# Alternative name for from_array

30

fromarray = from_array

31

```

32

33

### Low-Level PNG Creation

34

35

Direct PNG file creation by writing chunk data for advanced users who need complete control over PNG structure.

36

37

```python { .api }

38

def write_chunks(out, chunks):

39

"""

40

Create PNG file by writing chunk data directly.

41

42

Parameters:

43

- out: file-like object opened in binary write mode

44

- chunks: iterable of (chunk_type, chunk_data) tuples

45

46

Note: This is a low-level function. PNG signature is written automatically,

47

but all required chunks (IHDR, IDAT, IEND) must be provided.

48

"""

49

```

50

51

### Module Constants and Utilities

52

53

Important module-level constants and utility information for PNG manipulation.

54

55

```python { .api }

56

import collections

57

58

# Module version

59

__version__: str = "0.20220715.0"

60

61

# PNG file signature (8-byte header that identifies PNG files)

62

signature: bytes = b'\x89PNG\r\n\x1a\n'

63

64

# Adam7 interlacing pattern coordinates (xstart, ystart, xstep, ystep)

65

adam7: tuple = ((0, 0, 8, 8), (4, 0, 8, 8), (0, 4, 4, 8),

66

(2, 0, 4, 4), (0, 2, 2, 4), (1, 0, 2, 2), (0, 1, 1, 2))

67

68

# Alternative name for from_array function (PIL compatibility)

69

fromarray = from_array

70

71

# Named tuple for resolution metadata (from pHYs chunk)

72

Resolution = collections.namedtuple('_Resolution', 'x y unit_is_meter')

73

```

74

75

## Usage Examples

76

77

### Simple Image Creation

78

79

```python

80

import png

81

82

# Create greyscale image from simple 2D list

83

grey_pixels = [

84

[0, 64, 128, 192, 255], # Row 1: gradient from black to white

85

[255, 192, 128, 64, 0], # Row 2: gradient from white to black

86

[128, 128, 128, 128, 128] # Row 3: uniform grey

87

]

88

89

# Create and save PNG (mode automatically detected as 'L')

90

image = png.from_array(grey_pixels, 'L')

91

image.save('simple_grey.png')

92

```

93

94

### RGB Image Creation

95

96

```python

97

import png

98

99

# Create RGB image with explicit color values

100

rgb_pixels = [

101

[255, 0, 0, 0, 255, 0, 0, 0, 255], # Red, Green, Blue pixels

102

[255, 255, 0, 255, 0, 255, 0, 255, 255], # Yellow, Magenta, Cyan pixels

103

[255, 255, 255, 0, 0, 0, 128, 128, 128] # White, Black, Grey pixels

104

]

105

106

# Create RGB PNG

107

image = png.from_array(rgb_pixels, 'RGB')

108

image.save('rgb_colors.png')

109

```

110

111

### RGBA with Transparency

112

113

```python

114

import png

115

116

# Create RGBA image with transparency

117

rgba_pixels = [

118

[255, 0, 0, 255, 255, 0, 0, 128, 255, 0, 0, 0], # Red: opaque, half, transparent

119

[0, 255, 0, 255, 0, 255, 0, 128, 0, 255, 0, 0], # Green: opaque, half, transparent

120

[0, 0, 255, 255, 0, 0, 255, 128, 0, 0, 255, 0] # Blue: opaque, half, transparent

121

]

122

123

# Create RGBA PNG

124

image = png.from_array(rgba_pixels, 'RGBA')

125

image.save('rgba_transparency.png')

126

```

127

128

### Auto-Detection of Color Mode

129

130

```python

131

import png

132

133

# Let from_array auto-detect the color mode

134

pixels_1_channel = [[100, 150, 200]] # Detected as 'L' (greyscale)

135

pixels_2_channel = [[100, 255, 150, 128]] # Detected as 'LA' (greyscale + alpha)

136

pixels_3_channel = [[255, 0, 0, 0, 255, 0]] # Detected as 'RGB'

137

pixels_4_channel = [[255, 0, 0, 255, 0, 255, 0, 128]] # Detected as 'RGBA'

138

139

# Auto-detection based on values per pixel

140

image1 = png.from_array(pixels_1_channel) # Mode: 'L'

141

image2 = png.from_array(pixels_2_channel) # Mode: 'LA'

142

image3 = png.from_array(pixels_3_channel) # Mode: 'RGB'

143

image4 = png.from_array(pixels_4_channel) # Mode: 'RGBA'

144

145

image1.save('auto_grey.png')

146

image2.save('auto_grey_alpha.png')

147

image3.save('auto_rgb.png')

148

image4.save('auto_rgba.png')

149

```

150

151

### NumPy Array Integration

152

153

```python

154

import png

155

import numpy as np

156

157

# Create NumPy array

158

width, height = 64, 64

159

x, y = np.meshgrid(np.linspace(0, 1, width), np.linspace(0, 1, height))

160

161

# Generate mathematical pattern

162

pattern = np.sin(x * 10) * np.cos(y * 10)

163

# Scale to 0-255 range

164

pattern = ((pattern + 1) * 127.5).astype(np.uint8)

165

166

# Convert to PNG (NumPy arrays work directly)

167

image = png.from_array(pattern, 'L')

168

image.save('numpy_pattern.png')

169

170

# For RGB, reshape or create 3D array

171

rgb_pattern = np.zeros((height, width * 3), dtype=np.uint8)

172

rgb_pattern[:, 0::3] = pattern # Red channel

173

rgb_pattern[:, 1::3] = pattern // 2 # Green channel

174

rgb_pattern[:, 2::3] = 255 - pattern # Blue channel

175

176

rgb_image = png.from_array(rgb_pattern, 'RGB')

177

rgb_image.save('numpy_rgb_pattern.png')

178

```

179

180

### Working with Different Bit Depths

181

182

```python

183

import png

184

185

# 16-bit greyscale data (values 0-65535)

186

high_depth_pixels = [

187

[0, 16383, 32767, 49151, 65535], # Full 16-bit range

188

[65535, 49151, 32767, 16383, 0] # Reverse gradient

189

]

190

191

# Specify 16-bit depth in info dict

192

info = {'bitdepth': 16}

193

image = png.from_array(high_depth_pixels, 'L', info)

194

image.save('16bit_grey.png')

195

196

# For 16-bit RGB, values are still 0-65535 per channel

197

rgb_16bit = [

198

[65535, 0, 0, 0, 65535, 0, 0, 0, 65535], # Bright RGB

199

[32767, 32767, 32767, 16383, 16383, 16383] # Two greys

200

]

201

202

info_rgb = {'bitdepth': 16}

203

rgb_image = png.from_array(rgb_16bit, 'RGB', info_rgb)

204

rgb_image.save('16bit_rgb.png')

205

```

206

207

### Palette Images via Convenience Function

208

209

```python

210

import png

211

212

# Create palette-based image data (indices into palette)

213

palette_indices = [

214

[0, 1, 2, 1, 0],

215

[1, 2, 3, 2, 1],

216

[2, 3, 0, 3, 2]

217

]

218

219

# Define palette and include in info

220

palette = [(255, 0, 0), (0, 255, 0), (0, 0, 255), (255, 255, 0)]

221

info = {'palette': palette}

222

223

# Create palette PNG

224

image = png.from_array(palette_indices, mode=None, info=info)

225

image.save('palette_convenience.png')

226

```

227

228

### Low-Level Chunk Writing

229

230

```python

231

import png

232

import struct

233

import zlib

234

235

def create_minimal_png(width, height, pixel_data):

236

"""Create PNG using low-level chunk writing"""

237

238

# IHDR chunk data

239

ihdr_data = struct.pack('>IIBBBBB', width, height, 8, 2, 0, 0, 0)

240

241

# IDAT chunk - compress pixel data

242

# Add filter bytes (0 = no filter) to each row

243

filtered_data = b''

244

for row in pixel_data:

245

filtered_data += b'\x00' # Filter type

246

filtered_data += bytes(row)

247

248

idat_data = zlib.compress(filtered_data)

249

250

# Create chunk list

251

chunks = [

252

(b'IHDR', ihdr_data),

253

(b'IDAT', idat_data),

254

(b'IEND', b'')

255

]

256

257

# Write PNG file

258

with open('minimal.png', 'wb') as f:

259

png.write_chunks(f, chunks)

260

261

# Create simple 2x2 RGB image

262

pixel_data = [

263

[255, 0, 0, 0, 255, 0], # Red, Green

264

[0, 0, 255, 255, 255, 255] # Blue, White

265

]

266

267

create_minimal_png(2, 2, pixel_data)

268

```

269

270

### Error Handling

271

272

```python

273

import png

274

275

try:

276

# Invalid mode

277

invalid_pixels = [[255, 0, 0]]

278

image = png.from_array(invalid_pixels, 'INVALID_MODE')

279

except png.ProtocolError as e:

280

print(f"Protocol error: {e}")

281

282

try:

283

# Inconsistent row lengths

284

inconsistent_pixels = [

285

[255, 0, 0], # 3 values

286

[0, 255, 0, 128] # 4 values - inconsistent!

287

]

288

image = png.from_array(inconsistent_pixels, 'RGB')

289

except png.ProtocolError as e:

290

print(f"Data format error: {e}")

291

292

try:

293

# Empty or invalid data

294

empty_pixels = []

295

image = png.from_array(empty_pixels)

296

except (png.ProtocolError, ValueError) as e:

297

print(f"Invalid data: {e}")

298

```