YSTest: Image.cpp 源文件

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