IDS peak genericC++ v1.16.0
Loading...
Searching...
No Matches
peak_image_view_impl.hpp
Go to the documentation of this file.
1
10
11#pragma once
12
13#include "peak_image_view.hpp"
14
17
24
25#include <memory>
26
27namespace peak
28{
29namespace core
30{
31
32namespace detail
33{
34constexpr uint64_t usableRoiChunkId = 0x73020405;
35constexpr uint64_t imageChunkId = 0x73688300;
36
38{
39 uint16_t usableWidth{};
40 uint16_t usableHeight{};
41 uint16_t offsetX{};
42 uint16_t offsetY{};
43};
44
45inline UsableRoiChunkInfo ExtractUsableRoiChunkInfo(const std::shared_ptr<peak::core::BufferChunk>& chunk)
46{
47 if (chunk->ID() != usableRoiChunkId)
48 {
49 throw core::InternalErrorException("Cannot extract usable roi chunk info from chunk with wrong ID!");
50 }
51
52 const auto* base = static_cast<uint16_t*>(chunk->BasePtr());
53 return { base[0], base[1], base[2], base[3] };
54}
55
56inline std::shared_ptr<core::BufferChunk> FindBufferChunkById(
57 const std::vector<std::shared_ptr<peak::core::BufferChunk>>& chunks, uint64_t chunkId)
58{
59 const auto it = std::find_if(
60 chunks.cbegin(), chunks.cend(), [chunkId](const auto& chunk) { return chunk->ID() == chunkId; });
61 if (it == chunks.cend())
62 {
63 return nullptr;
64 }
65 return *it;
66}
67
69 const std::vector<std::shared_ptr<peak::core::BufferChunk>>& chunks)
70{
71 const auto imageChunk = FindBufferChunkById(chunks, imageChunkId);
72 if (imageChunk == nullptr)
73 {
74 throw core::InternalErrorException("Buffer has no image chunk.");
75 }
76
77 const auto imageSizeWithPaddingWithoutChunks = imageChunk->Size();
78
79 const auto usableRoiChunk = FindBufferChunkById(chunks, usableRoiChunkId);
80 if (usableRoiChunk == nullptr)
81 {
82 return payload;
83 }
84
85 ExtractedPayload result{ payload };
86
87 const auto chunkInfo = ExtractUsableRoiChunkInfo(usableRoiChunk);
88
89 result.size = peak::common::Size{ chunkInfo.usableWidth, chunkInfo.usableHeight };
90
91 auto buffer = imageChunk->ParentBuffer();
92 if (result.bytesPerLine != imageSizeWithPaddingWithoutChunks / buffer->Height())
93 {
94 throw core::InternalErrorException("Unexpected pitch!");
95 }
96
97 const auto bytesToSkip = result.bytesPerLine * chunkInfo.offsetY;
98 result.dataPtr = static_cast<void*>(static_cast<uint8_t*>(result.dataPtr) + bytesToSkip);
99
100 const peak::common::PixelFormatInfo pixelFormatInfo(result.pixelFormat);
101 result.lineStartOffset = pixelFormatInfo.GetSizeInBytes({ chunkInfo.offsetX, 1 });
102 result.dataSize = pixelFormatInfo.GetSizeInBytes(
103 { static_cast<uint32_t>(buffer->Width()), chunkInfo.usableHeight });
104 if (result.dataSize > imageSizeWithPaddingWithoutChunks)
105 {
106 throw core::InternalErrorException("Chunk size is not large enough to fit the expected image size!");
107 }
108
109 return result;
110}
111
112inline ExtractedPayload ExtractPayloadTypeImage(const std::shared_ptr<peak::core::Buffer>& buffer)
113{
114 assert(buffer->PixelFormatNamespace() != core::PixelFormatNamespace::IIDC
115 && buffer->PixelFormatNamespace() != core::PixelFormatNamespace::Custom);
116
117 ExtractedPayload result{};
118
119 result.size = { static_cast<uint32_t>(buffer->Width()), static_cast<uint32_t>(buffer->Height()) };
120 result.pixelFormat = static_cast<peak::common::PixelFormat>(buffer->PixelFormat());
121 result.dataPtr = static_cast<uint8_t*>(buffer->BasePtr()) + buffer->ImageOffset();
122
123 const auto pixelFormatInfo = peak::common::PixelFormatInfo(result.pixelFormat);
124
125 result.bytesPerLine = pixelFormatInfo.GetSizeInBytes({ static_cast<uint32_t>(buffer->Width()), 1 });
126 result.lineStartOffset = 0;
127 result.dataSize = pixelFormatInfo.GetSizeInBytes(
128 { static_cast<uint32_t>(buffer->Width()), static_cast<uint32_t>(buffer->Height()) });
129
130 const auto imageSizeWithPadding = buffer->Size() - buffer->ImageOffset();
131 if (result.dataSize > imageSizeWithPadding)
132 {
133 throw core::InternalErrorException("Buffer is not large enough to fit the expected image size!");
134 }
135
136 if (buffer->HasChunks())
137 {
138 result = UpdatePayloadInfoWithChunks(result, buffer->Chunks());
139 }
140
141 return result;
142}
143
144inline ExtractedPayload ExtractPayloadTypeChunk(const std::shared_ptr<peak::core::Buffer>& buffer)
145{
146 const auto remoteNodeMap = buffer->ParentDataStream()->ParentDevice()->RemoteDevice()->NodeMaps().at(0);
147 remoteNodeMap->UpdateChunkNodes(buffer);
148
149 const auto chunkWidth = remoteNodeMap->TryFindNode<core::nodes::IntegerNode>("ChunkWidth");
150 if (chunkWidth == nullptr || chunkWidth->AccessStatus() == core::nodes::NodeAccessStatus::NotAvailable)
151 {
152 throw core::InvalidCastException("Buffer has no ChunkWidth.");
153 }
154
155 const auto chunkHeight = remoteNodeMap->TryFindNode<core::nodes::IntegerNode>("ChunkHeight");
156 if (chunkHeight == nullptr || chunkHeight->AccessStatus() == core::nodes::NodeAccessStatus::NotAvailable)
157 {
158 throw core::InvalidCastException("Buffer has no ChunkHeight.");
159 }
160
161 const peak::common::Size size(
162 static_cast<uint32_t>(chunkWidth->Value()), static_cast<uint32_t>(chunkHeight->Value()));
163
164 const auto chunkPixelFormat = remoteNodeMap->TryFindNode<core::nodes::EnumerationNode>("ChunkPixelFormat");
165 if (chunkPixelFormat == nullptr || chunkPixelFormat->AccessStatus() == core::nodes::NodeAccessStatus::NotAvailable)
166 {
167 throw core::InvalidCastException("Buffer has no ChunkPixelFormat.");
168 }
169
170 const auto pixelFormat = static_cast<peak::common::PixelFormat>(
171 chunkPixelFormat->CurrentEntry()->NumericValue());
172
173 // assume first chunks is image data
174 const auto imageChunk = FindBufferChunkById(buffer->Chunks(), imageChunkId);
175 if (imageChunk == nullptr)
176 {
177 throw core::InternalErrorException("Buffer has no image chunk.");
178 }
179
180 const auto sizeInBytes = imageChunk->Size();
181
182 const auto pixelFormatInfo = peak::common::PixelFormatInfo(pixelFormat);
183 const auto expectedDataSize = pixelFormatInfo.GetSizeInBytes(size);
184 if (sizeInBytes < expectedDataSize)
185 {
186 std::stringstream msg;
187 msg << "The buffer's first chunk's size (" << imageChunk->Size() << ") is smaller than the expected data size ("
188 << expectedDataSize << ").";
189 throw core::InvalidCastException(msg.str());
190 }
191
192 return { size, pixelFormat, imageChunk->BasePtr(), sizeInBytes,
193 pixelFormatInfo.GetSizeInBytes(peak::common::Size(size.GetWidth(), 1)), 0 };
194}
195
196inline ExtractedPayload ExtractPayloadFromBufferPart(const std::shared_ptr<peak::core::BufferPart>& part)
197{
198 if (part == nullptr)
199 {
200 throw core::InvalidArgumentException("The given part is a nullptr!");
201 }
202
203 const auto partType = part->Type();
204
205 if (partType != BufferPartType::Image2D && partType != BufferPartType::ConfidenceMap
206 && partType != BufferPartType::Image3D)
207 {
208 throw core::InvalidCastException("BufferPart has no image data.");
209 }
210
211 assert(part->FormatNamespace() != static_cast<uint64_t>(core::PixelFormatNamespace::IIDC)
212 && part->FormatNamespace() != static_cast<uint64_t>(core::PixelFormatNamespace::Custom));
213
214 const auto pixelFormat = static_cast<peak::common::PixelFormat>(part->Format());
215 const auto bytesPerLine = peak::common::PixelFormatInfo(pixelFormat)
216 .GetSizeInBytes({ static_cast<uint32_t>(part->Width()), 1 });
217 return { peak::common::Size{ static_cast<uint32_t>(part->Width()), static_cast<uint32_t>(part->Height()) },
218 pixelFormat, part->BasePtr(), part->Size(), bytesPerLine, 0 };
219}
220
221inline ExtractedPayload ExtractPayloadFromBuffer(const std::shared_ptr<peak::core::Buffer>& buffer)
222{
223 if (buffer == nullptr)
224 {
225 throw core::InvalidArgumentException("The given buffer is a nullptr!");
226 }
227
228 if (buffer->HasImage())
229 {
230 return ExtractPayloadTypeImage(buffer);
231 }
232
233 if (buffer->PayloadType() == core::BufferPayloadType::Chunk)
234 {
235 return ExtractPayloadTypeChunk(buffer);
236 }
237
238 throw core::InvalidCastException("Buffer has no image data and no chunks.");
239}
240
241inline std::shared_ptr<peak::common::Metadata> ExtractMetadataFromBuffer(
242 const std::shared_ptr<peak::core::Buffer>& buffer, MetadataExtractionMode mode)
243{
244 if (buffer == nullptr)
245 {
246 throw core::InvalidArgumentException("The given buffer is a nullptr!");
247 }
248
249 auto metadata = std::make_shared<peak::common::Metadata>();
250
251 // NOTE: BUFFER_INFO_FRAMEID is a mandatory GenTL feature. It MUST be implemented.
252 metadata->SetValueByKey<peak::common::MetadataKey::DeviceFrameID>(buffer->FrameID());
253
254 // NOTE: We need to try, as the timestamp might not be supported by the TL.
255 try
256 {
257 metadata->SetValueByKey<peak::common::MetadataKey::DeviceTimestamp>(buffer->Timestamp_ns());
258 }
259 catch (const peak::core::Exception&)
260 {}
261
262 // NOTE: The system timestamp is optional and may not be supported by the TL or device.
263 try
264 {
265 metadata->SetValueByKey<peak::common::MetadataKey::SystemTimestamp>(buffer->SystemTimestamp_ns());
266 }
267 catch (const peak::core::Exception&)
268 {}
269
271 {
272 return metadata;
273 }
274
275 // MetadataExtractionMode::Extended
276
277 const auto remoteNodeMap = buffer->ParentDataStream()->ParentDevice()->RemoteDevice()->NodeMaps().at(0);
278 const auto chunkExposureTimeNode = remoteNodeMap->TryFindNode<nodes::FloatNode>("ChunkExposureTime");
279 const auto chunkGainSelectorNode = remoteNodeMap->TryFindNode<nodes::EnumerationNode>("ChunkGainSelector");
280 const auto chunkGainNode = remoteNodeMap->TryFindNode<nodes::FloatNode>("ChunkGain");
281
282 const auto lock = remoteNodeMap->Lock();
283 remoteNodeMap->UpdateChunkNodes(buffer);
284
285 if (chunkExposureTimeNode != nullptr && chunkExposureTimeNode->IsReadable())
286 {
287 metadata->SetValueByKey<peak::common::MetadataKey::DeviceExposureTime>(chunkExposureTimeNode->Value());
288 }
289
290 if (chunkGainSelectorNode != nullptr && chunkGainSelectorNode->AccessStatus() == nodes::NodeAccessStatus::ReadWrite
291 && chunkGainNode != nullptr)
292 {
293 const auto availableEntries = chunkGainSelectorNode->AvailableEntries();
294
295 bool found = false;
296 auto readChunkGain = [&](const std::string& entryName) {
297 const auto entry = chunkGainSelectorNode->TryFindEntry(entryName);
298 if (entry == nullptr || !entry->IsAvailable())
299 {
300 return 1.0;
301 }
302
303 chunkGainSelectorNode->SetCurrentEntry(entry);
304 if (!chunkGainNode->IsReadable())
305 {
306 return 1.0;
307 }
308 found = true;
309 return chunkGainNode->Value();
310 };
311
312 const auto gainAll = readChunkGain("All");
313 const auto gainAnalogAll = readChunkGain("AnalogAll");
314 const auto gainDigitalAll = readChunkGain("DigitalAll");
315
316 if (found)
317 {
318 metadata->SetValueByKey<peak::common::MetadataKey::DeviceGain>(
319 gainAll * gainAnalogAll * gainDigitalAll);
320 }
321 }
322
323 return metadata;
324}
325
326} // namespace detail
327
329 const detail::ExtractedPayload& payload, std::shared_ptr<peak::common::Metadata> metadata)
330 : m_metadata{ std::move(metadata) }
331 , m_payload{ payload }
332{}
333
334inline ImageView::ImageView(const std::shared_ptr<peak::core::Buffer>& buffer)
335 : ImageView(detail::ExtractPayloadFromBuffer(buffer),
336 detail::ExtractMetadataFromBuffer(buffer, MetadataExtractionMode::Minimal))
337{
338 m_parentBuffer = buffer;
339}
340
341inline ImageView::ImageView(const std::shared_ptr<Buffer>& buffer, MetadataExtractionMode mode)
342 : ImageView(detail::ExtractPayloadFromBuffer(buffer), detail::ExtractMetadataFromBuffer(buffer, mode))
343{
344 m_parentBuffer = buffer;
345}
346
347inline ImageView::ImageView(const std::shared_ptr<core::BufferPart>& part)
348 : ImageView(detail::ExtractPayloadFromBufferPart(part),
349 detail::ExtractMetadataFromBuffer(part->ParentBuffer(), MetadataExtractionMode::Minimal))
350{
351 m_parentBuffer = part->ParentBuffer();
352}
353
354inline ImageView::ImageView(const std::shared_ptr<core::BufferPart>& part, MetadataExtractionMode mode)
355 : ImageView(detail::ExtractPayloadFromBufferPart(part),
356 detail::ExtractMetadataFromBuffer(part->ParentBuffer(), mode))
357{
358 m_parentBuffer = part->ParentBuffer();
359}
360
361inline const uint8_t* ImageView::GetData() const
362{
363 return static_cast<uint8_t*>(m_payload.dataPtr);
364}
365
366inline uint8_t* ImageView::GetData()
367{
368 return static_cast<uint8_t*>(m_payload.dataPtr);
369}
370
371inline std::size_t ImageView::GetLineStartOffset() const
372{
373 return m_payload.lineStartOffset;
374}
375
376inline std::size_t ImageView::GetSizeInBytes() const
377{
378 return m_payload.dataSize;
379}
380
382{
383 return m_payload.pixelFormat;
384}
385
387{
388 return peak::common::PixelFormatInfo(m_payload.pixelFormat);
389}
390
392{
393 return m_payload.size;
394}
395
396inline uint32_t ImageView::GetWidth() const
397{
398 return m_payload.size.GetWidth();
399}
400
401inline uint32_t ImageView::GetHeight() const
402{
403 return m_payload.size.GetHeight();
404}
405
406inline size_t ImageView::GetBitsPerPixel() const
407{
408 return peak::common::PixelFormatInfo(m_payload.pixelFormat).GetAllocatedBitsPerPixel();
409}
410
411inline size_t ImageView::GetBytesPerLine() const
412{
413 return m_payload.bytesPerLine;
414}
415
416inline std::shared_ptr<peak::common::Metadata> ImageView::GetMetadata()
417{
418 return m_metadata;
419}
420
421inline std::shared_ptr<const peak::common::Metadata> ImageView::GetMetadata() const
422{
423 return m_metadata;
424}
425
426inline std::shared_ptr<peak::core::Buffer> ImageView::GetParentBuffer() const
427{
428 return LockOrThrow(m_parentBuffer);
429}
430
431} // namespace core
432} // namespace peak
Provides information and utility functions for pixel formats.
Definition peak_common_pixel_format.hpp:239
PEAK_COMMON_NO_DISCARD size_t GetSizeInBytes(const Size &size) const
Calculates the memory size in bytes for a given image size.
Definition peak_common_pixel_format_info.ipp:1188
PEAK_COMMON_NO_DISCARD size_t GetAllocatedBitsPerPixel() const
Returns the number of allocated bits per pixel.
Definition peak_common_pixel_format_info.ipp:931
PEAK_COMMON_NO_DISCARD constexpr T GetWidth() const
Returns the width.
Definition peak_common_size.hpp:119
The base class for all exceptions thrown by the library.
Definition peak_exception.hpp:28
PEAK_COMMON_NO_DISCARD uint32_t GetHeight() const override
Height of the image in pixels.
Definition peak_image_view_impl.hpp:401
PEAK_COMMON_NO_DISCARD std::size_t GetSizeInBytes() const override
Returns the number of bytes in a single image row.
Definition peak_image_view_impl.hpp:376
PEAK_COMMON_NO_DISCARD std::size_t GetLineStartOffset() const override
Returns the byte offset to the first pixel of a line.
Definition peak_image_view_impl.hpp:371
PEAK_COMMON_NO_DISCARD size_t GetBytesPerLine() const override
The amount of bytes per line.
Definition peak_image_view_impl.hpp:411
PEAK_COMMON_NO_DISCARD peak::common::PixelFormatInfo GetPixelFormatInfo() const override
Information object for the PixelFormat of the contained image.
Definition peak_image_view_impl.hpp:386
PEAK_COMMON_NO_DISCARD size_t GetBitsPerPixel() const override
The amount of bits in one pixel.
Definition peak_image_view_impl.hpp:406
PEAK_COMMON_NO_DISCARD std::shared_ptr< peak::core::Buffer > GetParentBuffer() const
The parent buffer object, the image view was created from.
Definition peak_image_view_impl.hpp:426
PEAK_COMMON_NO_DISCARD uint32_t GetWidth() const override
Width of the image in pixels.
Definition peak_image_view_impl.hpp:396
PEAK_COMMON_NO_DISCARD const uint8_t * GetData() const override
Returns a pointer to the start of the first line that contains valid image data (read-only).
Definition peak_image_view_impl.hpp:361
ImageView(const std::shared_ptr< Buffer > &buffer)
Construct an ImageView from a Buffer.
Definition peak_image_view_impl.hpp:334
PEAK_COMMON_NO_DISCARD peak::common::PixelFormat GetPixelFormat() const override
PixelFormat of the contained image.
Definition peak_image_view_impl.hpp:381
PEAK_COMMON_NO_DISCARD peak::common::Size GetSize() const override
Get the dimensions of the image. I.e. Width, Height, etc.
Definition peak_image_view_impl.hpp:391
PEAK_COMMON_NO_DISCARD std::shared_ptr< peak::common::Metadata > GetMetadata() override
The metadata object belonging to the image.
Definition peak_image_view_impl.hpp:416
The exception thrown for internal errors.
Definition peak_exception.hpp:81
The exception thrown for passing an invalid argument to a function.
Definition peak_exception.hpp:116
The exception thrown for trying to apply an invalid cast.
Definition peak_exception.hpp:142
Represents a GenAPI enumeration node.
Definition peak_enumeration_node.hpp:40
Represents a GenAPI float node.
Definition peak_float_node.hpp:48
Represents a GenAPI integer node.
Definition peak_integer_node.hpp:38
bool IsReadable() const
Returns whether the node is currently readable.
Definition peak_node.hpp:877
NodeAccessStatus AccessStatus() const
Returns the access status.
Definition peak_node.hpp:869
@ Image3D
Definition peak_buffer_part.hpp:42
@ ConfidenceMap
Definition peak_buffer_part.hpp:46
@ Image2D
Definition peak_buffer_part.hpp:38
@ Chunk
Definition peak_buffer.hpp:48
@ Custom
Definition peak_buffer.hpp:72
@ IIDC
Definition peak_buffer.hpp:68
detail::SizeT< uint32_t > Size
Size with unsigned 32-bit integer dimensions.
Definition peak_common_size.hpp:273
PixelFormat
Enum listing all supported pixel formats and their internal IDs.
Definition peak_common_pixel_format.hpp:64
@ NotAvailable
Definition peak_node.hpp:48
@ ReadWrite
Definition peak_node.hpp:51
@ DeviceGain
Device gain the image was captured with.
Definition peak_common_metadata_key.hpp:131
@ DeviceExposureTime
Device exposure time the image was captured with.
Definition peak_common_metadata_key.hpp:94
@ DeviceTimestamp
Device-provided image acquisition timestamp in nanoseconds.
Definition peak_common_metadata_key.hpp:43
@ SystemTimestamp
Timestamp of the system since unix epoch in nanoseconds.
Definition peak_common_metadata_key.hpp:110
@ DeviceFrameID
A sequentially incremented identifier for the frame.
Definition peak_common_metadata_key.hpp:56
Definition peak_image_view.hpp:31
ExtractedPayload UpdatePayloadInfoWithChunks(const peak::core::detail::ExtractedPayload &payload, const std::vector< std::shared_ptr< peak::core::BufferChunk > > &chunks)
Definition peak_image_view_impl.hpp:68
ExtractedPayload ExtractPayloadFromBuffer(const std::shared_ptr< peak::core::Buffer > &buffer)
Definition peak_image_view_impl.hpp:221
ExtractedPayload ExtractPayloadTypeChunk(const std::shared_ptr< peak::core::Buffer > &buffer)
Definition peak_image_view_impl.hpp:144
std::shared_ptr< core::BufferChunk > FindBufferChunkById(const std::vector< std::shared_ptr< peak::core::BufferChunk > > &chunks, uint64_t chunkId)
Definition peak_image_view_impl.hpp:56
ExtractedPayload ExtractPayloadFromBufferPart(const std::shared_ptr< peak::core::BufferPart > &part)
Definition peak_image_view_impl.hpp:196
UsableRoiChunkInfo ExtractUsableRoiChunkInfo(const std::shared_ptr< peak::core::BufferChunk > &chunk)
Definition peak_image_view_impl.hpp:45
constexpr uint64_t imageChunkId
Definition peak_image_view_impl.hpp:35
std::shared_ptr< peak::common::Metadata > ExtractMetadataFromBuffer(const std::shared_ptr< peak::core::Buffer > &buffer, MetadataExtractionMode mode)
Definition peak_image_view_impl.hpp:241
constexpr uint64_t usableRoiChunkId
Definition peak_image_view_impl.hpp:34
ExtractedPayload ExtractPayloadTypeImage(const std::shared_ptr< peak::core::Buffer > &buffer)
Definition peak_image_view_impl.hpp:112
The "core" namespace contains the direct GenAPI and GenTL wrapper.
Definition peak_buffer.hpp:34
MetadataExtractionMode
Controls how metadata is extracted when constructing an ImageView.
Definition peak_image_view.hpp:52
@ Minimal
Definition peak_image_view.hpp:57
The "peak" namespace directly contains convenience functionality like the DeviceManager as well as th...
Definition peak_dynamic_loader.h:35
Definition peak_image_view.hpp:33
size_t bytesPerLine
Definition peak_image_view.hpp:38
size_t lineStartOffset
Definition peak_image_view.hpp:39
size_t dataSize
Definition peak_image_view.hpp:37
peak::common::PixelFormat pixelFormat
Definition peak_image_view.hpp:35
peak::common::Size size
Definition peak_image_view.hpp:34
void * dataPtr
Definition peak_image_view.hpp:36
Definition peak_image_view_impl.hpp:38
uint16_t offsetY
Definition peak_image_view_impl.hpp:42
uint16_t usableWidth
Definition peak_image_view_impl.hpp:39
uint16_t offsetX
Definition peak_image_view_impl.hpp:41
uint16_t usableHeight
Definition peak_image_view_impl.hpp:40