344
344
* to append a constant 255 band to an image, perhaps to add an alpha channel. Of
345
345
* course you can also write:
346
346
*
347
- * ```ruby
347
+ * ```php
348
348
* $result = $image->bandjoin($image2);
349
349
* $result = $image->bandjoin([image2, image3]);
350
350
* $result = Image::bandjoin([image1, image2, image3]);
353
353
*
354
354
* and so on.
355
355
*
356
+ * # Array access
357
+ *
358
+ * Images can be treated as arrays of bands. You can write:
359
+ *
360
+ * ```php
361
+ * $result = $image[1];
362
+ * ```
363
+ *
364
+ * to get band 1 from an image (green, in an RGB image).
365
+ *
366
+ * You can assign to bands as well. You can write:
367
+ *
368
+ * ```php
369
+ * $image[1] = $other_image;
370
+ * ```
371
+ *
372
+ * And band 1 will be replaced by all the bands in `$other_image` using
373
+ * `bandjoin`. Use no offset to mean append, use -1 to mean prepend:
374
+ *
375
+ * ```php
376
+ * $image[] = $other_image; // append bands from other
377
+ * $image[-1] = $other_image; // prepend bands from other
378
+ * ```
379
+ *
380
+ * You can use number and array constants as well, for example:
381
+ *
382
+ * ```php
383
+ * $image[] = 255; // append a constant 255
384
+ * $image[1] = [1, 2, 3]; // swap band 1 for three constant bands
385
+ * ```
386
+ *
387
+ * Finally, you can delete bands with `unset`:
388
+ *
389
+ * ```php
390
+ * unset($image[1]); // remove band 1
391
+ * ```
392
+ *
356
393
* # Exceptions
357
394
*
358
395
* The wrapper spots errors from vips operations and throws
@@ -1221,7 +1258,7 @@ public function hasAlpha(): bool
1221
1258
}
1222
1259
1223
1260
/**
1224
- * Our ArrayAccess interface ... we allow [] to get band .
1261
+ * Does band exist in image .
1225
1262
*
1226
1263
* @param mixed $offset The index to fetch.
1227
1264
*
@@ -1233,7 +1270,7 @@ public function offsetExists($offset): bool
1233
1270
}
1234
1271
1235
1272
/**
1236
- * Our ArrayAccess interface ... we allow [] to get band .
1273
+ * Get band from image .
1237
1274
*
1238
1275
* @param mixed $offset The index to fetch.
1239
1276
*
@@ -1245,28 +1282,93 @@ public function offsetGet($offset): Image
1245
1282
}
1246
1283
1247
1284
/**
1248
- * Our ArrayAccess interface ... we allow [] to get band.
1285
+ * Set a band.
1249
1286
*
1250
- * @param mixed $offset The index to set.
1287
+ * Use `$image[1] = $other_image;' to remove band 1 from this image,
1288
+ * replacing it with all the bands in `$other_image`.
1289
+ *
1290
+ * Use `$image[] = $other_image;' to append all the bands in `$other_image`
1291
+ * to `$image`.
1292
+ *
1293
+ * Use `$image[-1] = $other_image;` to prepend all the bands in
1294
+ * `$other_image` to `$image`.
1295
+ *
1296
+ * You can use constants or arrays in place of `$other_image`. Use `$image[]
1297
+ * = 255;` to append a constant 255 band, for example, or `$image[1]
1298
+ * = [1, 2];` to replace band 1 with two constant bands.
1299
+ *
1300
+ * @param int $offset The index to set.
1251
1301
* @param Image $value The band to insert
1252
1302
*
1253
- * @return Image the expanded image.
1303
+ * @return void
1254
1304
*/
1255
- public function offsetSet ($ offset , $ value ): Image
1305
+ public function offsetSet ($ offset , $ value )
1256
1306
{
1257
- throw new \BadMethodCallException ('Image::offsetSet: not implemented ' );
1307
+ // no offset means append
1308
+ if (is_null ($ offset )) {
1309
+ $ offset = $ this ->bands ;
1310
+ }
1311
+
1312
+ if (!is_int ($ offset )) {
1313
+ throw new \BadMethodCallException ('Image::offsetSet: offset is not integer or null ' );
1314
+ }
1315
+
1316
+ // number of bands to the left and right of $value
1317
+ $ n_left = min ($ this ->bands , max (0 , $ offset ));
1318
+ $ n_right = min ($ this ->bands , max (0 , $ this ->bands - 1 - $ offset ));
1319
+ $ offset = $ this ->bands - $ n_right ;
1320
+
1321
+ // if we are setting a constant as the first element, we must expand it
1322
+ // to an image, since bandjoin must have an image as the first argument
1323
+ if ($ n_left == 0 && !($ value instanceof Image)) {
1324
+ $ value = self ::imageize ($ this , $ value );
1325
+ }
1326
+
1327
+ $ components = [];
1328
+ if ($ n_left > 0 ) {
1329
+ $ components [] = $ this ->extract_band (0 , ['n ' => $ n_left ]);
1330
+ }
1331
+ $ components [] = $ value ;
1332
+ if ($ n_right > 0 ) {
1333
+ $ components [] = $ this ->extract_band ($ offset , ['n ' => $ n_right ]);
1334
+ }
1335
+
1336
+ $ head = array_shift ($ components );
1337
+ $ this ->image = $ head ->bandjoin ($ components )->image ;
1258
1338
}
1259
1339
1260
1340
/**
1261
- * Our ArrayAccess interface ... we allow [] to get band .
1341
+ * Remove a band from an image .
1262
1342
*
1263
- * @param mixed $offset The index to remove.
1343
+ * @param int $offset The index to remove.
1264
1344
*
1265
- * @return Image the reduced image.
1345
+ * @return void
1266
1346
*/
1267
- public function offsetUnset ($ offset ): Image
1347
+ public function offsetUnset ($ offset )
1268
1348
{
1269
- throw new \BadMethodCallException ('Image::offsetUnset: not implemented ' );
1349
+ if (is_int ($ offset ) && $ offset >= 0 && $ offset < $ this ->bands ) {
1350
+ if ($ this ->bands == 1 ) {
1351
+ throw new \BadMethodCallException ('Image::offsetUnset: cannot delete final band ' );
1352
+ }
1353
+
1354
+ $ components = [];
1355
+ if ($ offset > 0 ) {
1356
+ $ components [] = $ this ->extract_band (0 , ['n ' => $ offset ]);
1357
+ }
1358
+ if ($ offset < $ this ->bands - 1 ) {
1359
+ $ components [] = $ this ->extract_band (
1360
+ $ offset + 1 ,
1361
+ ['n ' => $ this ->bands - 1 - $ offset ]
1362
+ );
1363
+ }
1364
+
1365
+ $ head = array_shift ($ components );
1366
+ if (empty ($ components )) {
1367
+ $ this ->image = $ head ->image ;
1368
+ } else {
1369
+ $ this ->image = $ head ->bandjoin ($ components )->image ;
1370
+ }
1371
+ }
1270
1372
}
1271
1373
1272
1374
/**
0 commit comments