or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

callbacks.mdimage-processing.mdindex.mdio.mdsavedmodel.mdtensorboard.md

image-processing.mddocs/

0

# Image Processing

1

2

TensorFlow.js Node provides native image processing capabilities that allow you to decode various image formats directly into tensors and encode tensors back to image formats. These operations are optimized for performance using native implementations.

3

4

## Capabilities

5

6

### Image Decoding

7

8

#### Decode Any Image Format

9

10

Automatically detects and decodes BMP, GIF, JPEG, and PNG images.

11

12

```typescript { .api }

13

/**

14

* Decode an image from a buffer into a tensor

15

* @param contents - Image data as Uint8Array

16

* @param channels - Number of color channels (0=auto, 1=grayscale, 3=RGB, 4=RGBA)

17

* @param dtype - Output tensor data type (currently only 'int32' supported)

18

* @param expandAnimations - If true, return 4D tensor for animated images

19

* @returns 3D tensor [height, width, channels] or 4D [frames, height, width, channels] for animations

20

*/

21

function decodeImage(

22

contents: Uint8Array,

23

channels?: number,

24

dtype?: 'int32',

25

expandAnimations?: boolean

26

): Tensor3D | Tensor4D;

27

```

28

29

**Usage Example:**

30

31

```typescript

32

import * as tf from '@tensorflow/tfjs-node';

33

import * as fs from 'fs';

34

35

// Read image file

36

const imageBuffer = fs.readFileSync('path/to/image.jpg');

37

const imageArray = new Uint8Array(imageBuffer);

38

39

// Decode to tensor

40

const imageTensor = tf.node.decodeImage(imageArray, 3); // RGB channels

41

console.log('Image shape:', imageTensor.shape); // [height, width, 3]

42

43

// Process the tensor

44

const normalizedImage = imageTensor.div(255.0); // Normalize to [0,1]

45

```

46

47

#### Decode JPEG Images

48

49

Decode JPEG images with advanced options for quality and performance tuning.

50

51

```typescript { .api }

52

/**

53

* Decode JPEG image with advanced options

54

* @param contents - JPEG image data as Uint8Array

55

* @param channels - Number of color channels (0=auto, 1=grayscale, 3=RGB)

56

* @param ratio - Downscaling ratio for performance (1=full resolution)

57

* @param fancyUpscaling - Use slower but higher quality chroma upscaling

58

* @param tryRecoverTruncated - Attempt to recover truncated images

59

* @param acceptableFraction - Minimum fraction of lines required for truncated recovery

60

* @param dctMethod - DCT decompression method ("INTEGER_FAST" or "INTEGER_ACCURATE")

61

* @returns 3D tensor [height, width, channels]

62

*/

63

function decodeJpeg(

64

contents: Uint8Array,

65

channels?: number,

66

ratio?: number,

67

fancyUpscaling?: boolean,

68

tryRecoverTruncated?: boolean,

69

acceptableFraction?: number,

70

dctMethod?: string

71

): Tensor3D;

72

```

73

74

**Usage Example:**

75

76

```typescript

77

// High-quality JPEG decoding

78

const jpegTensor = tf.node.decodeJpeg(

79

imageArray,

80

3, // RGB channels

81

1, // Full resolution

82

true, // High-quality upscaling

83

false, // Don't recover truncated

84

1.0, // Require 100% of lines

85

"INTEGER_ACCURATE" // High-quality DCT

86

);

87

88

// Fast JPEG decoding for thumbnails

89

const thumbnailTensor = tf.node.decodeJpeg(

90

imageArray,

91

3, // RGB channels

92

4, // 1/4 resolution (4x downscale)

93

false, // Fast upscaling

94

false, // Don't recover truncated

95

1.0, // Require 100% of lines

96

"INTEGER_FAST" // Fast DCT

97

);

98

```

99

100

#### Decode PNG Images

101

102

Decode PNG images with support for various bit depths and transparency.

103

104

```typescript { .api }

105

/**

106

* Decode PNG image

107

* @param contents - PNG image data as Uint8Array

108

* @param channels - Number of color channels (0=auto, 1=grayscale, 3=RGB, 4=RGBA)

109

* @param dtype - Output tensor data type

110

* @returns 3D tensor [height, width, channels]

111

*/

112

function decodePng(

113

contents: Uint8Array,

114

channels?: number,

115

dtype?: 'int32' | 'uint8' | 'float32'

116

): Tensor3D;

117

```

118

119

#### Decode BMP Images

120

121

Decode Windows Bitmap (BMP) images.

122

123

```typescript { .api }

124

/**

125

* Decode BMP image

126

* @param contents - BMP image data as Uint8Array

127

* @param channels - Number of color channels (0=auto, 1=grayscale, 3=RGB)

128

* @returns 3D tensor [height, width, channels]

129

*/

130

function decodeBmp(

131

contents: Uint8Array,

132

channels?: number

133

): Tensor3D;

134

```

135

136

#### Decode GIF Images

137

138

Decode GIF images, including animated GIFs.

139

140

```typescript { .api }

141

/**

142

* Decode GIF image (supports animation)

143

* @param contents - GIF image data as Uint8Array

144

* @returns 4D tensor [frames, height, width, channels] for animated GIFs

145

*/

146

function decodeGif(contents: Uint8Array): Tensor4D;

147

```

148

149

**Usage Example with Animated GIF:**

150

151

```typescript

152

const gifBuffer = fs.readFileSync('animated.gif');

153

const gifArray = new Uint8Array(gifBuffer);

154

155

// Decode animated GIF

156

const gifTensor = tf.node.decodeGif(gifArray);

157

console.log('GIF shape:', gifTensor.shape); // [frames, height, width, channels]

158

159

// Process each frame

160

const frameCount = gifTensor.shape[0];

161

for (let i = 0; i < frameCount; i++) {

162

const frame = gifTensor.slice([i, 0, 0, 0], [1, -1, -1, -1]).squeeze([0]);

163

// Process individual frame...

164

}

165

```

166

167

### Image Encoding

168

169

#### Encode JPEG Images

170

171

Encode tensors back to JPEG format with quality and format options.

172

173

```typescript { .api }

174

/**

175

* Encode tensor as JPEG image

176

* @param image - Input tensor [height, width, channels]

177

* @param format - Output format (''=auto, 'grayscale', 'rgb')

178

* @param quality - JPEG quality 0-100 (default: 95)

179

* @param progressive - Use progressive JPEG encoding

180

* @param optimizeSize - Optimize file size over quality

181

* @param chromaDownsampling - Enable chroma subsampling for smaller files

182

* @param densityUnit - DPI unit ('in' or 'cm')

183

* @param xDensity - Horizontal DPI

184

* @param yDensity - Vertical DPI

185

* @param xmpMetadata - XMP metadata string

186

* @returns Promise resolving to JPEG data as Uint8Array

187

*/

188

function encodeJpeg(

189

image: Tensor3D,

190

format?: '' | 'grayscale' | 'rgb',

191

quality?: number,

192

progressive?: boolean,

193

optimizeSize?: boolean,

194

chromaDownsampling?: boolean,

195

densityUnit?: 'in' | 'cm',

196

xDensity?: number,

197

yDensity?: number,

198

xmpMetadata?: string

199

): Promise<Uint8Array>;

200

```

201

202

**Usage Example:**

203

204

```typescript

205

// Create or process an image tensor

206

const imageTensor = tf.randomUniform([224, 224, 3], 0, 255).cast('int32');

207

208

// High-quality JPEG encoding

209

const highQualityJpeg = await tf.node.encodeJpeg(

210

imageTensor,

211

'rgb', // RGB format

212

95, // High quality

213

false, // Not progressive

214

false, // Don't optimize size over quality

215

false, // No chroma downsampling

216

'in', // Inches

217

300, // 300 DPI horizontal

218

300 // 300 DPI vertical

219

);

220

221

// Save to file

222

fs.writeFileSync('output-high-quality.jpg', Buffer.from(highQualityJpeg));

223

224

// Optimized JPEG for web

225

const webJpeg = await tf.node.encodeJpeg(

226

imageTensor,

227

'rgb', // RGB format

228

85, // Good quality for web

229

true, // Progressive loading

230

true, // Optimize for size

231

true // Enable chroma downsampling

232

);

233

234

fs.writeFileSync('output-web.jpg', Buffer.from(webJpeg));

235

```

236

237

#### Encode PNG Images

238

239

Encode tensors as PNG images with compression options.

240

241

```typescript { .api }

242

/**

243

* Encode tensor as PNG image

244

* @param image - Input tensor [height, width, channels]

245

* @param compression - Compression level 0-9 (0=none, 9=max, default: 1)

246

* @returns Promise resolving to PNG data as Uint8Array

247

*/

248

function encodePng(

249

image: Tensor3D,

250

compression?: number

251

): Promise<Uint8Array>;

252

```

253

254

**Usage Example:**

255

256

```typescript

257

// Create or process an image tensor

258

const imageTensor = tf.randomUniform([224, 224, 4], 0, 255).cast('int32'); // RGBA

259

260

// Fast PNG encoding (low compression)

261

const fastPng = await tf.node.encodePng(imageTensor, 1);

262

fs.writeFileSync('output-fast.png', Buffer.from(fastPng));

263

264

// Maximum compression PNG

265

const compressedPng = await tf.node.encodePng(imageTensor, 9);

266

fs.writeFileSync('output-compressed.png', Buffer.from(compressedPng));

267

```

268

269

### Image Format Detection

270

271

#### Get Image Type

272

273

Determine the format of image data from file headers.

274

275

```typescript { .api }

276

/**

277

* Detect image format from file header bytes

278

* @param content - Image data as Uint8Array (first few bytes sufficient)

279

* @returns Image format string ('jpeg', 'png', 'gif', 'bmp', or 'unknown')

280

*/

281

function getImageType(content: Uint8Array): string;

282

```

283

284

**Usage Example:**

285

286

```typescript

287

const imageBuffer = fs.readFileSync('unknown-image.data');

288

const imageArray = new Uint8Array(imageBuffer);

289

290

const imageType = tf.node.getImageType(imageArray);

291

console.log('Detected format:', imageType);

292

293

// Use appropriate decoder based on format

294

let decodedTensor;

295

switch (imageType) {

296

case 'jpeg':

297

decodedTensor = tf.node.decodeJpeg(imageArray);

298

break;

299

case 'png':

300

decodedTensor = tf.node.decodePng(imageArray);

301

break;

302

case 'gif':

303

decodedTensor = tf.node.decodeGif(imageArray);

304

break;

305

case 'bmp':

306

decodedTensor = tf.node.decodeBmp(imageArray);

307

break;

308

default:

309

throw new Error('Unsupported image format: ' + imageType);

310

}

311

```

312

313

## Types

314

315

```typescript { .api }

316

enum ImageType {

317

JPEG = 'jpeg',

318

PNG = 'png',

319

GIF = 'gif',

320

BMP = 'BMP'

321

}

322

323

type ImageFormat = '' | 'grayscale' | 'rgb';

324

type DensityUnit = 'in' | 'cm';

325

```

326

327

## Common Patterns

328

329

### Image Preprocessing Pipeline

330

331

```typescript

332

import * as tf from '@tensorflow/tfjs-node';

333

import * as fs from 'fs';

334

335

async function preprocessImage(imagePath: string): Promise<Tensor4D> {

336

// Load image

337

const imageBuffer = fs.readFileSync(imagePath);

338

const imageArray = new Uint8Array(imageBuffer);

339

340

// Decode image

341

const imageTensor = tf.node.decodeImage(imageArray, 3); // RGB

342

343

// Resize to model input size

344

const resized = tf.image.resizeBilinear(imageTensor, [224, 224]);

345

346

// Normalize to [0,1]

347

const normalized = resized.div(255.0);

348

349

// Add batch dimension

350

const batched = normalized.expandDims(0);

351

352

// Clean up intermediate tensors

353

imageTensor.dispose();

354

resized.dispose();

355

normalized.dispose();

356

357

return batched;

358

}

359

```

360

361

### Image Augmentation

362

363

```typescript

364

async function augmentAndSave(inputPath: string, outputPath: string) {

365

const imageBuffer = fs.readFileSync(inputPath);

366

const imageArray = new Uint8Array(imageBuffer);

367

368

// Decode

369

const original = tf.node.decodeImage(imageArray, 3);

370

371

// Apply augmentations

372

const flipped = tf.image.flipLeftRight(original);

373

const rotated = tf.image.rot90(original);

374

const brightened = tf.image.adjustBrightness(original, 0.2);

375

376

// Encode and save variations

377

const flippedJpeg = await tf.node.encodeJpeg(flipped.cast('int32'));

378

const rotatedJpeg = await tf.node.encodeJpeg(rotated.cast('int32'));

379

const brightenedJpeg = await tf.node.encodeJpeg(brightened.cast('int32'));

380

381

fs.writeFileSync(`${outputPath}/flipped.jpg`, Buffer.from(flippedJpeg));

382

fs.writeFileSync(`${outputPath}/rotated.jpg`, Buffer.from(rotatedJpeg));

383

fs.writeFileSync(`${outputPath}/brightened.jpg`, Buffer.from(brightenedJpeg));

384

385

// Clean up

386

original.dispose();

387

flipped.dispose();

388

rotated.dispose();

389

brightened.dispose();

390

}

391

```