47 class Print final :
public Serializable
51 const std::shared_ptr<Image>
image;
101 auto isoEncoder = IsoImageEncoder(*
this, encoder);
102 return isoEncoder.Encode();
112 IsoImage isoImage(*
this);
113 const std::vector<uint8_t> rawGrayscale =
image->AsRawGrayscale().Data();
114 return isoImage.FillIsoImage(rawGrayscale);
131 static std::shared_ptr<Print>
FromIsoImage(
const std::vector<uint8_t>& isoImage)
133 static constexpr size_t SizeOfIdentifier = 4UL;
134 static constexpr size_t SizeOfVersion = 4UL;
135 if (isoImage.size() < SizeOfIdentifier + SizeOfVersion)
139 if (
const std::vector<uint8_t>
id = {
'F',
'I',
'R',
'\0' };
140 std::search(isoImage.begin(), isoImage.end(),
id.begin(),
id.end()) == isoImage.end())
144 static constexpr size_t VersionIndex = SizeOfIdentifier;
145 if (
const std::vector<uint8_t> ver = {
'0',
'2',
'0',
'\0' };
146 std::search(isoImage.begin() + VersionIndex, isoImage.end(), ver.begin(), ver.end()) == isoImage.end())
150 static constexpr size_t CertificationFlagIndex = 14UL;
151 static constexpr size_t SizeOfCertificationFlag = 1UL;
152 if (isoImage.size() < (CertificationFlagIndex + SizeOfCertificationFlag))
155 "Fail to decode print ISO image (fail to read certification flag)");
157 const auto certificationFlag = isoImage[CertificationFlagIndex];
158 static constexpr size_t DeviceTechnologyId = 29UL;
159 static constexpr size_t SizeOfDeviceTechnologyId = 1UL;
160 if (isoImage.size() < (DeviceTechnologyId + SizeOfDeviceTechnologyId))
163 "Fail to decode print ISO image (fail to read device technology identifier)");
165 const auto deviceTechnologyId = isoImage[DeviceTechnologyId];
166 static constexpr size_t DeviceVendorId = 30UL;
167 static constexpr size_t SizeOfDeviceVendorId = 2UL;
168 if (isoImage.size() < (DeviceVendorId + SizeOfDeviceVendorId))
171 "Fail to decode print ISO image (fail to read device vendor identifier)");
173 const uint16_t deviceVendorId = (isoImage[DeviceVendorId] << 8U) + isoImage[DeviceVendorId + 1];
174 static constexpr size_t DeviceTypeId = 32UL;
175 static constexpr size_t SizeOfDeviceTypeId = 2UL;
176 if (isoImage.size() < (DeviceTypeId + SizeOfDeviceTypeId))
179 "Fail to decode print ISO image (fail to read device type identifier)");
181 const uint16_t deviceTypeId = (isoImage[DeviceTypeId] << 8U) + isoImage[DeviceTypeId + 1];
182 static constexpr size_t QualityBlocksLengthIndex = 34UL;
183 static constexpr size_t SizeOfQualityBlocksLength = 1UL;
184 static constexpr size_t SizeOfQualityBlock = 5UL;
185 if (isoImage.size() < (QualityBlocksLengthIndex + SizeOfQualityBlocksLength))
188 "Fail to decode print ISO image (fail to read quality blocks count)");
190 const auto qualityBlocksCount = isoImage[QualityBlocksLengthIndex];
191 const auto qualityBlocksSize = qualityBlocksCount * SizeOfQualityBlock;
192 size_t sizeOfCertificationRecord = 0;
193 if (certificationFlag == 1)
195 const auto certificationRecordsCountIndex =
196 QualityBlocksLengthIndex + SizeOfQualityBlocksLength + qualityBlocksSize;
197 static constexpr size_t SizeOfCertificationRecordsCount = 1UL;
198 if (isoImage.size() < (certificationRecordsCountIndex + SizeOfCertificationRecordsCount))
201 "Fail to decode print ISO image (fail to read certification records count)");
203 static constexpr size_t SizeOfCertificationRecord = 3UL;
204 sizeOfCertificationRecord = isoImage[certificationRecordsCountIndex] * SizeOfCertificationRecord +
205 SizeOfCertificationRecordsCount;
207 const auto positionIndex =
208 QualityBlocksLengthIndex + SizeOfQualityBlocksLength + qualityBlocksSize + sizeOfCertificationRecord;
209 static constexpr size_t SizeOfPosition = 1UL;
210 if (isoImage.size() < (positionIndex + SizeOfPosition))
214 const auto position = isoImage[positionIndex];
215 static constexpr size_t ImpressionOffsetFromPosition = 13UL;
216 static constexpr size_t SizeOfImpression = 1UL;
217 const auto impressionIndex = positionIndex + ImpressionOffsetFromPosition;
218 if (isoImage.size() < (impressionIndex + SizeOfImpression))
222 const auto impression = isoImage[impressionIndex];
223 static constexpr size_t ImageLengthOffsetFromPosition = 18UL;
224 const auto imageLengthIndex = positionIndex + ImageLengthOffsetFromPosition;
225 static constexpr size_t SizeOfImageLength = 4UL;
226 if (isoImage.size() < (imageLengthIndex + SizeOfImageLength))
230 const size_t encodedImageLength = (isoImage[imageLengthIndex] << 24U) +
231 (isoImage[imageLengthIndex + 1] << 16U) +
232 (isoImage[imageLengthIndex + 2] << 8U) + isoImage[imageLengthIndex + 3];
233 const auto imageDataIndex = imageLengthIndex + SizeOfImageLength;
234 if (isoImage.size() < (imageDataIndex + encodedImageLength))
238 std::vector<uint8_t> encodedImageData = std::vector<uint8_t>(
239 std::next(isoImage.begin(),
static_cast<ptrdiff_t
>(imageDataIndex)),
240 std::next(isoImage.begin(),
static_cast<ptrdiff_t
>(imageDataIndex + encodedImageLength)));
242 static constexpr size_t ImageHorizontalDpiOffsetFromPosition = 7UL;
243 const auto imageHorizontalDpiIndex = positionIndex + ImageHorizontalDpiOffsetFromPosition;
244 const unsigned int imageHorizontalDpi =
245 (isoImage[imageHorizontalDpiIndex] << 8U) + isoImage[imageHorizontalDpiIndex + 1];
246 static constexpr size_t ImageVerticalDpiOffsetFromPosition = 9UL;
247 const auto imageVerticalDpiIndex = positionIndex + ImageVerticalDpiOffsetFromPosition;
248 const unsigned int imageVerticalDpi =
249 (isoImage[imageVerticalDpiIndex] << 8U) + isoImage[imageVerticalDpiIndex + 1];
250 if (imageHorizontalDpi != imageVerticalDpi)
253 "Fail to decode print ISO image (vertical and horizontal image DPI is different)");
255 static constexpr size_t ImageScaleUnitOffsetFromPosition = 2UL;
256 const auto imageScaleUnitIndex = positionIndex + ImageScaleUnitOffsetFromPosition;
257 const auto imageScaleUnit = isoImage[imageScaleUnitIndex];
258 static constexpr uint8_t ImageScaleUnitDPI = 1;
259 static constexpr uint8_t ImageScaleUnitDPCM = 2;
260 if (imageScaleUnit != ImageScaleUnitDPI && imageScaleUnit != ImageScaleUnitDPCM)
264 auto dpi =
ImageDpi{ imageHorizontalDpi };
265 if (imageScaleUnit == ImageScaleUnitDPCM)
277 static constexpr size_t ImageBitDepthOffsetFromPosition = 11UL;
278 const auto imagBitDepthIndex = positionIndex + ImageBitDepthOffsetFromPosition;
279 const auto imageBitDepth = isoImage[imagBitDepthIndex];
280 static constexpr uint8_t SupportedBitsPerPixel = 8;
282 static constexpr size_t ImageCompressionOffsetFromPosition = 12UL;
283 const auto imageCompressionIndex = positionIndex + ImageCompressionOffsetFromPosition;
284 const auto imageCompression = isoImage[imageCompressionIndex];
285 static constexpr uint8_t RawNotPackedImage = 0;
286 static constexpr uint8_t RawPackedImage = 1;
288 if (imageCompression == RawNotPackedImage || imageCompression == RawPackedImage)
290 if (imageBitDepth != SupportedBitsPerPixel)
295 static constexpr size_t ImageWidthOffsetFromPosition = 14UL;
296 const auto imagWidthIndex = positionIndex + ImageWidthOffsetFromPosition;
297 const ImageWidth imageWidth = (isoImage[imagWidthIndex] << 8U) + isoImage[imagWidthIndex + 1];
298 static constexpr size_t ImageHeightOffsetFromPosition = 16UL;
299 const auto imagHeightIndex = positionIndex + ImageHeightOffsetFromPosition;
300 const ImageHeight imageHeight = (isoImage[imagHeightIndex] << 8U) + isoImage[imagHeightIndex + 1];
323 const std::scoped_lock lock(presenceMux);
324 if (!presence.has_value())
326 uint8_t localPresence = 0;
328 auto gs =
image->AsRawGrayscale();
329 exec->CalculatePresence(gs.width,
331 static_cast<unsigned int>(gs.dpi),
336 presence = localPresence;
338 return presence.value();
351 const std::scoped_lock lock(nfiq1Mux);
352 if (!nfiq1.has_value())
354 uint8_t localNFIQ1 = 0;
356 auto gs =
image->AsRawGrayscale();
358 exec->CalculateNFIQ1(gs.width,
360 static_cast<unsigned int>(gs.dpi),
367 return nfiq1.value();
386 const std::scoped_lock lock(nfiq2Mux);
387 log.LogInfo(
"Calculating NFIQ2 for image %v",
image);
389 if (!nfiq2.has_value())
393 static constexpr const char* Msg =
"Image for NFIQ2 quality MUST have 500 DPI";
394 log.LogError(
"Calculating NFIQ2 for image %v failed '%s'",
image, Msg);
398 uint8_t localNFIQ2 = 0;
400 auto gs =
image->AsRawGrayscale();
402 exec->CalculateNFIQ2(gs.width,
404 static_cast<unsigned int>(gs.dpi),
411 log.LogInfo(
"Calculating NFIQ2 for image %v with result %d",
image, nfiq2.value());
412 return nfiq2.value();
425 const std::scoped_lock lock(imageQualityMux);
426 if (!imageQuality.has_value())
430 auto gs =
image->AsRawGrayscale();
432 exec->CalculateImageQuality(
433 gs.width, gs.height,
static_cast<unsigned int>(gs.dpi), gs.Data().data(), &quality, ThrowOnError{});
435 imageQuality = quality;
437 return imageQuality.value();
450 const std::scoped_lock lock(placementMux);
451 if (!placement.has_value())
453 uint8_t localPlacement = 0;
455 auto gs =
image->AsRawGrayscale();
457 exec->CalculatePlacement(gs.width,
459 static_cast<unsigned int>(gs.dpi),
464 placement = localPlacement;
466 return placement.value();
475 std::shared_ptr<PrintExecutor>& executor)
477 uint8_t intensity = 0;
479 const inno::RawImage rawImage =
image->AsRawGrayscale();
481 executor->GetImageIntensity(
482 rawImage.width, rawImage.height, rawImage.Data().data(), &intensity, ThrowOnError{});
497 const std::scoped_lock lock(intensityMux);
498 if (!intensity.has_value())
502 return intensity.value();
511 [[nodiscard]] std::shared_ptr<Image>
DrawMinutiae(
const std::vector<std::shared_ptr<Minutia>>& minutiae,
524 const std::vector<std::shared_ptr<CriticalPoint>>& points,
536 writer.Write(
"i",
image);
537 writer.Write(
"p",
static_cast<unsigned int>(
position));
540 const std::scoped_lock lock(presenceMux, nfiq1Mux, nfiq2Mux, imageQualityMux, placementMux, intensityMux);
542 if (presence.has_value())
544 writer.Write(
"pr", presence.value());
546 if (nfiq1.has_value())
548 writer.Write(
"n1", nfiq1.value());
550 if (nfiq2.has_value())
552 writer.Write(
"n2", nfiq2.value());
554 if (imageQuality.has_value())
556 writer.Write(
"iq", imageQuality.value());
558 if (placement.has_value())
560 writer.Write(
"pl", placement.value());
562 if (intensity.has_value())
564 writer.Write(
"in", intensity.value());
575 bool IsSameAs(
const Print& print)
const
577 return this == &print;
606 return !(*
this == f);
613 virtual ~Print() =
default;
626 static std::shared_ptr<Print>
Create(std::shared_ptr<Image> img,
631 return std::shared_ptr<Print>(
new Print(std::move(img),
position, pa, std::move(executor)));
635 std::shared_ptr<PrintExecutor> exec;
637 mutable std::mutex presenceMux;
638 mutable std::mutex nfiq1Mux;
639 mutable std::mutex nfiq2Mux;
640 mutable std::mutex imageQualityMux;
641 mutable std::mutex placementMux;
642 mutable std::mutex intensityMux;
644 std::optional<uint8_t> presence;
645 std::optional<uint8_t> nfiq1;
646 std::optional<uint8_t> nfiq2;
647 std::optional<uint8_t> imageQuality;
648 std::optional<uint8_t> placement;
649 std::optional<uint8_t> intensity;
651 Print(std::shared_ptr<Image> img,
654 std::shared_ptr<PrintExecutor> executor)
655 : image(std::move(img))
657 , printAttributes(std::move(pa))
658 , exec(std::move(executor))
666 if (image ==
nullptr)
668 throw NullArgumentException(
"Could not create Print due to image can not be null");
675 explicit IsoImage(
const Print& p)
680 ~IsoImage() =
default;
681 IsoImage(
const IsoImage&) =
delete;
682 IsoImage(IsoImage&&) =
delete;
683 IsoImage& operator=(
const IsoImage&) =
delete;
684 IsoImage& operator=(IsoImage&&) =
delete;
686 void SetCompressionType(uint8_t ct)
688 compressionType = ct;
691 std::vector<uint8_t> FillIsoImage(
const std::vector<uint8_t>& encodedImage)
693 static constexpr size_t GeneralHeaderLength = 16UL;
694 static constexpr size_t RepresentationHeaderLength = 41UL;
695 static constexpr size_t CertificationBlockSize = 1UL;
696 const size_t representationHeaderLength =
697 RepresentationHeaderLength +
698 (print.printAttributes.GetCertificationFlag() ? CertificationBlockSize : 0UL);
699 static constexpr size_t RepresentationBodyExtraDataLength = 0;
702 auto imageLength = encodedImage.size();
705 auto representationLength =
706 representationHeaderLength + imageLength + RepresentationBodyExtraDataLength;
709 auto recordLength = GeneralHeaderLength + representationLength;
711 std::vector<uint8_t> isoImage;
712 isoImage.resize(recordLength);
714 FillGeneralHeader(isoImage, recordLength);
715 FillRepresentationHeader(isoImage, representationLength, imageLength);
716 FillRepresentationBody(isoImage, encodedImage);
722 size_t writeIndex = 0;
724 static void ThrowWhenValueCannotFitInto4Bytes(
size_t recordLength)
726 if (recordLength >
static_cast<size_t>(std::numeric_limits<uint32_t>::max()))
728 throw EnrollmentRuntimeException(
"Invalid conversion size");
740 void FillGeneralHeader(std::vector<uint8_t>& isoImage,
const size_t recordLength)
742 FillFormatIdentifier(isoImage);
743 FillVersionNumber(isoImage);
744 FillLengthOfRecord(isoImage, recordLength);
745 FillNumberOfFingerPalmRepresentations(isoImage);
746 FillCertificationFlag(isoImage);
747 FillNumberOfDistinctFingerPalmPositions(isoImage);
756 void FillFormatIdentifier(std::vector<uint8_t>& isoImage)
759 isoImage[writeIndex++] =
'F';
760 isoImage[writeIndex++] =
'I';
761 isoImage[writeIndex++] =
'R';
762 isoImage[writeIndex++] =
'\0';
774 void FillVersionNumber(std::vector<uint8_t>& isoImage)
777 isoImage[writeIndex++] =
'0';
778 isoImage[writeIndex++] =
'2';
779 isoImage[writeIndex++] =
'0';
780 isoImage[writeIndex++] =
'\0';
792 void FillLengthOfRecord(std::vector<uint8_t>& isoImage,
const size_t recordLength)
794 ThrowWhenValueCannotFitInto4Bytes(recordLength);
797 isoImage[writeIndex++] =
static_cast<uint8_t
>(recordLength >> ThreeBytesBitsCount);
798 isoImage[writeIndex++] =
static_cast<uint8_t
>((recordLength >> ThreeBytesBitsCount) & ByteMask);
799 isoImage[writeIndex++] =
static_cast<uint8_t
>((recordLength >> OneByteBitsCount) & ByteMask);
800 isoImage[writeIndex++] =
static_cast<uint8_t
>(recordLength & ByteMask);
810 void FillNumberOfFingerPalmRepresentations(std::vector<uint8_t>& isoImage)
813 isoImage[writeIndex++] = 0x00;
814 isoImage[writeIndex++] = 0x01;
825 void FillCertificationFlag(std::vector<uint8_t>& isoImage)
827 isoImage[writeIndex++] = print.printAttributes.GetCertificationFlag() ? 1 : 0;
837 void FillNumberOfDistinctFingerPalmPositions(std::vector<uint8_t>& isoImage)
839 isoImage[writeIndex++] = 0x01;
855 void FillRepresentationHeader(std::vector<uint8_t>& isoImage,
856 size_t representationLength,
859 FillRepresentationLength(isoImage, representationLength);
860 FillCaptureDateTime(isoImage);
861 FillCaptureDeviceTechnologyIdentifier(isoImage);
862 FillCaptureDeviceVendorIdentifier(isoImage);
863 FillCaptureDeviceTypeIdentifier(isoImage);
864 FillNumberOfQualityBlocks(isoImage);
865 FillCaptureDeviceCertifications(isoImage);
866 FillFingerPalmPosition(isoImage);
867 FillRepresentationNumber(isoImage);
868 FillScaleUnits(isoImage);
869 FillCaptureDeviceSpatialHorizontalSamplingRate(isoImage);
870 FillCaptureDeviceSpatialVerticalSamplingRate(isoImage);
871 FillImageSpatialHorizontalSamplingRate(isoImage);
872 FillImageSpatialVerticalSamplingRate(isoImage);
873 FillBitDepth(isoImage);
874 FillImageCompressionAlgorithm(isoImage);
875 FillImpressionType(isoImage);
876 FillHorizontalLineLength(isoImage);
877 FillVerticalLineLength(isoImage);
878 FillImageDataLength(isoImage, imageLength);
889 void FillRepresentationLength(std::vector<uint8_t>& isoImage,
size_t representationLength)
891 ThrowWhenValueCannotFitInto4Bytes(representationLength);
894 isoImage[writeIndex++] =
static_cast<uint8_t
>(representationLength >> ThreeBytesBitsCount);
895 isoImage[writeIndex++] =
static_cast<uint8_t
>((representationLength >> ThreeBytesBitsCount) & ByteMask);
896 isoImage[writeIndex++] =
static_cast<uint8_t
>((representationLength >> OneByteBitsCount) & ByteMask);
897 isoImage[writeIndex++] =
static_cast<uint8_t
>(representationLength & ByteMask);
908 void FillCaptureDateTime(std::vector<uint8_t>& isoImage)
911 static constexpr uint8_t DummyValue = 0xff;
912 isoImage[writeIndex++] = DummyValue;
913 isoImage[writeIndex++] = DummyValue;
914 isoImage[writeIndex++] = DummyValue;
915 isoImage[writeIndex++] = DummyValue;
916 isoImage[writeIndex++] = DummyValue;
917 isoImage[writeIndex++] = DummyValue;
918 isoImage[writeIndex++] = DummyValue;
919 isoImage[writeIndex++] = DummyValue;
920 isoImage[writeIndex++] = DummyValue;
931 void FillCaptureDeviceTechnologyIdentifier(std::vector<uint8_t>& isoImage)
934 isoImage[writeIndex++] =
946 void FillCaptureDeviceVendorIdentifier(std::vector<uint8_t>& isoImage)
949 const PrintCaptureDeviceVendorID vendor = print.printAttributes.GetCaptureDeviceVendorID();
950 isoImage[writeIndex++] =
static_cast<uint8_t
>(
static_cast<unsigned int>(vendor) >> OneByteBitsCount);
951 isoImage[writeIndex++] =
static_cast<uint8_t
>(
static_cast<unsigned int>(vendor) & ByteMask);
961 void FillCaptureDeviceTypeIdentifier(std::vector<uint8_t>& isoImage)
964 const PrintCaptureDeviceTypeID type = print.printAttributes.GetCaptureDeviceTypeID();
965 isoImage[writeIndex++] =
static_cast<uint8_t
>(
static_cast<unsigned int>(type) >> OneByteBitsCount);
966 isoImage[writeIndex++] =
static_cast<uint8_t
>(
static_cast<unsigned int>(type) & ByteMask);
977 void FillNumberOfQualityBlocks(std::vector<uint8_t>& isoImage)
979 isoImage[writeIndex++] = 0x00;
986 void FillQualityBlockData(std::vector<uint8_t>& isoImage)
989 FillQualityScore(isoImage);
990 FillQualityAlgorithmVendorId(isoImage);
991 FillQualityAlgorithmId(isoImage);
1003 void FillQualityScore(std::vector<uint8_t>& isoImage)
1005 isoImage[writeIndex++] = 0x00;
1016 void FillQualityAlgorithmVendorId(std::vector<uint8_t>& isoImage)
1019 isoImage[writeIndex++] = 0x00;
1020 isoImage[writeIndex++] = 0x00;
1032 void FillQualityAlgorithmId(std::vector<uint8_t>& isoImage)
1035 isoImage[writeIndex++] = 0x00;
1036 isoImage[writeIndex++] = 0x00;
1049 void FillCaptureDeviceCertifications(std::vector<uint8_t>& isoImage)
1051 FillNumberOfCertificationBlocks(isoImage);
1060 void FillNumberOfCertificationBlocks(std::vector<uint8_t>& isoImage)
1063 if (print.printAttributes.GetCertificationFlag())
1065 isoImage[writeIndex++] = 0x00;
1076 void FillCertificationBlocks(std::vector<uint8_t>& isoImage)
1079 isoImage[writeIndex++] = 0x00;
1080 isoImage[writeIndex++] = 0x00;
1089 void FillCertificationSchemeIdentifier(std::vector<uint8_t>& isoImage)
1091 isoImage[writeIndex++] = 0x00;
1099 void FillFingerPalmPosition(std::vector<uint8_t>& isoImage)
1111 void FillRepresentationNumber(std::vector<uint8_t>& isoImage)
1113 isoImage[writeIndex++] = 0x00;
1123 void FillScaleUnits(std::vector<uint8_t>& isoImage)
1125 isoImage[writeIndex++] = 0x01;
1135 void FillCaptureDeviceSpatialHorizontalSamplingRate(std::vector<uint8_t>& isoImage)
1138 isoImage[writeIndex++] =
1139 static_cast<uint8_t
>(
static_cast<unsigned int>(print.image->Dpi()) >> OneByteBitsCount);
1140 isoImage[writeIndex++] =
static_cast<uint8_t
>(
static_cast<unsigned int>(print.image->Dpi()) & ByteMask);
1150 void FillCaptureDeviceSpatialVerticalSamplingRate(std::vector<uint8_t>& isoImage)
1153 isoImage[writeIndex++] =
1154 static_cast<uint8_t
>(
static_cast<unsigned int>(print.image->Dpi()) >> OneByteBitsCount);
1155 isoImage[writeIndex++] =
static_cast<uint8_t
>(
static_cast<unsigned int>(print.image->Dpi()) & ByteMask);
1166 void FillImageSpatialHorizontalSamplingRate(std::vector<uint8_t>& isoImage)
1169 isoImage[writeIndex++] =
1170 static_cast<uint8_t
>(
static_cast<unsigned int>(print.image->Dpi()) >> OneByteBitsCount);
1171 isoImage[writeIndex++] =
static_cast<uint8_t
>(
static_cast<unsigned int>(print.image->Dpi()) & ByteMask);
1182 void FillImageSpatialVerticalSamplingRate(std::vector<uint8_t>& isoImage)
1185 isoImage[writeIndex++] =
1186 static_cast<uint8_t
>(
static_cast<unsigned int>(print.image->Dpi()) >> OneByteBitsCount);
1187 isoImage[writeIndex++] =
static_cast<uint8_t
>(
static_cast<unsigned int>(print.image->Dpi()) & ByteMask);
1196 void FillBitDepth(std::vector<uint8_t>& isoImage)
1198 static constexpr uint8_t BitsPerPixel = 8;
1199 isoImage[writeIndex++] = BitsPerPixel;
1216 void FillImageCompressionAlgorithm(std::vector<uint8_t>& isoImage)
1218 isoImage[writeIndex++] = compressionType;
1229 void FillImpressionType(std::vector<uint8_t>& isoImage)
1231 isoImage[writeIndex++] =
1241 void FillHorizontalLineLength(std::vector<uint8_t>& isoImage)
1244 isoImage[writeIndex++] =
static_cast<uint8_t
>(print.image->Width() >> OneByteBitsCount);
1245 isoImage[writeIndex++] =
static_cast<uint8_t
>(print.image->Width() & ByteMask);
1254 void FillVerticalLineLength(std::vector<uint8_t>& isoImage)
1257 isoImage[writeIndex++] =
static_cast<uint8_t
>(print.image->Height() >> OneByteBitsCount);
1258 isoImage[writeIndex++] =
static_cast<uint8_t
>(print.image->Height() & ByteMask);
1270 void FillImageDataLength(std::vector<uint8_t>& isoImage,
size_t imageLength)
1272 ThrowWhenValueCannotFitInto4Bytes(imageLength);
1275 isoImage[writeIndex++] =
static_cast<uint8_t
>(imageLength >> ThreeBytesBitsCount);
1276 isoImage[writeIndex++] =
static_cast<uint8_t
>((imageLength >> ThreeBytesBitsCount) & ByteMask);
1277 isoImage[writeIndex++] =
static_cast<uint8_t
>((imageLength >> OneByteBitsCount) & ByteMask);
1278 isoImage[writeIndex++] =
static_cast<uint8_t
>(imageLength & ByteMask);
1288 void FillRepresentationBody(std::vector<uint8_t>& isoImage,
const std::vector<uint8_t>& encodedImage)
1290 FillImageData(isoImage, encodedImage);
1291 FillExtendedDataBlocks(isoImage);
1301 void FillImageData(std::vector<uint8_t>& isoImage,
const std::vector<uint8_t>& encodedImage)
1303 std::copy(encodedImage.begin(),
1305 std::next(isoImage.begin(),
static_cast<ptrdiff_t
>(writeIndex)));
1306 writeIndex += encodedImage.size();
1320 void FillExtendedDataBlocks(std::vector<uint8_t>& )
1337 void FillTypeIdentificationCode(std::vector<uint8_t>& isoImage)
1340 isoImage[writeIndex++] = 0x00;
1341 isoImage[writeIndex++] = 0x00;
1353 void FillLengthOfData(std::vector<uint8_t>& isoImage)
1356 isoImage[writeIndex++] = 0x00;
1357 isoImage[writeIndex++] = 0x00;
1368 void FillDataSection(std::vector<uint8_t>& isoImage)
1370 isoImage[writeIndex++] = 0x00;
1374 static constexpr uint8_t RawCompressionType = 0;
1375 uint8_t compressionType = RawCompressionType;
1376 static constexpr unsigned int OneByteBitsCount = 8U;
1377 static constexpr unsigned int TwoBytesBitsCount = 16U;
1378 static constexpr unsigned int ThreeBytesBitsCount = 24U;
1379 static constexpr unsigned int ByteMask = 0xffU;
1382 class IsoImageEncoder :
public ImageEncoderVisitor
1392 std::vector<uint8_t> Encode()
1395 encoder.Accept(*
this);
1398 auto encodedImage = print.image->EncodeIn(encoder);
1400 return isoImage.FillIsoImage(encodedImage);
1403 void Visit(
const WsqImageEncoder& )
final
1406 static constexpr uint8_t WsqCompression = 2;
1407 isoImage.SetCompressionType(WsqCompression);
1410 void Visit(
const JpgImageEncoder& )
final
1413 static constexpr uint8_t JpgCompression = 3;
1414 isoImage.SetCompressionType(JpgCompression);
1417 void Visit(
const Jp2ImageEncoder& jp2Encoder)
final
1419 if (jp2Encoder.IsLossy())
1422 static constexpr uint8_t Jp2Lossy = 4;
1423 isoImage.SetCompressionType(Jp2Lossy);
1428 static constexpr uint8_t Jp2Lossless = 5;
1429 isoImage.SetCompressionType(Jp2Lossless);
1433 void Visit(
const PngImageEncoder& )
final
1436 static constexpr uint8_t PngCompression = 6;
1437 isoImage.SetCompressionType(PngCompression);
1440 void Visit(
const IRawImageEncoder& )
final
1442 throw EnrollmentInvalidArgumentException(
"Could not create ISO image for IRAW image format");
1445 void Visit(
const BmpImageEncoder& )
final
1447 throw EnrollmentInvalidArgumentException(
"Could not create ISO image for BMP image format");
1450 void Visit(
const TiffImageEncoder& )
final
1452 throw EnrollmentInvalidArgumentException(
"Could not create ISO image for TIFF image format");
1455 void Visit(
const WebpImageEncoder& )
final
1457 throw EnrollmentInvalidArgumentException(
"Could not create ISO image for WEBP image format");
1462 IsoImageEncoder(
const Print& p, ImageEncoder& e)
1465 , isoImage(IsoImage(p))
1468 IsoImageEncoder() =
delete;
1469 virtual ~IsoImageEncoder() =
default;
1470 IsoImageEncoder(
const IsoImageEncoder&) =
delete;
1471 IsoImageEncoder(IsoImageEncoder&&) =
delete;
1472 IsoImageEncoder& operator=(
const IsoImageEncoder&) =
delete;
1473 IsoImageEncoder& operator=(IsoImageEncoder&&) =
delete;
1477 ImageEncoder& encoder;