Skip to content

Commit e9148a7

Browse files
committed
docs: expand on changes in the API
1 parent c4a3e53 commit e9148a7

File tree

1 file changed

+114
-29
lines changed

1 file changed

+114
-29
lines changed

blog/release.md

Lines changed: 114 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
slug: v1-release
33
title: Release notes v1
4-
date: 2025-07-19
4+
date: 2025-07-25
55
---
66

77
We're excited to announce the release of a new major version of ImageJS. This version brings TypeScript support and a more intuitive API while maintaining the powerful image processing capabilities you love.
@@ -71,9 +71,26 @@ const image2 = new Image(10, 10);
7171

7272
This change makes the Image constructor more explicit by requiring you to specify the dimensions upfront, preventing potential errors from working with uninitialized or undefined-sized images
7373

74-
#### Image position
74+
#### Coordinate System Changes
7575

76-
Images now include an `origin` property that tracks their position relative to their parent image. When you crop an image, the cropped section remembers where it came from in the original image.
76+
Coordinates are now represented using `Point` objects instead of arrays. This change affects methods that require coordinate input like cropping, drawing, and pixel manipulation.
77+
78+
```ts
79+
// Before
80+
const croppedImage = img.crop({
81+
origin: [10, 10],
82+
width: 10,
83+
height: 10,
84+
});
85+
// After
86+
const croppedImage = img.crop({
87+
origin: { column: 10, row: 10 },
88+
width: 10,
89+
height: 10,
90+
});
91+
```
92+
93+
Images also include an `origin` that tracks their position relative to their parent image. When you crop an image, the cropped section remembers where it came from in the original image.
7794

7895
```ts
7996
const croppedImage = img.crop({
@@ -85,6 +102,8 @@ const croppedImage = img.crop({
85102
console.log(croppedImage.origin); // { column: 10, row: 10 }
86103
```
87104

105+
It is a more explicit and self-documenting code.It also eliminates confusion about array order (column vs row).
106+
88107
### Masks
89108

90109
Binary images are now handled by a dedicated `Mask` class instead of Image with `kind: 'BINARY'`.
@@ -105,25 +124,6 @@ The new `Mask` class uses 1 byte per pixel (vs 8 pixels per byte), trading ~8x m
105124

106125
### Points
107126

108-
Coordinates are now represented using `Point` objects instead of arrays. This change affects methods that require coordinate input like cropping, drawing, and pixel manipulation.
109-
110-
```ts
111-
// Before
112-
const croppedImage = img.crop({
113-
origin: [10, 10],
114-
width: 10,
115-
height: 10,
116-
});
117-
// After
118-
const croppedImage = img.crop({
119-
origin: { column: 10, row: 10 },
120-
width: 10,
121-
height: 10,
122-
});
123-
```
124-
125-
It is a more explicit and self-documenting code and it also eliminates confusion about array order (column vs row).
126-
127127
### Sobel and Scharr filters
128128

129129
[Sobel](https://en.wikipedia.org/wiki/Sobel_operator), [Scharr](https://en.wikipedia.org/wiki/Sobel_operator#Alternative_operators) filters are now combined into a single `derivative()` method.
@@ -152,19 +152,29 @@ Several methods have been renamed for consistency:
152152

153153
`img.paintCircle()` ➡️ `img.drawCircle()`
154154

155-
**Other methods**:
155+
**Stack methods**
156156

157-
`img.copy()` ➡️ `img.clone()`
157+
`stack.getMinImage()` ➡️ `stack.minImage()`
158+
159+
`stack.getMinImage()` ➡️ `stack.maxImage()`
160+
161+
`stack.getAverageImage()` ➡️ `stack.meanImage()`
162+
163+
**Other methods**:
158164

159165
`img.clearBit()` ➡️ `img.setBit()`
160166

161167
`img.getLocalMaxima()` ➡️ `img.getExtrema()`
162168

163169
`img.getChannel()` ➡️ `img.extractChannel()`
164170

165-
`img.rotateLeft()` and `img.rotateRight()` ➡️ `img.rotate()`
171+
`img.rotateLeft()` & `img.rotateRight()` ➡️ `img.rotate()`
172+
173+
`img.flipX()` & `img.flipY()` ➡️ `img.flip()`
166174

167-
`img.flipX()` and `img.flipY()` ➡️ `img.flip()`
175+
`img.colorDepth()` ➡️ `img.convertBitDepth()`
176+
177+
`img.fromWatershed()` ➡️ `img.watershed()`
168178

169179
Consistent naming follows common conventions ("draw\*" for rendering, "clone" for copying objects).
170180

@@ -186,6 +196,9 @@ The following deprecated features have been removed:
186196
- `abs()` has been removed.
187197
- `paintMasks()` has been removed. Use `paintMask()`+ `for` loop.
188198
- `mergeRois()` has been removed.
199+
- `clearBit()` and `toggleBit()` have been removed, due to changes in `Mask`
200+
data representation (see ["Masks"](#masks)).
201+
- `colsInfo()` and `rowsInfo()` in `Roi` have been removed.
189202

190203
## 🆕 New Features
191204

@@ -250,18 +263,90 @@ const warped = img.transform(matrix);
250263

251264
### `merge()`
252265

253-
`merge()` allows combining several one-channel images into one image. It is the opposite of `split()`:
266+
`merge()`is the opposite of `split()`. It allows combining several one-channel images into one multi-channel image:
254267

255268
```ts
256269
// Creates 3 grayscale images;
257-
const img2 = new Image(2, 2, { colorModel: 'GREY', bitDepth: 8 }).fill(0);
258270
const img1 = new Image(2, 2, { colorModel: 'GREY', bitDepth: 8 }).fill(0);
271+
const img2 = new Image(2, 2, { colorModel: 'GREY', bitDepth: 8 }).fill(0);
259272
const img3 = new Image(2, 2, { colorModel: 'GREY', bitDepth: 8 }).fill(255);
260273
// Creates RGB image. In this case, it creates blue 2x2 image.
261274
const img4 = merge([img1, img2, img3]);
262275
```
263276

264-
**Use case**: Combination of multiple channels into one image after they were.
277+
**Use case**: Combination of multiple channels into one image after they were modified.
278+
279+
### `Stack` features
280+
281+
The Stack class has been significantly expanded with new methods for batch processing and statistical analysis of image collections.
282+
283+
#### Array-like Operations
284+
285+
A user can now filter images based on custom criteria using `filter()`:
286+
287+
```ts
288+
// Create sample images
289+
const img1 = new Image(2, 2, { colorModel: 'GREY', bitDepth: 8 }).fill(0);
290+
const img2 = new Image(2, 2, { colorModel: 'GREY', bitDepth: 8 }).fill(0);
291+
const img3 = new Image(2, 2, { colorModel: 'GREY', bitDepth: 8 }).fill(255);
292+
293+
const stack = new Stack([img1, img2, img3]);
294+
295+
// Filter images where top-left pixel is white (255)
296+
const brightImages = stack.filter((img) => img.getValue(0, 0, 0) === 255);
297+
// Result: [img3]
298+
```
299+
300+
One can also apply the same operation to every image in the stack with `map()`:
301+
302+
```ts
303+
// Set top-left corner to gray (125) on all images
304+
const modifiedStack = stack.map((img) => {
305+
img.setValue(0, 0, 0, 125);
306+
return img;
307+
});
308+
```
309+
310+
#### Statistical Operations
311+
312+
It is now possible to generate a median image from the entire stack - useful for noise reduction and background subtraction:
313+
314+
```ts
315+
const medianImage = stack.medianImage();
316+
```
317+
318+
or create a cumulative sum of all images in the stack:
319+
320+
```ts
321+
const summedImage = stack.sum();
322+
```
323+
324+
Access specific pixel values from any image in the stack using two convenient methods:
325+
326+
_By Coordinates_
327+
328+
```ts
329+
const stackIndex = 1; // Second image in stack.
330+
const row = 0;
331+
const column = 0;
332+
const channel = 0;
333+
334+
// Get pixel value at specific coordinates.
335+
const pixelValue = stack.getValue(stackIndex, row, column, channel);
336+
```
337+
338+
_By Linear Index_
339+
340+
```ts
341+
const stackIndex = 1;
342+
const pixelIndex = row * image.width + column; // Convert 2D to 1D index.
343+
const channel = 0;
344+
345+
// Get the same pixel value using linear indexing.
346+
const pixelValue = stack.getValueByIndex(stackIndex, pixelIndex, channel);
347+
```
348+
349+
**Use Cases**: Time-lapse analysis, scientific imaging.
265350

266351
## 🚀 Getting Started
267352

0 commit comments

Comments
 (0)