YSTest: Image.cpp 源文件

YSTest PreAlpha_b800_20170810 The YSLib Test Project

- 首页
- 相关页面
- 模块
- 命名空间
- 类
- 文件

- 文件列表
- 文件成员

Image.cpp
浏览该文件的文档.
1 /*
2 © 2013-2016 FrankHB.
3
4 This file is part of the YSLib project, and may only be used,
5 modified, and distributed under the terms of the YSLib project
6 license, LICENSE.TXT. By continuing to use, modify, or distribute
7 this file you indicate that you have read the license and
8 understand and accept it fully.
9 */
10
28 #include "YSLib/Service/YModules.h"
29 #include "CHRLib/YModules.h"
30 #include YFM_YSLib_Adaptor_Image // for Timers::TimeSpan,
31 // ystdex::aligned_store_cast;
32 #include <FreeImage.h>
33 #include YFM_YSLib_Service_YBlit
34 #include YFM_YSLib_Service_YGDI
35 #include YFM_CHRLib_CharacterProcessing // for CHRLib::ToASCII;
36
37 namespace YSLib
38 {
39
41 using Timers::TimeSpan;
42
43 namespace Drawing
44 {
45
47 static_assert(int(SamplingFilter::Box) == ::FILTER_BOX
48 && int(SamplingFilter::Bicubic) == ::FILTER_BICUBIC
49 && int(SamplingFilter::Bilinear) == ::FILTER_BILINEAR
50 && int(SamplingFilter::BSpline) == ::FILTER_BSPLINE
51 && int(SamplingFilter::CatmullRom) == ::FILTER_CATMULLROM
52 && int(SamplingFilter::Lanczos3) == ::FILTER_LANCZOS3,
53 "Incompatible filter found.");
54
56 namespace
57 {
58
60 void DLL_CALLCONV
61 FI_OutputMessage(::FREE_IMAGE_FORMAT fif, const char* msg)
62 {
63 YTraceDe(Warning, "FreeImage failed, format = %d: %s.", int(fif), msg);
64
65 yunused(fif),
66 yunused(msg);
67 }
68
69 ::FreeImageIO u8_io{
70 [](void *buffer, unsigned size, unsigned nmemb, fi_handle h) ynothrow{
71 return unsigned(std::fread(buffer, size_t(size),
72 size_t(nmemb), static_cast<std::FILE*>(h)));
73 },
74 [](void *buffer, unsigned size, unsigned nmemb, fi_handle h) ynothrow{
75 return unsigned(std::fwrite(buffer, size_t(size),
76 size_t(nmemb), static_cast<std::FILE*>(h)));
77 },
78 [](::fi_handle h, long offset, int whence) ynothrow{
79 return std::fseek(static_cast<std::FILE*>(h), offset, whence);
80 },
81 [](::fi_handle h) ynothrow{
82 return std::ftell(static_cast<std::FILE*>(h));
83 }
84 };
85
87
88 ::FIBITMAP*
89 LoadImage(ImageFormat fmt, std::FILE* fp, ImageDecoderFlags flags)
90 {
91 if(fp)
92 {
93 const auto bitmap(::FreeImage_LoadFromHandle(::FREE_IMAGE_FORMAT(fmt),
94 &u8_io, ::fi_handle(fp), int(flags)));
95
96 std::fclose(fp);
97 if(bitmap)
98 return bitmap;
99 throw GeneralEvent("Loading image failed.");
100 }
101 throw std::invalid_argument("Invalid file found on loading image.");
102 }
103 ::FIBITMAP*
104 LoadImage(ImageFormat fmt, const char* filename, ImageDecoderFlags flags)
105 {
106 return LoadImage(fmt, ufopen(filename, "rb"), flags);
107 }
108 ::FIBITMAP*
109 LoadImage(ImageFormat fmt, const char16_t* filename, ImageDecoderFlags flags)
110 {
111 return LoadImage(fmt, ufopen(filename, u"rb"), flags);
112 }
114
116
117 void
118 SaveImage(ImageFormat fmt, ::FIBITMAP* dib, std::FILE* fp,
119 ImageDecoderFlags flags)
120 {
121 if(dib)
122 {
123 const bool res(::FreeImage_SaveToHandle(::FREE_IMAGE_FORMAT(fmt),
124 dib, &u8_io, ::fi_handle(fp), int(flags)));
125
126 std::fclose(fp);
127 if(!res)
128 throw GeneralEvent("Failed saving image");
129 }
130 throw std::invalid_argument("No valid bitmap data found on saving image.");
131 }
132 void
133 SaveImage(ImageFormat fmt, ::FIBITMAP* dib, const char* filename,
134 ImageDecoderFlags flags)
135 {
136 SaveImage(fmt, dib, ufopen(filename, "wb"), flags);
137 }
138 void
139 SaveImage(ImageFormat fmt, ::FIBITMAP* dib, const char16_t* filename,
140 ImageDecoderFlags flags)
141 {
142 SaveImage(fmt, dib, ufopen(filename, u"wb"), flags);
143 }
145
147
148 ImageFormat
149 GetFileType(std::FILE* fp)
150 {
151 if(fp)
152 {
153 const auto
154 fif(::FreeImage_GetFileTypeFromHandle(&u8_io, ::fi_handle(fp)));
155
156 std::fclose(fp);
157 return ImageFormat(fif);
158 }
159 return ImageFormat::Unknown;
160 }
161 ImageFormat
162 GetFileType(const char* filename)
163 {
164 return GetFileType(ufopen(filename, "rb"));
165 }
166 ImageFormat
167 GetFileType(const char16_t* filename)
168 {
169 return GetFileType(ufopen(filename, u"rb"));
170 }
172
173 ImageFormat
174 GetFormatFromFilename(const char16_t* filename)
175 {
176 const auto len(ystdex::ntctslen(filename));
177 const auto p_buf(make_unique_default_init<char[]>(len + 1));
178 const auto str(p_buf.get());
179
180 for(size_t i{}; i < len; ++i)
181 str[i] = CHRLib::ToASCII(filename[i]);
182 str[len] = char();
183 return ImageFormat(::FreeImage_GetFIFFromFilename(str));
184 }
185
186 ::FI_PluginRec&
187 LookupPlugin(::FREE_IMAGE_FORMAT fif)
188 {
189 if(const auto p_node = ::FreeImageEx_GetPluginNodeFromFIF(fif))
190 {
191 if(const auto p_plugin = p_node->m_plugin)
192 return *p_plugin;
193 else
194 throw GeneralEvent("Invalid plugin node found.");
195 }
196 else
197 throw GeneralEvent("No proper plugin found.");
198 }
199
200
201 #if (YCL_PIXEL_FORMAT_XYZ555 & 0x00FFFFFF) == 0x00BBCCDD
202 # define YF_PixConvSpec \
203 16, FI16_555_RED_MASK, FI16_555_GREEN_MASK, FI16_555_BLUE_MASK
204 #elif (YCL_PIXEL_FORMAT_XYZ555 & 0x00FFFFFF) == 0x00DDCCBB
205 # define YF_PixConvSpec \
206 16, FI16_555_BLUE_MASK, FI16_555_GREEN_MASK, FI16_555_RED_MASK
207 //#elif (YCL_PIXEL_FORMAT_XYZ555 & 0x00FFFFFF) == 0x00DDCCBB
208 #elif (YCL_PIXEL_FORMAT_XYZ888 & 0x00FFFFFF) == 0x00BBCCDD
209 # define YF_PixConvSpec \
210 32, FI_RGBA_BLUE_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_RED_MASK
211 #elif (YCL_PIXEL_FORMAT_XYZ888 & 0x00FFFFFF) == 0x00DDCCBB
212 # define YF_PixConvSpec \
213 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK
214 # if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
215 //# elif FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB
216 // TODO: Add support for different color orders.
217 # else
218 # error "No supported FreeImage pixel format found."
219 # endif
220 #else
221 # error "Unsupported pixel format found."
222 #endif
223
224 } // unnamed namespace;
225
226
227 ImplDeDtor(BadImageAlloc)
228
229
230 ImplDeDtor(UnsupportedImageFormat)
231
232
233 ImplDeDtor(UnknownImageFormat)
234
235
236 void
237 ImageMemory::Deleter::operator()(pointer p) const ynothrow
238 {
239 ::FreeImage_CloseMemory(p);
240 }
241
242
243 ImageMemory::ImageMemory(const HBitmap& pixmap, ImageFormat fmt,
244 ImageDecoderFlags flags)
245 : buffer(), format([=]{
246 if(fmt == ImageFormat::Unknown)
247 throw UnknownImageFormat("Unknown image format found when saving.");
248 return fmt;
249 }()), p_memory([&]{
250 if(!pixmap.GetDataPtr())
251 throw GeneralEvent("Source image is empty.");
252 return ::FreeImage_OpenMemory();
253 }())
254 {
255 if(p_memory)
256 {
257 if(!::FreeImage_SaveToMemory(::FREE_IMAGE_FORMAT(format),
258 pixmap.GetDataPtr().get(), GetNativeHandle(), int(flags)))
259 throw GeneralEvent("Saving image to memory failed.");
260 }
261 else
262 throw BadImageAlloc();
263 }
264 ImageMemory::ImageMemory(Buffer buf)
265 : ImageMemory(std::move(buf), ImageFormat::Unknown)
266 {
267 format = ImageCodec::DetectFormat(GetNativeHandle(), buffer.size());
268 }
269 ImageMemory::ImageMemory(Buffer buf, ImageFormat fmt)
270 : buffer([&]{
271 if(buf.empty())
272 throw GeneralEvent("Null buffer found.");
273 return std::move(buf);
274 }()), format(fmt),
275 p_memory(::FreeImage_OpenMemory(static_cast<byte*>(buffer.data()),
276 static_cast<unsigned long>(buffer.size())))
277 {
278 if(!p_memory)
279 throw GeneralEvent("Opening image memory failed.");
280 }
281
282
283 void
284 HBitmap::Deleter::operator()(pointer p) const ynothrow
285 {
286 ::FreeImage_Unload(p);
287 }
288
289
290 HBitmap::HBitmap(const Size& s, BitPerPixel bpp)
291 : p_bitmap(::FreeImage_Allocate(CheckArithmetic<int>(s.Width),
292 CheckArithmetic<int>(s.Height), bpp, 0, 0, 0))
293 {
294 if(!p_bitmap)
295 throw BadImageAlloc();
296 }
297 HBitmap::HBitmap(BitmapPtr src, const Size& s, size_t pitch_delta)
298 : p_bitmap([&]{
299 return ::FreeImage_ConvertFromRawBits(ystdex::aligned_store_cast<byte*>(
300 Nonnull(src)), CheckArithmetic<int>(s.Width),
301 CheckArithmetic<int>(s.Height), CheckArithmetic<int>(
302 s.Width * sizeof(Pixel) + pitch_delta), YF_PixConvSpec, true);
303 }())
304 {
305 if(!p_bitmap)
306 throw GeneralEvent("Converting compact pixmap failed.");
307 }
308 HBitmap::HBitmap(const CompactPixmap& buf)
309 : HBitmap(buf.GetBufferPtr(), buf.GetSize())
310 {}
311 HBitmap::HBitmap(const char* filename, ImageDecoderFlags flags)
312 : HBitmap(filename, ImageCodec::DetectFormat(filename), flags)
313 {}
314 HBitmap::HBitmap(const char* filename, ImageFormat fmt, ImageDecoderFlags flags)
315 : p_bitmap(Nonnull(LoadImage(fmt, filename, flags)))
316 {}
317 HBitmap::HBitmap(const char16_t* filename, ImageDecoderFlags flags)
318 : HBitmap(filename, ImageCodec::DetectFormat(filename), flags)
319 {}
320 HBitmap::HBitmap(const char16_t* filename, ImageFormat fmt,
321 ImageDecoderFlags flags)
322 : p_bitmap(Nonnull(LoadImage(fmt, filename, flags)))
323 {}
324 HBitmap::HBitmap(const ImageMemory& mem, ImageDecoderFlags flags)
325 : p_bitmap(::FreeImage_LoadFromMemory(::FREE_IMAGE_FORMAT(mem.GetFormat()),
326 mem.GetNativeHandle(), int(flags)))
327 {
328 if(!p_bitmap)
329 throw GeneralEvent("Loading image failed.");
330 }
331 HBitmap::HBitmap(const HBitmap& pixmap, BitPerPixel bpp)
332 : p_bitmap([bpp](::FIBITMAP* p_bmp){
333 switch(bpp)
334 {
335 case 32:
336 return FreeImage_ConvertTo32Bits(p_bmp);
337 case 24:
338 return FreeImage_ConvertTo24Bits(p_bmp);
339 case 16:
340 return FreeImage_ConvertTo16Bits555(p_bmp);
341 case 8:
342 return FreeImage_ConvertTo8Bits(p_bmp);
343 case 4:
344 return FreeImage_ConvertTo4Bits(p_bmp);
345 default:
346 throw UnsupportedImageFormat("Unsupported bit per pixel found.");
347 }
348 }(pixmap.p_bitmap.get()))
349 {
350 if(!p_bitmap)
351 throw GeneralEvent("Converting bitmap failed.");
352 }
353 HBitmap::HBitmap(const HBitmap& pixmap, const Size& s, SamplingFilter sf)
354 : p_bitmap(::FreeImage_Rescale(pixmap.p_bitmap.get(),
355 CheckArithmetic<int>(s.Width), CheckArithmetic<int>(s.Height),
356 ::FREE_IMAGE_FILTER(sf)))
357 {
358 if(!p_bitmap)
359 throw GeneralEvent("Rescaling image failed.");
360 }
361 HBitmap::HBitmap(const HBitmap& pixmap)
362 : p_bitmap(::FreeImage_Clone(pixmap.p_bitmap.get()))
363 {
364 if(!p_bitmap)
365 throw BadImageAlloc();
366 }
367
368 byte*
369 HBitmap::operator[](size_t idx) const ynothrowv
370 {
371 YAssertNonnull(*this);
372 YAssert(idx < GetHeight(), "Index is out of range.");
373 return ::FreeImage_GetScanLine(Nonnull(p_bitmap.get()), int(idx));
374 }
375
376 HBitmap::operator CompactPixmap() const
377 {
378 const Size& s(GetSize());
379 // XXX: Depends right behavior on external API.
380 auto pixels(make_unique_default_init<Pixel[]>(size_t(GetAreaOf(s))));
381
382 ::FreeImage_ConvertToRawBits(ystdex::aligned_store_cast<byte*>(&pixels[0]),
383 GetDataPtr().get(), CheckArithmetic<int>(s.Width * sizeof(Pixel)),
384 YF_PixConvSpec, true);
385 return CompactPixmap(std::move(pixels), s);
386 }
387
388 BitPerPixel
389 HBitmap::GetBPP() const ynothrow
390 {
391 return ::FreeImage_GetBPP(p_bitmap.get());
392 }
393 SDst
394 HBitmap::GetHeight() const ynothrow
395 {
396 return ::FreeImage_GetHeight(p_bitmap.get());
397 }
398 SDst
399 HBitmap::GetPitch() const ynothrow
400 {
401 return ::FreeImage_GetPitch(p_bitmap.get());
402 }
403 byte*
404 HBitmap::GetPixels() const ynothrow
405 {
406 return ::FreeImage_GetBits(p_bitmap.get());
407 }
408 SDst
409 HBitmap::GetWidth() const ynothrow
410 {
411 return ::FreeImage_GetWidth(p_bitmap.get());
412 }
413
414 HBitmap::Deleter::pointer
415 HBitmap::Release() ynothrow
416 {
417 return p_bitmap.release();
418 }
419
420 void
421 HBitmap::Rescale(const Size& s, SamplingFilter sf)
422 {
423 *this = HBitmap(*this, s, sf);
424 }
425
426 void
427 HBitmap::SaveTo(const char* filename, ImageFormat fmt, ImageDecoderFlags flags)
428 const
429 {
430 SaveImage(fmt, GetDataPtr().get(), filename, flags);
431 }
432 void
433 HBitmap::SaveTo(const char16_t* filename, ImageFormat fmt,
434 ImageDecoderFlags flags) const
435 {
436 SaveImage(fmt, GetDataPtr().get(), filename, flags);
437 }
438
439 TimeSpan
440 GetFrameTimeOf(const HBitmap& bmp)
441 {
442 return TimeSpan(CheckNonnegative<long>(ImageTag(bmp,
443 ImageMetadataModel::Animation, "FrameTime").GetValue<long>(),
444 "frame time", Warning));
445 }
446
447 Size
448 GetLogicalSizeOf(const HBitmap& bmp)
449 {
450 return {CheckPositive<SDst>(ImageTag(bmp, ImageMetadataModel::Animation,
451 "LogicalWidth").GetValue<short>(), "logical width", Warning),
452 CheckPositive<SDst>(ImageTag(bmp, ImageMetadataModel::Animation,
453 "LogicalHeight").GetValue<short>(), "logical height", Warning)};
454 }
455
456
457 class MultiBitmapData final : private noncopyable
458 {
459 private:
460 bool read;
461 ::fi_handle handle;
462 int load_flags;
464 lref<::FreeImageIO> io_ref;
466 lref<::FI_PluginRec> plugin_ref;
467 size_t page_count = 1;
468 void* data = {};
469
470 public:
472 MultiBitmapData(::fi_handle, int, ::FI_PluginRec&, ::FreeImageIO& = u8_io,
473 bool = true);
475 MultiBitmapData(ImageFormat, std::FILE&, int = 0, ::FreeImageIO& = u8_io,
476 bool = true);
478 ~MultiBitmapData();
479
480 DefPred(const ynothrow, OpenForRead, read)
481
482 DefGetter(const ynothrow, size_t, PageCount, page_count)
483
485 observer_ptr<::FIBITMAP>
486 LockPage(size_t = 0) const ynothrow;
487 };
488
489 MultiBitmapData::MultiBitmapData(::fi_handle h, int flags,
490 ::FI_PluginRec& plugin, ::FreeImageIO& io, bool open_for_reading)
491 : read(open_for_reading), handle(h), load_flags(flags), io_ref(io),
492 plugin_ref(plugin)
493 {
494 io.seek_proc(handle, 0, SEEK_SET);
495 if(const auto open = plugin.open_proc)
496 {
497 data = open(&io_ref.get(), handle, open_for_reading);
498 if(const auto proc = plugin_ref.get().pagecount_proc)
499 {
500 const int cnt(proc(&io_ref.get(), handle, data));
501
502 if(cnt > 0)
503 page_count = size_t(cnt);
504 }
505 }
506 }
507 MultiBitmapData::MultiBitmapData(ImageFormat fmt, std::FILE& f, int flags,
508 ::FreeImageIO& io, bool open_for_reading)
509 : MultiBitmapData(::fi_handle(&f), flags,
510 LookupPlugin(::FREE_IMAGE_FORMAT(fmt)), io, open_for_reading)
511 {}
512 MultiBitmapData::~MultiBitmapData()
513 {
514 if(const auto close = plugin_ref.get().close_proc)
515 close(&io_ref.get(), handle, data);
516 }
517
518 observer_ptr<::FIBITMAP>
519 MultiBitmapData::LockPage(size_t index) const ynothrow
520 {
521 YAssert(index < page_count, sfmt("Invalid page index %zu found, should be"
522 " less than %zu.", index, page_count).c_str());
523 if(const auto load = plugin_ref.get().load_proc)
524 return make_observer(load(&io_ref.get(), handle, int(index), load_flags,
525 data));
526 return {};
527 }
528
529
531 namespace
532 {
533
535
536 MultiBitmapData*
537 LoadImagePages(ImageFormat fmt, std::FILE* fp, ImageDecoderFlags flags)
538 {
539 if(fp)
540 TryRet(new MultiBitmapData(fmt, *fp, int(flags)))
541 CatchThrow(std::bad_alloc&, BadImageAlloc())
542 throw std::invalid_argument("Invalid file found on loading image pages.");
543 }
544 MultiBitmapData*
545 LoadImagePages(ImageFormat fmt, const char* filename, ImageDecoderFlags flags)
546 {
547 return LoadImagePages(fmt, ufopen(filename, "rb"), flags);
548 }
549 MultiBitmapData*
550 LoadImagePages(ImageFormat fmt, const char16_t* filename,
551 ImageDecoderFlags flags)
552 {
553 return LoadImagePages(fmt, ufopen(filename, u"rb"), flags);
554 }
556
557 } // unnamed namespace;
558
559
560 HMultiBitmap::HMultiBitmap(const char* filename, ImageDecoderFlags flags)
561 : HMultiBitmap(filename, ImageCodec::DetectFormat(filename), flags)
562 {}
563 HMultiBitmap::HMultiBitmap(const char* filename, ImageFormat fmt,
564 ImageDecoderFlags flags)
565 : pages(Nonnull(LoadImagePages(fmt, filename, flags)))
566 {}
567 HMultiBitmap::HMultiBitmap(const char16_t* filename, ImageDecoderFlags flags)
568 : HMultiBitmap(filename, ImageCodec::DetectFormat(filename), flags)
569 {}
570 HMultiBitmap::HMultiBitmap(const char16_t* filename, ImageFormat fmt,
571 ImageDecoderFlags flags)
572 : pages(Nonnull(LoadImagePages(fmt, filename, flags)))
573 {}
574
575 size_t
576 HMultiBitmap::GetPageCount() const ynothrow
577 {
578 return pages ? pages->GetPageCount() : 0;
579 }
580
581 HBitmap
582 HMultiBitmap::Lock(size_t i) const ynothrowv
583 {
584 return pages ? pages->LockPage(i) : nullptr;
585 }
586
587
588 ImageTag::ImageTag(const ImageTag& tag) ythrow(BadImageAlloc)
589 : p_tag(::FreeImage_CloneTag(tag.p_tag)), owns(true)
590 {
591 if(bool(p_tag) != bool(tag.p_tag))
592 throw BadImageAlloc();
593 }
594 ImageTag::ImageTag(HBitmap::DataPtr p_bmp, ImageMetadataModel model,
595 const char* name)
596 : p_tag([=]{
597 YAssertNonnull(name);
598 if(!p_bmp)
599 throw std::invalid_argument("Invalid bitmap found.");
600
601 ::FITAG* p_new_tag{};
602
603 if(::FreeImage_GetMetadata(::FREE_IMAGE_MDMODEL(model), p_bmp.get(),
604 name, &p_new_tag) && p_new_tag)
605 return p_new_tag;
606 throw GeneralEvent("Specified tag not found.");
607 }())
608 {}
609 ImageTag::ImageTag(const HBitmap& bmp, ImageMetadataModel model,
610 const char* name)
611 : ImageTag(bmp.GetDataPtr(), model, name)
612 {}
613 ImageTag::~ImageTag()
614 {
615 if(owns)
616 ::FreeImage_DeleteTag(p_tag);
617 }
618
619 size_t
620 ImageTag::GetCount() const ynothrow
621 {
622 return ::FreeImage_GetTagCount(p_tag);
623 }
624 const char*
625 ImageTag::GetDescription() const ynothrow
626 {
627 return ::FreeImage_GetTagDescription(p_tag);
628 }
629 ImageTag::ID
630 ImageTag::GetID() const ynothrow
631 {
632 return ::FreeImage_GetTagID(p_tag);
633 }
634 const char*
635 ImageTag::GetKey() const ynothrow
636 {
637 return ::FreeImage_GetTagKey(p_tag);
638 }
639 size_t
640 ImageTag::GetLength() const ynothrow
641 {
642 return ::FreeImage_GetTagLength(p_tag);
643 }
644 ImageTag::Type
645 ImageTag::GetType() const ynothrow
646 {
647 return ImageTag::Type(::FreeImage_GetTagType(p_tag));
648 }
649 const void*
650 ImageTag::GetValuePtr() const ynothrow
651 {
652 return ::FreeImage_GetTagValue(p_tag);
653 }
654
655 bool
656 ImageTag::SetCount(size_t count) const ynothrow
657 {
658 return ::FreeImage_SetTagCount(p_tag, static_cast<unsigned long>(count));
659 }
660 bool
661 ImageTag::SetDescription(const char* desc) const ynothrow
662 {
663 return ::FreeImage_SetTagDescription(p_tag, desc);
664 }
665 bool
666 ImageTag::SetID(ImageTag::ID id) const ynothrow
667 {
668 return ::FreeImage_SetTagID(p_tag, id);
669 }
670 bool
671 ImageTag::SetKey(const char* key) const ynothrow
672 {
673 return ::FreeImage_SetTagKey(p_tag, key);
674 }
675 bool
676 ImageTag::SetLength(size_t len) const ynothrow
677 {
678 return ::FreeImage_SetTagLength(p_tag, static_cast<unsigned long>(len));
679 }
680 bool
681 ImageTag::SetType(ImageTag::Type type) const ynothrow
682 {
683 return ::FreeImage_SetTagType(p_tag, ::FREE_IMAGE_MDTYPE(type));
684 }
685 bool
686 ImageTag::SetValue(const void* value) const ynothrow
687 {
688 return ::FreeImage_SetTagValue(p_tag, value);
689 }
690
691 ImageTag::DataPtr
692 ImageTag::Release() ynothrow
693 {
694 const auto ptr(p_tag);
695
696 p_tag = {};
697 return ptr;
698 }
699
700 string
701 to_string(const ImageTag& tag, ImageMetadataModel model)
702 {
703 static mutex mtx;
704 lock_guard<mutex> lck(mtx);
705
706 // XXX: The documentation does not guarantee non null return value, but
707 // The implementation actually use static string as buffer, as well as
708 // suggested "not thread safe".
709 return string(Nonnull(::FreeImage_TagToString(::FREE_IMAGE_MDMODEL(model),
710 tag.GetDataPtr())));
711 }
712
713
714 ImageMetadataFindData::ImageMetadataFindData(HBitmap::DataPtr ptr,
715 ImageMetadataModel model)
716 : CurrentModel(model), p_bitmap(ptr)
717 {
718 if(!p_bitmap)
719 throw std::invalid_argument("Invalid bitmap found.");
720 }
721 ImageMetadataFindData::ImageMetadataFindData(const HBitmap& bmp,
722 ImageMetadataModel model)
723 : ImageMetadataFindData(bmp.GetDataPtr(), model)
724 {}
725 ImageMetadataFindData::~ImageMetadataFindData()
726 {
727 if(p_metadata)
728 Close();
729 }
730
731 void
732 ImageMetadataFindData::Close() ynothrow
733 {
734 ::FreeImage_FindCloseMetadata(p_metadata);
735 }
736
737 void
738 ImageMetadataFindData::Read() ynothrow
739 {
740 if(!p_metadata)
741 p_metadata = ::FreeImage_FindFirstMetadata(
742 ::FREE_IMAGE_MDMODEL(CurrentModel), p_bitmap.get(), &p_tag);
743 else if(!::FreeImage_FindNextMetadata(p_metadata, &p_tag))
744 {
745 Close();
746 p_metadata = {};
747 }
748 }
749
750 void
751 ImageMetadataFindData::Rewind() ynothrow
752 {
753 if(p_metadata)
754 {
755 Close();
756 p_metadata = {};
757 }
758 }
759
760
761 ImageCodec::ImageCodec()
762 {
763 // XXX: Thread safety of errno.
764 const auto old_errno(errno);
765
766 ::FreeImage_Initialise(false);
767 ::FreeImage_SetOutputMessageStdCall(FI_OutputMessage);
768 errno = old_errno;
769 }
770 ImageCodec::~ImageCodec()
771 {
772 ::FreeImage_DeInitialise();
773 }
774
775 ImageFormat
776 ImageCodec::DetectFormat(ImageMemory::NativeHandle handle, size_t size)
777 {
778 return ImageFormat(::FreeImage_GetFileTypeFromMemory(handle,
779 int(static_cast<unsigned long>(size))));
780 }
781 ImageFormat
782 ImageCodec::DetectFormat(const char* filename)
783 {
784 const auto fmt(GetFileType(filename));
785
786 return fmt == ImageFormat::Unknown
787 ? ImageFormat(::FreeImage_GetFIFFromFilename(filename)) : fmt;
788 }
789 ImageFormat
790 ImageCodec::DetectFormat(const char16_t* filename)
791 {
792 const auto fmt(GetFileType(filename));
793
794 // TODO: Implement detection based on file content rather than filename.
795 return fmt == ImageFormat::Unknown ? GetFormatFromFilename(filename) : fmt;
796 }
797
798 CompactPixmap
799 ImageCodec::Load(ImageMemory::Buffer buf)
800 {
801 const ImageMemory mem(std::move(buf));
802
803 if(mem.GetFormat() == ImageFormat::Unknown)
804 throw UnknownImageFormat("Unknown image format found when loading.");
805 return HBitmap(mem);
806 }
807
808 HMultiBitmap
809 ImageCodec::LoadForPlaying(const char* path)
810 {
811 const auto fmt(DetectFormat(path));
812
813 return HMultiBitmap(path, fmt, fmt == ImageFormat::GIF
814 ? ImageDecoderFlags::GIF_Playback : ImageDecoderFlags::Default);
815 }
816 HMultiBitmap
817 ImageCodec::LoadForPlaying(const char16_t* path)
818 {
819 const auto fmt(DetectFormat(path));
820
821 return HMultiBitmap(path, fmt, fmt == ImageFormat::GIF
822 ? ImageDecoderFlags::GIF_Playback : ImageDecoderFlags::Default);
823 }
824
825 #undef YF_PixConvSpec
826
827 } // namespace Drawing;
828
829 } // namespace YSLib;
830
YSLib::Drawing::MultiBitmapData::handle
::fi_handle handle
Definition: Image.cpp:461
YSLib::Drawing::MultiBitmapData::DefPred
DefPred(const ynothrow, OpenForRead, read) DefGetter(const ynothrow
YTraceDe
#define YTraceDe(...)
YCLib 默认调试跟踪。
Definition: Debug.h:313
YSLib::Drawing::GetHeight
tr GetHeight())) inline PDefH(void
按字体高度和行距调整文本区域的底边距。
YSLib::Drawing::MultiBitmapData::read
bool read
Definition: Image.cpp:460
YSLib::Drawing::ImageMetadataFindData::CurrentModel
ImageMetadataModel CurrentModel
当前生效的模型。
Definition: Image.h:851
YSLib::Drawing::ImageMemory::NativeHandle
::FIMEMORY * NativeHandle
Definition: Image.h:222
platform::msg
const string & msg
Definition: Debug.h:464
YSLib::Drawing::HBitmap::SaveTo
void SaveTo(const char *, ImageFormat=ImageFormat::BMP, ImageDecoderFlags=ImageDecoderFlags::Default) const
\ brief 保存：使用指定 UTF-8 文件名、格式和解码器标识。
Definition: Image.cpp:427
YSLib::Drawing::to_string
string to_string(const ImageTag &tag, ImageMetadataModel model)
Definition: Image.cpp:701
YSLib::Drawing::ImageMemory::ImageMemory
ImageMemory(const HBitmap &, ImageFormat=ImageFormat::BMP, ImageDecoderFlags=ImageDecoderFlags::Default)
构造：从现有图像打开。
YSLib::Drawing::ImageMetadataFindData::~ImageMetadataFindData
~ImageMetadataFindData()
析构：关闭查找状态。
Definition: Image.cpp:725
YSLib::Drawing::ImageTag::ImageTag
ImageTag(const HBitmap &, ImageMetadataModel, const char *)
构造：使用依赖的位图、模型和元数据名称。
Definition: Image.cpp:609
YSLib::Drawing::HMultiBitmap
多页面位图句柄：指向多页面位图数据。
Definition: Image.h:582
CatchThrow
#define CatchThrow(_ex,...)
指定抛出指定异常作为异常处理器。
Definition: YBaseMacro.h:141
YSLib::Drawing::ImageFormat::GIF
YSLib::Drawing::buffer
The boundary is out of the buffer
Definition: YDraw.h:118
YModules.h
YSLib::Drawing::MultiBitmapData::size_t
size_t
Definition: Image.cpp:482
YSLib::Drawing::ImageMetadataModel
ImageMetadataModel
图像元数据模型标识。
Definition: Image.h:138
YSLib
YSLib 命名空间。
Definition: AndroidHost.h:45
ystdex::make_observer
observer_ptr< _type > make_observer(_type *p)
Definition: pointer.hpp:326
YSLib::Drawing::GetFrameTimeOf
TimeSpan GetFrameTimeOf(const HBitmap &bmp)
Definition: Image.cpp:440
YSLib::Drawing::ImageTag::SetType
bool SetType(Type) const ynothrow
Definition: Image.cpp:681
YSLib::Drawing::HBitmap::Rescale
void Rescale(const Size &, SamplingFilter=SamplingFilter::Box)
缩放为指定大小。
Definition: Image.cpp:421
YSLib::Drawing::BitmapPtr
Pixel * BitmapPtr
Definition: YGraphics.h:42
YSLib::Drawing::ImageTag::GetValue
const _type & GetValue() const ythrow(GeneralEvent)
取指定类型的标签值。
Definition: Image.h:790
YSLib::Drawing::ImageTag::GetLength
size_t GetLength() const ynothrow
Definition: Image.cpp:640
YSLib::Drawing::MultiBitmapData::page_count
size_t page_count
Definition: Image.cpp:467
YSLib::Drawing::ImageTag::SetKey
bool SetKey(const char *) const ynothrow
Definition: Image.cpp:671
CHRLib::f
f(d, s)
YSLib::Drawing::ImageMetadataFindData::Rewind
void Rewind() ynothrow
Definition: Image.cpp:751
YSLib::Drawing::CompactPixmap
标准矩形像素图缓冲区。
Definition: YGDI.h:243
YSLib::Drawing::ImageMetadataFindData::p_tag
ImageTag::DataPtr p_tag
Definition: Image.h:855
YSLib::Drawing::ImplDeDtor
ImplDeDtor(FontException) namespace
Definition: Font.cpp:80
YSLib::Drawing::ImageCodec
Definition: Image.h:935
YAssertNonnull
#define YAssertNonnull(_expr)
Definition: cassert.h:120
NPL::c_str
YF_API const char src c_str())) YF_API void InstallDirectory(const string &
安装目录：复制目录树。
Definition: Dependency.h:131
ystdex::ntctslen
size_t ntctslen(const _tChar *s)
计算简单 NTCTS 长度。
Definition: cstring.h:456
YSLib::Drawing::ImageTag::Release
DataPtr Release() ynothrow
释放所有权。
Definition: Image.cpp:692
YSLib::Drawing::BitPerPixel
std::uint8_t BitPerPixel
Definition: Image.h:58
YSLib::UI::Close
void Close(IWidget &wgt)
Definition: YWidget.cpp:92
TryRet
#define TryRet(...)
指定表达式在 try 块中求值并返回。
Definition: YBaseMacro.h:124
YSLib::Drawing::HBitmap::p_bitmap
unique_ptr_from< Deleter > p_bitmap
Definition: Image.h:315
platform::containers::string
basic_string< char > string
Definition: Container.h:101
YSLib::Text::buf
const char * buf
Definition: TextFile.h:81
ystdex::data
auto data(_tRange &c) -> decltype(c.data())
Definition: range.hpp:280
YSLib::Drawing::ImageTag::SetLength
bool SetLength(size_t) const ynothrow
Definition: Image.cpp:676
CHRLib::ToASCII
yconstfn char ToASCII(_tChar c)
任意整数类型字符转换为 ASCII 取值范围兼容的字符。
Definition: CharacterProcessing.h:61
YSLib::CheckArithmetic
_tDst CheckArithmetic(_type val, const std::string &name={}, RecordLevel lv=Err)
检查算术类型数值在指定类型的范围内。
Definition: YCoreUtilities.h:321
YSLib::YAssert
YAssert(!(v< Deref(a)),"Value less than lower bound found.")
YSLib::Drawing::MultiBitmapData::io_ref
lref<::FreeImageIO > io_ref
Definition: Image.cpp:464
platform_ex::Windows::proc
const char * proc
Definition: MinGW32.h:240
YSLib::Drawing::UnsupportedImageFormat
未被支持的图像格式异常：表示请求的操作涉及的图像格式不受库的支持。
Definition: Image.h:177
YSLib::Drawing::ImageTag::GetValuePtr
const void * GetValuePtr() const ynothrow
Definition: Image.cpp:650
platform_ex::Windows::unsigned
YF_API unsigned
Definition: NLS.h:52
YSLib::Drawing::MultiBitmapData::PageCount
PageCount
Definition: Image.cpp:482
YSLib::Drawing::ImageCodec::LoadForPlaying
static HMultiBitmap LoadForPlaying(const char *)
读取指定路径的多页面图片文件为用于直接呈现的帧序列。
Definition: Image.cpp:809
ystdex::lref
左值引用包装。
Definition: ref.hpp:74
YSLib::Drawing::ImageMemory::Buffer
vector< octet > Buffer
Definition: Image.h:224
YSLib::Drawing::HBitmap::Release
PDefH(byte *, GetScanLine, size_t idx) const ynothrow ImplRet(p_bitmap?(*this) Release[idx] Deleter::pointer() ynothrow
取扫描线数据。
Definition: Image.h:498
YSLib::Drawing::Size::Width
SDst Width
Definition: YGDIBase.h:302
YSLib::Drawing::ImageTag::DataPtr
::FITAG * DataPtr
Definition: Image.h:689
platform::SDst
std::uint16_t SDst
屏幕坐标距离。
Definition: Video.h:44
YSLib::Drawing::MultiBitmapData::MultiBitmapData
MultiBitmapData(::fi_handle, int,::FI_PluginRec &,::FreeImageIO &=u8_io, bool=true)
Definition: Image.cpp:489
CHRLib::s
_tDst const _tSrc * s
Definition: CharacterProcessing.h:140
ystdex::sfmt
auto sfmt(const _tChar *fmt,...) -> decltype(vsfmt(fmt, std::declval< std::va_list >()))
以 C 标准输出格式的输出 std::basic_string 实例的对象。
Definition: string.hpp:1200
YSLib::Drawing::ImageTag::SetValue
bool SetValue(const void *) const ynothrow
Definition: Image.cpp:686
ystdex::lref::get
_type & get() const
Definition: ref.hpp:108
YSLib::i
return i
Definition: YCoreUtilities.h:176
YSLib::Drawing::ImageMetadataFindData::p_bitmap
HBitmap::DataPtr p_bitmap
Definition: Image.h:854
YSLib::Drawing::HBitmap
位图句柄：指向位图数据。
Definition: Image.h:299
platform_ex::Windows::Invalid
Definition: MinGW32.h:471
YSLib::Drawing::ImageTag::SetCount
bool SetCount(size_t) const ynothrow
Definition: Image.cpp:656
YModules.h
YSLib::Drawing::ImageCodec::DetectFormat
static ImageFormat DetectFormat(ImageMemory::NativeHandle, size_t)
检测图像格式。
Definition: Image.cpp:776
YSLib::Drawing::ImageTag::~ImageTag
~ImageTag()
Definition: Image.cpp:613
Drawing
YSLib::Drawing::MultiBitmapData
Definition: Image.cpp:457
YSLib::Drawing::ImageDecoderFlags
ImageDecoderFlags
图像解码器标识。
Definition: Image.h:84
YSLib::Drawing::HBitmap::Deleter::pointer
::FIBITMAP * pointer
Definition: Image.h:307
YSLib::Drawing::HBitmap::DataPtr
observer_ptr<::FIBITMAP > DataPtr
Definition: Image.h:302
YSLib::Drawing::HMultiBitmap::Lock
HBitmap Lock(size_t=0) const ynothrowv
Definition: Image.cpp:582
YSLib::Drawing::ImageMetadataFindData::ImageMetadataFindData
ImageMetadataFindData(HBitmap::DataPtr, ImageMetadataModel)
Definition: Image.cpp:714
YSLib::Drawing::ImageTag::GetID
ID GetID() const ynothrow
Definition: Image.cpp:630
YSLib::ynothrow
YB_PURE const _type size_t n ynothrow
Definition: YCoreUtilities.h:168
YSLib::Drawing::ImageTag::ID
std::uint16_t ID
Definition: Image.h:690
YSLib::Drawing::GetLogicalSizeOf
Size GetLogicalSizeOf(const HBitmap &bmp)
Definition: Image.cpp:448
YSLib::Drawing::ImageCodec::Load
static CompactPixmap Load(ImageMemory::Buffer)
Definition: Image.cpp:799
yunused
#define yunused(...)
标记未使用的表达式。
Definition: ydef.h:968
YSLib::Drawing::ImageMemory
图像内存对象；保存图像内容的数据缓冲对象。
Definition: Image.h:219
YSLib::Drawing::MultiBitmapData::LockPage
page_count observer_ptr<::FIBITMAP > LockPage(size_t=0) const ynothrow
Definition: Image.cpp:519
platform::ufopen
std::FILE * ufopen(const char *filename, const char *mode) ynothrowv
Definition: FileIO.cpp:898
YSLib::Drawing::ImageMemory::format
ImageFormat format
Definition: Image.h:238
YSLib::Drawing::ImageMetadataFindData::Read
void Read() ynothrow
读取：迭代当前查找状态。
Definition: Image.cpp:738
YSLib::Drawing::ImageTag::owns
bool owns
Definition: Image.h:720
YSLib::Drawing::MultiBitmapData::load_flags
int load_flags
Definition: Image.cpp:462
YSLib::Drawing::ImageFormat::Unknown
YSLib::Drawing::HBitmap::HBitmap
HBitmap(const Size &, BitPerPixel=0)
异常中立：输入的大小分量过大。
Definition: Image.cpp:290
ynothrowv
#define ynothrowv
YSLib 无异常抛出保证验证：有条件地使用无异常抛出规范。
Definition: ydef.h:786
YSLib::Drawing::ImageTag::GetType
Type GetType() const ynothrow
Definition: Image.cpp:645
YSLib::Drawing::MultiBitmapData::data
void * data
Definition: Image.cpp:468
YSLib::Drawing::HBitmap::Deleter::operator()
void operator()(pointer) const ynothrow
Definition: Image.cpp:284
YSLib::Drawing::ImageTag::GetKey
const char * GetKey() const ynothrow
Definition: Image.cpp:635
YSLib::Drawing::HBitmap::GetPixels
byte * GetPixels() const ynothrow
取像素数据。
Definition: Image.cpp:404
YSLib::Drawing::Size::Height
SDst Height
宽和高。
Definition: YGDIBase.h:302
YSLib::Drawing::ImageFormat
ImageFormat
图像格式。
Definition: Image.h:67
YSLib::Drawing::ImageMetadataFindData::p_metadata
DataPtr p_metadata
Definition: Image.h:856
std
Definition: memory.hpp:1183
YSLib::Drawing::HBitmap::GetBPP
BitPerPixel GetBPP() const ynothrow
Definition: Image.cpp:389
YSLib::Drawing::ImageTag::p_tag
DataPtr p_tag
Definition: Image.h:718
DefGetter
#define DefGetter(_q, _t, _n,...)
Definition: YBaseMacro.h:241
ythrow
#define ythrow(...)
YSLib 动态异常规范：根据是否使用异常规范宏指定或忽略动态异常规范。
Definition: ydef.h:817
ystdex::byte
unsigned char byte
字节类型。
Definition: ydef.h:834
platform::Nonnull
_type && Nonnull(_type &&p) ynothrowv
断言并返回非空参数。
Definition: Debug.h:422
YSLib::Drawing::ImageTag::Type
Type
元数据类型标识。
Definition: Image.h:695
YSLib::GeneralEvent
std::runtime_error GeneralEvent
一般运行时异常事件类。
Definition: YException.h:46
YSLib::Drawing::ImageMetadataModel::Animation
YSLib::Drawing::ImageTag::SetDescription
bool SetDescription(const char *) const ynothrow
Definition: Image.cpp:661
platform::Descriptions::Warning
Definition: YCommon.h:167
YSLib::Drawing::ImageCodec::~ImageCodec
~ImageCodec()
Definition: Image.cpp:770
YSLib::Drawing::MultiBitmapData::plugin_ref
lref<::FI_PluginRec > plugin_ref
Definition: Image.cpp:466
YSLib::UI::name
yconstfn const string & name
Definition: Loader.h:130
ystdex::noncopyable
不可复制对象：禁止派生类调用默认原型的复制构造函数和复制赋值操作符。
Definition: base.h:41
YSLib::Drawing::Size
屏幕区域大小。
Definition: YGDIBase.h:293
YSLib::Text::str
const char const char * str
Definition: TextFile.h:81
YSLib::Drawing::ImageCodec::ImageCodec
ImageCodec()
Definition: Image.cpp:761
YSLib::Drawing::MultiBitmapData::~MultiBitmapData
~MultiBitmapData()
Definition: Image.cpp:512
CHRLib::char16_t
char16_t((*c_ptr<< CHAR_BIT)|c_ptr[1])) inline PDefH(char16_t
取 c_ptr 指向的小端序双字节字符。
YSLib::Drawing::UnknownImageFormat
未知图像格式异常：表示请求的操作涉及的图像格式因为不明确而不受库的支持。
Definition: Image.h:199
ystdex::single_thread::mutex
Definition: pseudo_mutex.h:746
ystdex::size
auto size(const _tRange &c) -> decltype(c.size())
类容器访问。
Definition: range.hpp:233
ystdex::make_unique_default_init
enable_if_t<!is_array< _type >::value, std::unique_ptr< _type > > make_unique_default_init()
Definition: memory.hpp:879
YSLib::Drawing::ImageDecoderFlags::GIF_Playback
YSLib::IO::int
YF_API int
Definition: File.h:51
YSLib::Drawing::ImageMetadataFindData
图像元数据。
Definition: Image.h:841
YSLib::Drawing::ImageTag::SetID
bool SetID(ID) const ynothrow
Definition: Image.cpp:666
YSLib::Drawing::BadImageAlloc
图像资源分配失败异常：表示存储等资源不足导致无法创建图像。
Definition: Image.h:160
YSLib::Drawing::ImageTag
图像元数据标签。
Definition: Image.h:686
YSLib::Timers::TimeSpan
std::chrono::duration< Duration::rep, std::milli > TimeSpan
低精度时间间隔。
Definition: YClock.h:81
YSLib::path
YF_API const char * path
Definition: Initialization.h:77
YSLib::Drawing::ImageDecoderFlags::Default
YSLib::Drawing::HMultiBitmap::HMultiBitmap
HMultiBitmap(const char *, ImageFormat, ImageDecoderFlags=ImageDecoderFlags::Default)
构造：使用指定 UTF-8 文件名、指定格式和解码器标识。
Definition: Image.cpp:563
CHRLib::p
const auto p(d)
fp
tidy_ptr< std::streambuf > fp
Definition: TextManager.cpp:93
ystdex::details::get
get())
Definition: cast.hpp:102