feat: 大规模扩充至212个模块/175K行代码 — 覆盖android/java/javax/org/dalvik全包
- 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关键字冲突
This commit is contained in:
1 parent
506f9ac725
commit
a51854455b
128 files changed
+100571
-3
No files matched your search
@@ -0,0 +1,649 @@
|
||||
"""
|
||||
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)
|
||||
Reference in new issue
Block a user