numpyimage 3.0.2__tar.gz → 3.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: numpyimage
3
- Version: 3.0.2
3
+ Version: 3.1.0
4
4
  Summary: Load, save, & manipulate image files as numpy arrays
5
5
  Author-email: Jasper Phelps <jasper.s.phelps@gmail.com>
6
6
  License: MIT License
@@ -161,6 +161,7 @@ class VideoStreamer:
161
161
  self.container = av.open(str(self.filename))
162
162
  self.stream = self.container.streams.video[0]
163
163
  self.time_base = self.stream.time_base
164
+ self._frame_iterator = self.container.decode(self.stream)
164
165
  self._shape = None
165
166
  self._first_frame = None
166
167
  self._width = None
@@ -322,6 +323,22 @@ class VideoStreamer:
322
323
  def frame_number_to_time(self, frame_number: int) -> float:
323
324
  return float(self.frame_number_to_pts(frame_number) * self.time_base)
324
325
 
326
+ def pts_to_frame_number(self, pts: int) -> int:
327
+ if self._framerate == 'variable':
328
+ if pts not in self.frames_pts:
329
+ raise ValueError(f'PTS {pts} not in video index.')
330
+ return self.frames_pts.index(pts)
331
+ else:
332
+ if pts < self.pts0:
333
+ raise ValueError(f'PTS {pts} is before the start of the'
334
+ f' video (PTS {self.pts0}).')
335
+ if pts > self.pts_delta * (self.n_frames - 1) + self.pts0:
336
+ raise ValueError(f'PTS {pts} is after the end of the video (PTS '
337
+ f'{self.pts_delta * (self.n_frames - 1) + self.pts0}).')
338
+ if (pts - self.pts0) % self.pts_delta != 0:
339
+ raise ValueError(f'PTS {pts} is between frames for this video.')
340
+ return (pts - self.pts0) // self.pts_delta
341
+
325
342
  def __getitem__(self, key) -> np.ndarray:
326
343
  if isinstance(key, tuple):
327
344
  frame_idx = key[0]
@@ -350,9 +367,11 @@ class VideoStreamer:
350
367
  to the requested frame number.
351
368
  """
352
369
  target_pts = self.frame_number_to_pts(frame_number)
353
- for frame in self.container.decode(self.stream):
370
+ for frame in self._frame_iterator:
354
371
  if frame.pts is None:
355
- continue # Skip frames without PTS
372
+ if self.verbose:
373
+ print('WARNING: Skipping a frame with no PTS.')
374
+ continue
356
375
  if frame.pts == target_pts:
357
376
  frame = frame.to_ndarray(format='rgb24')
358
377
  self._current_frame_number = frame_number
@@ -360,8 +379,8 @@ class VideoStreamer:
360
379
  if frame.pts > target_pts:
361
380
  raise RuntimeError(f'Frame with PTS {target_pts} not found after'
362
381
  f' seeking – current frame PTS: {frame.pts}')
363
- raise RuntimeError(f'Frame with PTS {target_pts} not found after'
364
- f' seeking – current frame PTS: {frame.pts}')
382
+ raise RuntimeError('Ran out of frames before finding frame with requested'
383
+ f' PTS {target_pts} – current frame PTS: {frame.pts}')
365
384
 
366
385
  if isinstance(frame_number, slice): # Support slicing
367
386
  start, stop, step = frame_number.indices(self.n_frames)
@@ -385,10 +404,14 @@ class VideoStreamer:
385
404
 
386
405
  def _normalize_frame_number(self, frame_number: int) -> int:
387
406
  """
388
- Normalize frame number to be within the valid range.
407
+ Support negative indexing by converting negative frame numbers to
408
+ positive ones, e.g. -1 becomes n_frames - 1, -2 becomes n_frames - 2, etc.
389
409
  """
390
- if not isinstance(frame_number, int):
391
- raise TypeError(f'Frame number must be an integer, not {type(frame_number)}')
410
+ try:
411
+ frame_number = int(frame_number)
412
+ except ValueError:
413
+ raise TypeError(f'Frame number must be castable to int but got "{frame_number}"')
414
+
392
415
  if frame_number < -self.n_frames:
393
416
  raise IndexError(f'Negative frame {frame_number} not in'
394
417
  f' valid range [-{self.n_frames}, -1]')
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: numpyimage
3
- Version: 3.0.2
3
+ Version: 3.1.0
4
4
  Summary: Load, save, & manipulate image files as numpy arrays
5
5
  Author-email: Jasper Phelps <jasper.s.phelps@gmail.com>
6
6
  License: MIT License
@@ -4,7 +4,7 @@ build-backend = 'setuptools.build_meta'
4
4
 
5
5
  [project]
6
6
  name = 'numpyimage'
7
- version = '3.0.2'
7
+ version = '3.1.0'
8
8
  description = 'Load, save, & manipulate image files as numpy arrays'
9
9
  readme.file = 'README.md'
10
10
  readme.content-type = 'text/markdown'
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes