- android/ 167个模块 (app/content/os/view/widget/graphics/media/hardware/net/telephony/provider等) - java/ 35个模块 (lang/io/util/net/nio/security/crypto/sql/beans/rmi/awt等) - javax/ 4个模块 (net/crypto/security/sql) - org/ 5个模块 (json/w3c_dom/xml_sax/xml_pull/apache_http) - dalvik/ 1个模块 (system) - ~3053个类/接口,方法签名完全对齐Android SDK - 桌面跨平台运行 (Windows/macOS/Linux) - 修复所有导入错误和Python关键字冲突
649 lines
21 KiB
Python
649 lines
21 KiB
Python
"""
|
||
Android media.image 组件 — Image, ImageReader, ImageWriter 等
|
||
方法签名完全对齐 Android SDK
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
import os
|
||
import io
|
||
import math
|
||
import time
|
||
import struct
|
||
import threading
|
||
from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Union
|
||
|
||
from .._core import Stub, AndroidOnlyError
|
||
from ..java.lang import RuntimeException
|
||
|
||
|
||
# ═══════════════════════════════════════════════════════════════
|
||
# Image 格式常量
|
||
# ═══════════════════════════════════════════════════════════════
|
||
|
||
FORMAT_NV21 = 17
|
||
FORMAT_NV16 = 16
|
||
FORMAT_YUY2 = 20
|
||
FORMAT_JPEG = 256
|
||
FORMAT_RAW_PRIVATE = 36
|
||
FORMAT_RAW_SENSOR = 32
|
||
FORMAT_RAW10 = 37
|
||
FORMAT_RAW12 = 38
|
||
FORMAT_RAW_DEPTH = 4098
|
||
FORMAT_RAW_DEPTH10 = 4099
|
||
FORMAT_YUV_420_888 = 35
|
||
FORMAT_YUV_422_888 = 39
|
||
FORMAT_YUV_444_888 = 40
|
||
FORMAT_FLEX_RGB_888 = 41
|
||
FORMAT_FLEX_RGBA_8888 = 42
|
||
FORMAT_PRIVATE = 34
|
||
FORMAT_UNKNOWN = 0
|
||
FORMAT_RGB_565 = 4
|
||
FORMAT_RGBA_8888 = 1
|
||
FORMAT_RGBX_8888 = 2
|
||
FORMAT_BGRA_8888 = 5
|
||
FORMAT_Y8 = 538982489
|
||
FORMAT_Y16 = 540422489
|
||
FORMAT_DEPTH16 = 1144402265
|
||
FORMAT_DEPTH_POINT_CLOUD = 257
|
||
FORMAT_HEIC = 1212500294
|
||
|
||
TRANSFORM_NONE = 0
|
||
TRANSFORM_FLIP_H = 1
|
||
TRANSFORM_FLIP_V = 2
|
||
TRANSFORM_ROTATE_90 = 4
|
||
TRANSFORM_ROTATE_180 = 3
|
||
TRANSFORM_ROTATE_270 = 7
|
||
|
||
SCALER_ROTATE_90 = 1
|
||
SCALER_ROTATE_180 = 2
|
||
SCALER_ROTATE_270 = 3
|
||
|
||
|
||
class Image(Stub):
|
||
"""Image — 图像数据容器"""
|
||
|
||
class Plane(Stub):
|
||
"""Image.Plane — 图像平面(YUV 各个平面)"""
|
||
|
||
def __init__(self, buffer: Optional[bytes] = None,
|
||
row_stride: int = 0, pixel_stride: int = 0):
|
||
super().__init__()
|
||
self._buffer = buffer or b""
|
||
self._row_stride = row_stride
|
||
self._pixel_stride = pixel_stride
|
||
|
||
def getBuffer(self) -> Optional[bytes]:
|
||
return self._buffer
|
||
|
||
def getRowStride(self) -> int:
|
||
return self._row_stride
|
||
|
||
def getPixelStride(self) -> int:
|
||
return self._pixel_stride
|
||
|
||
def setBuffer(self, buf: bytes) -> None:
|
||
self._buffer = buf
|
||
|
||
def setRowStride(self, stride: int) -> None:
|
||
self._row_stride = stride
|
||
|
||
def setPixelStride(self, stride: int) -> None:
|
||
self._pixel_stride = stride
|
||
|
||
def toString(self) -> str:
|
||
return (f"Plane(rowStride={self._row_stride}, "
|
||
f"pixelStride={self._pixel_stride}, "
|
||
f"bufferSize={len(self._buffer) if self._buffer else 0})")
|
||
|
||
# Image 格式常量
|
||
FORMAT_NV21 = FORMAT_NV21
|
||
FORMAT_NV16 = FORMAT_NV16
|
||
FORMAT_YUY2 = FORMAT_YUY2
|
||
FORMAT_JPEG = FORMAT_JPEG
|
||
FORMAT_RAW_PRIVATE = FORMAT_RAW_PRIVATE
|
||
FORMAT_RAW_SENSOR = FORMAT_RAW_SENSOR
|
||
FORMAT_RAW10 = FORMAT_RAW10
|
||
FORMAT_RAW12 = FORMAT_RAW12
|
||
FORMAT_RAW_DEPTH = FORMAT_RAW_DEPTH
|
||
FORMAT_RAW_DEPTH10 = FORMAT_RAW_DEPTH10
|
||
FORMAT_YUV_420_888 = FORMAT_YUV_420_888
|
||
FORMAT_YUV_422_888 = FORMAT_YUV_422_888
|
||
FORMAT_YUV_444_888 = FORMAT_YUV_444_888
|
||
FORMAT_FLEX_RGB_888 = FORMAT_FLEX_RGB_888
|
||
FORMAT_FLEX_RGBA_8888 = FORMAT_FLEX_RGBA_8888
|
||
FORMAT_PRIVATE = FORMAT_PRIVATE
|
||
FORMAT_UNKNOWN = FORMAT_UNKNOWN
|
||
FORMAT_RGB_565 = FORMAT_RGB_565
|
||
FORMAT_RGBA_8888 = FORMAT_RGBA_8888
|
||
FORMAT_RGBX_8888 = FORMAT_RGBX_8888
|
||
FORMAT_BGRA_8888 = FORMAT_BGRA_8888
|
||
FORMAT_Y8 = FORMAT_Y8
|
||
FORMAT_Y16 = FORMAT_Y16
|
||
FORMAT_DEPTH16 = FORMAT_DEPTH16
|
||
FORMAT_DEPTH_POINT_CLOUD = FORMAT_DEPTH_POINT_CLOUD
|
||
FORMAT_HEIC = FORMAT_HEIC
|
||
|
||
def __init__(self, width: int = 0, height: int = 0,
|
||
format: int = FORMAT_UNKNOWN, timestamp: int = 0):
|
||
super().__init__()
|
||
self._width = width
|
||
self._height = height
|
||
self._format = format
|
||
self._timestamp = timestamp
|
||
self._planes: List[Image.Plane] = []
|
||
self._crop: Optional[Tuple[int, int, int, int]] = None
|
||
self._fence: Optional[Any] = None
|
||
self._hardware_buffer: Optional[Any] = None
|
||
self._released = False
|
||
self._owner: Optional[Any] = None
|
||
self._source: Optional[Any] = None
|
||
self._lock = threading.Lock()
|
||
|
||
def getWidth(self) -> int:
|
||
return self._width
|
||
|
||
def getHeight(self) -> int:
|
||
return self._height
|
||
|
||
def getFormat(self) -> int:
|
||
return self._format
|
||
|
||
def getTimestamp(self) -> int:
|
||
return self._timestamp
|
||
|
||
def setTimestamp(self, timestamp: int) -> None:
|
||
self._timestamp = timestamp
|
||
|
||
def getPlanes(self) -> List[Plane]:
|
||
return self._planes
|
||
|
||
def getCropRect(self) -> Optional[Tuple[int, int, int, int]]:
|
||
return self._crop
|
||
|
||
def setCropRect(self, crop: Tuple[int, int, int, int]) -> None:
|
||
self._crop = crop
|
||
|
||
def getFence(self) -> Optional[Any]:
|
||
return self._fence
|
||
|
||
def setFence(self, fence: Any) -> None:
|
||
self._fence = fence
|
||
|
||
def getHardwareBuffer(self) -> Optional[Any]:
|
||
return self._hardware_buffer
|
||
|
||
def close(self) -> None:
|
||
with self._lock:
|
||
if self._released:
|
||
return
|
||
self._released = True
|
||
self._planes.clear()
|
||
if self._source:
|
||
self._source._notify_image_closed(self)
|
||
|
||
def isClosed(self) -> bool:
|
||
return self._released
|
||
|
||
def toString(self) -> str:
|
||
return (f"Image(width={self._width}, height={self._height}, "
|
||
f"format={self._format}, planes={len(self._planes)}, "
|
||
f"timestamp={self._timestamp})")
|
||
|
||
|
||
# ═══════════════════════════════════════════════════════════════
|
||
# ImageReader
|
||
# ═══════════════════════════════════════════════════════════════
|
||
|
||
class ImageReader(Stub):
|
||
"""ImageReader — 图像读取器"""
|
||
|
||
def __init__(self, width: int, height: int, format: int,
|
||
max_images: int = 1, usage: int = 0):
|
||
super().__init__()
|
||
self._width = width
|
||
self._height = height
|
||
self._format = format
|
||
self._max_images = max_images
|
||
self._usage = usage
|
||
self._images: List[Image] = []
|
||
self._available_images: List[Image] = []
|
||
self._on_image_available: Optional[Callable[[ImageReader], None]] = None
|
||
self._lock = threading.Lock()
|
||
self._released = False
|
||
self._surface: Optional[Any] = None
|
||
|
||
@staticmethod
|
||
def newInstance(width: int, height: int, format: int,
|
||
max_images: int = 1, usage: int = 0) -> "ImageReader":
|
||
return ImageReader(width, height, format, max_images, usage)
|
||
|
||
def acquireLatestImage(self) -> Optional[Image]:
|
||
with self._lock:
|
||
if not self._available_images:
|
||
return None
|
||
latest = self._available_images[-1]
|
||
self._available_images.clear()
|
||
return latest
|
||
|
||
def acquireNextImage(self) -> Optional[Image]:
|
||
with self._lock:
|
||
if not self._available_images:
|
||
return None
|
||
return self._available_images.pop(0)
|
||
|
||
def getWidth(self) -> int:
|
||
return self._width
|
||
|
||
def getHeight(self) -> int:
|
||
return self._height
|
||
|
||
def getFormat(self) -> int:
|
||
return self._format
|
||
|
||
def getMaxImages(self) -> int:
|
||
return self._max_images
|
||
|
||
def getUsage(self) -> int:
|
||
return self._usage
|
||
|
||
def getSurface(self) -> Optional[Any]:
|
||
return self._surface
|
||
|
||
def setOnImageAvailableListener(self, listener: Optional[Callable],
|
||
handler: Optional[Any] = None) -> None:
|
||
self._on_image_available = listener
|
||
|
||
def getOnImageAvailableListener(self) -> Optional[Callable]:
|
||
return self._on_image_available
|
||
|
||
def close(self) -> None:
|
||
with self._lock:
|
||
if self._released:
|
||
return
|
||
self._released = True
|
||
for img in self._images:
|
||
img.close()
|
||
self._images.clear()
|
||
self._available_images.clear()
|
||
|
||
def isClosed(self) -> bool:
|
||
return self._released
|
||
|
||
def _notify_image_closed(self, image: Image) -> None:
|
||
with self._lock:
|
||
if image in self._images:
|
||
self._images.remove(image)
|
||
|
||
def _add_image(self, image: Image) -> None:
|
||
with self._lock:
|
||
image._source = self
|
||
self._images.append(image)
|
||
self._available_images.append(image)
|
||
if self._on_image_available:
|
||
self._on_image_available(self)
|
||
|
||
def toString(self) -> str:
|
||
return (f"ImageReader(width={self._width}, height={self._height}, "
|
||
f"format={self._format}, maxImages={self._max_images})")
|
||
|
||
|
||
# ═══════════════════════════════════════════════════════════════
|
||
# ImageWriter
|
||
# ═══════════════════════════════════════════════════════════════
|
||
|
||
class ImageWriter(Stub):
|
||
"""ImageWriter — 图像写入器"""
|
||
|
||
def __init__(self, surface: Any, max_images: int = 1):
|
||
super().__init__()
|
||
self._surface = surface
|
||
self._max_images = max_images
|
||
self._queued_images: List[Image] = []
|
||
self._on_image_released: Optional[Callable] = None
|
||
self._lock = threading.Lock()
|
||
self._released = False
|
||
|
||
@staticmethod
|
||
def newInstance(surface: Any, max_images: int = 1) -> "ImageWriter":
|
||
return ImageWriter(surface, max_images)
|
||
|
||
def getSurface(self) -> Optional[Any]:
|
||
return self._surface
|
||
|
||
def getMaxImages(self) -> int:
|
||
return self._max_images
|
||
|
||
def queueInputImage(self, image: Image) -> None:
|
||
with self._lock:
|
||
if self._released:
|
||
raise RuntimeException("ImageWriter 已关闭")
|
||
self._queued_images.append(image)
|
||
if self._on_image_released:
|
||
self._on_image_released(self)
|
||
|
||
def setOnImageReleasedListener(self, listener: Optional[Callable],
|
||
handler: Optional[Any] = None) -> None:
|
||
self._on_image_released = listener
|
||
|
||
def getOnImageReleasedListener(self) -> Optional[Callable]:
|
||
return self._on_image_released
|
||
|
||
def close(self) -> None:
|
||
with self._lock:
|
||
if self._released:
|
||
return
|
||
self._released = True
|
||
self._queued_images.clear()
|
||
|
||
def isClosed(self) -> bool:
|
||
return self._released
|
||
|
||
def toString(self) -> str:
|
||
return (f"ImageWriter(maxImages={self._max_images}, "
|
||
f"queued={len(self._queued_images)})")
|
||
|
||
|
||
# ═══════════════════════════════════════════════════════════════
|
||
# MediaImage
|
||
# ═══════════════════════════════════════════════════════════════
|
||
|
||
class MediaImage(Image):
|
||
"""MediaImage — 媒体图像(扩展 Image)"""
|
||
|
||
def __init__(self, width: int = 0, height: int = 0,
|
||
format: int = FORMAT_UNKNOWN, timestamp: int = 0,
|
||
sequence_number: int = 0):
|
||
super().__init__(width, height, format, timestamp)
|
||
self._sequence_number = sequence_number
|
||
self._metadata: Dict[str, Any] = {}
|
||
self._transform: int = TRANSFORM_NONE
|
||
|
||
def getSequenceNumber(self) -> int:
|
||
return self._sequence_number
|
||
|
||
def setSequenceNumber(self, seq: int) -> None:
|
||
self._sequence_number = seq
|
||
|
||
def getTransform(self) -> int:
|
||
return self._transform
|
||
|
||
def setTransform(self, transform: int) -> None:
|
||
self._transform = transform
|
||
|
||
def getMetadata(self, key: str) -> Any:
|
||
return self._metadata.get(key)
|
||
|
||
def setMetadata(self, key: str, value: Any) -> None:
|
||
self._metadata[key] = value
|
||
|
||
def getAllMetadata(self) -> Dict[str, Any]:
|
||
return dict(self._metadata)
|
||
|
||
def toString(self) -> str:
|
||
return (f"MediaImage(width={self.getWidth()}, height={self.getHeight()}, "
|
||
f"format={self.getFormat()}, seq={self._sequence_number})")
|
||
|
||
|
||
# ═══════════════════════════════════════════════════════════════
|
||
# SurfaceImage / ImageTransform
|
||
# ═══════════════════════════════════════════════════════════════
|
||
|
||
class SurfaceImage(Stub):
|
||
"""SurfaceImage — 表面图像(用于 SurfaceView/TextureView 捕获)"""
|
||
|
||
def __init__(self):
|
||
super().__init__()
|
||
self._image: Optional[Image] = None
|
||
self._transform: int = TRANSFORM_NONE
|
||
self._timestamp: int = 0
|
||
self._lock = threading.Lock()
|
||
|
||
def getImage(self) -> Optional[Image]:
|
||
with self._lock:
|
||
return self._image
|
||
|
||
def setImage(self, image: Image) -> None:
|
||
with self._lock:
|
||
self._image = image
|
||
self._timestamp = image.getTimestamp()
|
||
|
||
def getTransform(self) -> int:
|
||
return self._transform
|
||
|
||
def setTransform(self, transform: int) -> None:
|
||
self._transform = transform
|
||
|
||
def getTimestamp(self) -> int:
|
||
return self._timestamp
|
||
|
||
def release(self) -> None:
|
||
with self._lock:
|
||
if self._image:
|
||
self._image.close()
|
||
self._image = None
|
||
|
||
|
||
class ImageTransform(Stub):
|
||
"""ImageTransform — 图像变换"""
|
||
|
||
SCALER_ROTATE_90 = SCALER_ROTATE_90
|
||
SCALER_ROTATE_180 = SCALER_ROTATE_180
|
||
SCALER_ROTATE_270 = SCALER_ROTATE_270
|
||
TRANSFORM_NONE = TRANSFORM_NONE
|
||
TRANSFORM_FLIP_H = TRANSFORM_FLIP_H
|
||
TRANSFORM_FLIP_V = TRANSFORM_FLIP_V
|
||
TRANSFORM_ROTATE_90 = TRANSFORM_ROTATE_90
|
||
TRANSFORM_ROTATE_180 = TRANSFORM_ROTATE_180
|
||
TRANSFORM_ROTATE_270 = TRANSFORM_ROTATE_270
|
||
|
||
def __init__(self, rotation: int = 0, flip_h: bool = False, flip_v: bool = False):
|
||
super().__init__()
|
||
self._rotation = rotation
|
||
self._flip_h = flip_h
|
||
self._flip_v = flip_v
|
||
|
||
def getRotation(self) -> int:
|
||
return self._rotation
|
||
|
||
def setRotation(self, rotation: int) -> None:
|
||
self._rotation = rotation
|
||
|
||
def isFlippedHorizontally(self) -> bool:
|
||
return self._flip_h
|
||
|
||
def setFlipHorizontal(self, flip: bool) -> None:
|
||
self._flip_h = flip
|
||
|
||
def isFlippedVertically(self) -> bool:
|
||
return self._flip_v
|
||
|
||
def setFlipVertical(self, flip: bool) -> None:
|
||
self._flip_v = flip
|
||
|
||
@staticmethod
|
||
def fromTransformBits(transform: int) -> "ImageTransform":
|
||
flip_h = bool(transform & TRANSFORM_FLIP_H)
|
||
flip_v = bool(transform & TRANSFORM_FLIP_V)
|
||
rotation = 0
|
||
if transform & TRANSFORM_ROTATE_90:
|
||
rotation = 90
|
||
elif transform & TRANSFORM_ROTATE_180:
|
||
rotation = 180
|
||
elif transform & TRANSFORM_ROTATE_270:
|
||
rotation = 270
|
||
return ImageTransform(rotation, flip_h, flip_v)
|
||
|
||
def getTransformBits(self) -> int:
|
||
bits = 0
|
||
if self._rotation == 90:
|
||
bits |= TRANSFORM_ROTATE_90
|
||
elif self._rotation == 180:
|
||
bits |= TRANSFORM_ROTATE_180
|
||
elif self._rotation == 270:
|
||
bits |= TRANSFORM_ROTATE_270
|
||
if self._flip_h:
|
||
bits |= TRANSFORM_FLIP_H
|
||
if self._flip_v:
|
||
bits |= TRANSFORM_FLIP_V
|
||
return bits
|
||
|
||
def toString(self) -> str:
|
||
return (f"ImageTransform(rotation={self._rotation}, "
|
||
f"flipH={self._flip_h}, flipV={self._flip_v})")
|
||
|
||
|
||
class ImageConfig(Stub):
|
||
"""ImageConfig — 图像配置"""
|
||
|
||
def __init__(self, width: int = 0, height: int = 0,
|
||
format: int = FORMAT_UNKNOWN, usage: int = 0):
|
||
super().__init__()
|
||
self._width = width
|
||
self._height = height
|
||
self._format = format
|
||
self._usage = usage
|
||
|
||
def getWidth(self) -> int:
|
||
return self._width
|
||
|
||
def setWidth(self, width: int) -> None:
|
||
self._width = width
|
||
|
||
def getHeight(self) -> int:
|
||
return self._height
|
||
|
||
def setHeight(self, height: int) -> None:
|
||
self._height = height
|
||
|
||
def getFormat(self) -> int:
|
||
return self._format
|
||
|
||
def setFormat(self, fmt: int) -> None:
|
||
self._format = fmt
|
||
|
||
def getUsage(self) -> int:
|
||
return self._usage
|
||
|
||
def setUsage(self, usage: int) -> None:
|
||
self._usage = usage
|
||
|
||
def toString(self) -> str:
|
||
return (f"ImageConfig(width={self._width}, height={self._height}, "
|
||
f"format={self._format})")
|
||
|
||
|
||
class ImagePool(Stub):
|
||
"""ImagePool — 图像池"""
|
||
|
||
def __init__(self, max_images: int = 4):
|
||
super().__init__()
|
||
self._max_images = max_images
|
||
self._pool: List[Image] = []
|
||
self._lock = threading.Lock()
|
||
|
||
def acquireImage(self, width: int, height: int, format: int) -> Optional[Image]:
|
||
with self._lock:
|
||
for img in self._pool:
|
||
if (img.getWidth() == width and img.getHeight() == height
|
||
and img.getFormat() == format and not img.isClosed()):
|
||
self._pool.remove(img)
|
||
return img
|
||
if len(self._pool) < self._max_images:
|
||
img = Image(width, height, format)
|
||
return img
|
||
return None
|
||
|
||
def releaseImage(self, image: Image) -> None:
|
||
with self._lock:
|
||
if len(self._pool) < self._max_images and not image.isClosed():
|
||
self._pool.append(image)
|
||
|
||
def close(self) -> None:
|
||
with self._lock:
|
||
for img in self._pool:
|
||
img.close()
|
||
self._pool.clear()
|
||
|
||
def getAvailableCount(self) -> int:
|
||
with self._lock:
|
||
return len(self._pool)
|
||
|
||
def getMaxImages(self) -> int:
|
||
return self._max_images
|
||
|
||
def toString(self) -> str:
|
||
return f"ImagePool(max={self._max_images}, available={len(self._pool)})"
|
||
|
||
|
||
class ImageUtils(Stub):
|
||
"""ImageUtils — 图像工具类"""
|
||
|
||
@staticmethod
|
||
def getFormatName(format: int) -> str:
|
||
names = {
|
||
FORMAT_NV21: "NV21",
|
||
FORMAT_NV16: "NV16",
|
||
FORMAT_YUY2: "YUY2",
|
||
FORMAT_JPEG: "JPEG",
|
||
FORMAT_RAW_PRIVATE: "RAW_PRIVATE",
|
||
FORMAT_RAW_SENSOR: "RAW_SENSOR",
|
||
FORMAT_RAW10: "RAW10",
|
||
FORMAT_RAW12: "RAW12",
|
||
FORMAT_RAW_DEPTH: "RAW_DEPTH",
|
||
FORMAT_YUV_420_888: "YUV_420_888",
|
||
FORMAT_FLEX_RGB_888: "FLEX_RGB_888",
|
||
FORMAT_FLEX_RGBA_8888: "FLEX_RGBA_8888",
|
||
FORMAT_PRIVATE: "PRIVATE",
|
||
FORMAT_RGB_565: "RGB_565",
|
||
FORMAT_RGBA_8888: "RGBA_8888",
|
||
FORMAT_BGRA_8888: "BGRA_8888",
|
||
FORMAT_DEPTH16: "DEPTH16",
|
||
FORMAT_DEPTH_POINT_CLOUD: "DEPTH_POINT_CLOUD",
|
||
FORMAT_HEIC: "HEIC",
|
||
}
|
||
return names.get(format, f"UNKNOWN({format})")
|
||
|
||
@staticmethod
|
||
def isYuvFormat(format: int) -> bool:
|
||
return format in (FORMAT_NV21, FORMAT_NV16, FORMAT_YUY2,
|
||
FORMAT_YUV_420_888, FORMAT_YUV_422_888, FORMAT_YUV_444_888)
|
||
|
||
@staticmethod
|
||
def getPlaneCount(format: int) -> int:
|
||
if format in (FORMAT_NV21, FORMAT_NV16):
|
||
return 2
|
||
if format in (FORMAT_YUV_420_888, FORMAT_YUV_422_888, FORMAT_YUV_444_888):
|
||
return 3
|
||
if format in (FORMAT_RGBA_8888, FORMAT_RGBX_8888, FORMAT_BGRA_8888,
|
||
FORMAT_RGB_565, FORMAT_JPEG):
|
||
return 1
|
||
if format == FORMAT_PRIVATE:
|
||
return 1
|
||
return 1
|
||
|
||
@staticmethod
|
||
def getSizeInBytes(width: int, height: int, format: int) -> int:
|
||
bpp = {
|
||
FORMAT_RGBA_8888: 4,
|
||
FORMAT_RGBX_8888: 4,
|
||
FORMAT_BGRA_8888: 4,
|
||
FORMAT_RGB_565: 2,
|
||
FORMAT_YUY2: 2,
|
||
}
|
||
if format == FORMAT_JPEG:
|
||
return width * height * 3
|
||
if format == FORMAT_NV21:
|
||
return width * height * 3 // 2
|
||
if format == FORMAT_NV16:
|
||
return width * height * 2
|
||
if format == FORMAT_YUV_420_888:
|
||
return width * height * 3 // 2
|
||
if format in bpp:
|
||
return width * height * bpp[format]
|
||
return width * height * 4
|
||
|
||
@staticmethod
|
||
def isDepthFormat(format: int) -> bool:
|
||
return format in (FORMAT_DEPTH16, FORMAT_DEPTH_POINT_CLOUD,
|
||
FORMAT_RAW_DEPTH, FORMAT_RAW_DEPTH10) |