OWLNext    7.0
Borland's Object Windows Library for the modern age
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
dib.cpp
Go to the documentation of this file.
1//----------------------------------------------------------------------------
2// ObjectWindows
3// Copyright (c) 1992, 1996 by Borland International, All Rights Reserved
4//
5/// \file
6/// Implementation of TDib class, an encapsulation of Device Independent Bitmaps
7/// on disk and in memory.
8//----------------------------------------------------------------------------
9#include <owl/pch.h>
10
11#include <owl/gdiobjec.h>
12#include <owl/metafile.h>
13#include <owl/clipboar.h>
14#include <owl/except.h>
15#include <owl/file.h>
16#include <owl/wsyscls.h>
17
18#if defined(__BORLANDC__)
19# pragma option -w-ccc // Disable "Condition is always true/false"
20#endif
21
22#define BFT_BITMAP 0x4d42 /* 'BM' */
23
24using namespace std;
25
26namespace owl {
27
29DIAG_DECLARE_GROUP(OwlGDI); // General GDI diagnostic group
30
31//
32// Internal DIB file Read/Write functions talk to this IO implementation
33//
34class TFileIO : public TDib::IFileIn, public TDib::IFileOut {
35 public:
36 TFileIO(TFile& file) : File(file) {}
37
38 virtual long Read(void * buffer, long size)
39 {
40 return File.Read(buffer, size);
41 }
42 virtual void Skip(long size)
43 {
44 File.Seek(size, TFile::cur);
45 }
46 virtual bool Write(void * buffer, long size)
47 {
48 return File.Write(buffer, size);
49 }
50
51 private:
52 TFile& File;
53};
54
55
56//
57/// Given a BITMAPINFOHEADER, allocate a global buffer for Handle & init Info
58//
59void
61{
62 // Allocate & lock down the actual single memory block used by this DIB
63 //
64 int maskAlloc = infoHeader.biCompression==BI_BITFIELDS ? 3*sizeof(uint32) : 0;
65 int colorAlloc = int(infoHeader.biClrUsed * sizeof(RGBQUAD)); // Color table size in mem
66 IsResHandle = false;
67 uint32 size = sizeof(BITMAPINFOHEADER) + maskAlloc + colorAlloc + infoHeader.biSizeImage;
69 if (!Handle)
71
72 // Setup Info ptr & copy over working infoHeader. Finish by using
73 // InfoFromHandle to update all members from Info.
74 //
75 Info = reinterpret_cast<LPBITMAPINFO>(::GlobalLock(Handle));
76 Info->bmiHeader = infoHeader;
77
79}
80
81//
82/// Locks the global/res handle if needed and extracts the pointers and cached info
83/// maintained as member variables from Info.
84///
85/// Needs only Info setup, or if Info is 0 then Handle & IsResHandle setup
86//
87void
89{
90 // Get the BITMAPINFO Info from the handle if needed
91 //
92 if (!Info) {
93 if (IsResHandle)
94 Info = reinterpret_cast<LPBITMAPINFO>(::LockResource(Handle));
95 else
96 Info = reinterpret_cast<LPBITMAPINFO>(::GlobalLock(Handle));
97 if (!Info)
99 }
100
101 // Fail if the header does not look OK
102 //
103 if (Info->bmiHeader.biSize != sizeof(BITMAPINFOHEADER)) {
104 if (!IsResHandle)
107 }
108
109 // Determine if there is a bit mask (used by 16 & 32 bpp bmps) and where
110 // the color table starts
111 //
112 if (Info->bmiHeader.biCompression == BI_BITFIELDS) {
113 Mask = reinterpret_cast<uint32 *>(Info->bmiColors);
114 Colors = reinterpret_cast<TRgbQuad *>(reinterpret_cast<char *>(Info->bmiColors) + 3 * sizeof(uint32));
115 }
116 else {
117 Mask = nullptr;
118 Colors = static_cast<TRgbQuad *>(Info->bmiColors);
119 }
120
121 // Figure out the number of colors in the color table using biClrsUsed &
122 // biBitCount.
123 //
124 NumClrs = Info->bmiHeader.biClrUsed
125 ? Info->bmiHeader.biClrUsed
126 : NColors(Info->bmiHeader.biBitCount);
127
128 Bits = reinterpret_cast<char *>(Colors) + static_cast<int>(NumClrs) * sizeof(RGBQUAD);
129
130 // Zero out Colors if there is no color table.
131 //
132 if (!NumClrs)
133 Colors = nullptr;
134
135 Mode = DIB_RGB_COLORS;
136}
137
138//
139/// Under Win32, resources are read-only. So, to allow for modification of the
140/// Dib, a copy must be made.
141//
142void
144{
145 const char* begin = reinterpret_cast<const char*>(Info);
146 const char* end = static_cast<const char*>(Bits) + Info->bmiHeader.biSizeImage;
147 size_t size = end - begin;
149 if (!tempHandle)
151
153 memcpy(tempInfo, Info, size);
154
155 // Handle will now be a memory handle, & no longer a res handle
156 // Update Bits pointer & other members that may have moved.
157 //
159 Info = reinterpret_cast<LPBITMAPINFO>(tempInfo);
160 IsResHandle = false;
162}
163
164
165//
166/// Creates a TDib object and sets the Handle data member to the given borrowed
167/// handle. The ShouldDelete data member defaults to false, ensuring that the
168/// borrowed handle will not be deleted when the C++ object is destroyed.
169//
171:
173 Info(nullptr), IsResHandle(false)
174{
176}
177
178
179//
180/// Constructs a TDib object with a handle borrowed from the given Clipboard.
181//
182TDib::TDib(const TClipboard& clipboard)
183:
184 TGdiBase(clipboard.GetClipboardData(CF_DIB)),
185 Info(nullptr), IsResHandle(false)
186{
188}
189
190
191//
192/// This public copy constructor creates a complete copy of the given src object as
193/// in:
194/// \code
195/// TDib mySrc = yourSrc;
196/// \endcode
197//
199:
200 IsResHandle(false)
201{
202 PRECONDITION(src.Info != 0);
203
204// long size = ::GlobalSize(src.Handle); // !CQ assumes src has a mem handle
205 uint32 size = src.SizeDib();
207 if (!Handle)
209
210 Info = reinterpret_cast<LPBITMAPINFO>(::GlobalLock(Handle));
211 memcpy(Info, src.Info, size);
212
213 Mask = reinterpret_cast<uint32 *>(src.Mask ?
214 reinterpret_cast<char *>(Info) + (reinterpret_cast<char *>(src.Mask) - reinterpret_cast<char *>(src.Info)) : nullptr);
215 Bits = reinterpret_cast<char *>(Info) + (reinterpret_cast<char *>(src.Bits) - reinterpret_cast<char *>(src.Info));
216
217 NumClrs = src.NumClrs;
218
219 // Zero out Colors if there is no color table.
220 //
221 if (!NumClrs)
222 Colors = nullptr;
223 else
224 Colors = reinterpret_cast<TRgbQuad *>(reinterpret_cast<char *>(Info) + (reinterpret_cast<char *>(src.Colors) - reinterpret_cast<char *>(src.Info)));
225
226 Mode = src.Mode;
227}
228
229
230//
231/// Destruct a TDib by unlocking & freeing its global memory handle as required
232//
234{
235 if (!Handle || IsResHandle) return;
237 if (ShouldDelete)
239}
240
241
242//
243/// Converts the existing color table in place to use palette relative values. The
244/// palette that is passed is used as a reference. Returns true if the call is
245/// successful; otherwise returns false.
246///
247/// Makes sure that color table is RGB
248//
249bool
251{
252 if (Mode != DIB_RGB_COLORS)
253 return false;
254
255 uint16 nEntries = pal.GetNumEntries();
256
257 for (int c = 0; c < NumClrs; c++) {
258 uint16 index = uint16(c);
259 for (uint16 i = 0; i < nEntries; i++) {
260 PALETTEENTRY pe; //getting all entries one time up front would be faster
261 pal.GetPaletteEntry(i, pe);
262 if (pe.peRed == Colors[c].rgbRed &&
263 pe.peGreen == Colors[c].rgbGreen &&
264 pe.peBlue == Colors[c].rgbBlue) {
265 index = i;
266 break;
267 }
268 }
269 (reinterpret_cast<uint16*>(Colors))[c] = index;
270 }
271 Mode = DIB_PAL_COLORS;
272 return true;
273}
274
275
276//
277/// Converts the existing color table in place to use absolute RGB values. The
278/// palette that is passed is used as a reference. Returns true if the call is
279/// successful; otherwise returns false.
280///
281/// Makes sure that color table is pal relative & that there is enough space
282//
283bool
285{
286 if (Mode != DIB_PAL_COLORS ||
287 static_cast<uint>(reinterpret_cast<char*>(Bits) - reinterpret_cast<char*>(Info)) < NumClrs*sizeof(RGBQUAD))
288 return false;
289
290 uint16 nEntries = pal.GetNumEntries();
291
292 for (int c = static_cast<int>(NumClrs)-1; c >= 0; c--) {
293 uint16 i = (reinterpret_cast<uint16*>(Colors))[c];
294 if (i >= nEntries)
295 i = 0;
297 pal.GetPaletteEntry(i, pe);
298 Colors[c].rgbRed = pe.peRed;
299 Colors[c].rgbGreen = pe.peGreen;
300 Colors[c].rgbBlue = pe.peBlue;
301 }
302 Mode = DIB_RGB_COLORS;
303 return true;
304}
305
306
307//
308// Get, set, find and map the color table entries as colors (RGBQUADs)
309
310//
311/// Returns the color for the given palette entry.
312//
313TColor
315{
316 if (entry >= 0 && entry < NumClrs)
317 if (Mode == DIB_RGB_COLORS)
318 return GetColors()[entry];
319
320 return TColor();
321}
322
323
324//
325/// Sets the given color for the given palette entry.
326//
327void
329{
330 if (entry >= 0 && entry < NumClrs)
331 if (Mode == DIB_RGB_COLORS)
332 GetColors()[entry] = color;
333}
334
335
336//
337/// Returns the palette entry for the given color.
338//
339int
341{
342 for (int entry = 0; entry < NumClrs; entry++)
343 if (color == GetColors()[entry]) // Small data model requires this order
344 return entry;
345 return -1;
346}
347
348
349//
350/// Maps the first or all occurances of fromColor to the toColor in the current palette of this DIB.
351/// Returns the palette entry for the given color. Returns the palette entry for the
352/// toColor argument.
353//
354int
356{
357 int count = 0;
358 for (int entry = 0; entry < NumClrs; entry++)
359 if (fromColor == GetColors()[entry]) { // Small data model requires this order
361 count++;
362 if (!mapAll)
363 break;
364 }
365 return count;
366}
367
368
369//
370// Get, set, find and map the color table entries as palette indices
371//
372uint16
374{
375 if (entry >= 0 && entry < NumClrs)
376 if (Mode == DIB_PAL_COLORS)
377 return (reinterpret_cast<const uint16*>(GetColors()))[entry];
378
379 return 0;
380}
381
382
383//
384/// Sets the given index for the given entry.
385//
386void
388{
389 if (entry >= 0 && entry < NumClrs)
390 if (Mode == DIB_PAL_COLORS)
391 (reinterpret_cast<uint16*>(GetColors()))[entry] = index;
392}
393
394
395//
396/// Returns the palette entry corresponding to the given index.
397//
398int
400{
401 for (int entry = 0; entry < NumClrs; entry++)
402 if (GetIndices()[entry] == index)
403 return entry;
404 return -1;
405}
406
407
408//
409/// Maps the fromIndex to the toIndex in the current palette of this DIB.
410/// Returns the palette entry for the toIndex argument.
411//
412int
414{
415 int count = 0;
416 for (int entry = 0; entry < NumClrs; entry++)
417 if (GetIndices()[entry] == fromIndex) {
419 count++;
420 if (!doAll)
421 break;
422 }
423 return count;
424}
425
426
427//
428/// Maps the UI colors to the value specified in the parameter, mapColors, which is
429/// one of the values of the Map enum. Use this function to get the colors for the
430/// face shading on push buttons, the highlighting for a selected control button,
431/// the text on push buttons, the shade of the window frame and the background
432/// color.
433//
434/// Use MapColor to map selected standard UI colors in this DIB to their
435/// current system values. Also can map a background color. Used to update a
436/// UI DIB to current colors before rendering.
437///
438/// - \c \b LtGray -> 3d Face
439/// - \c \b Black -> Button Text
440/// - \c \b Gray -> 3d Shadow
441/// - \c \b White -> 3d Hilight
442/// - \c \b Magenta -> Window Frame
443/// - \c \b LtYellow -> bkColor
444//
445void
467
468
469//
470/// Moves this dib to the clipboard. Ownership of the DIB handle is passed to the
471/// clipboard.
472//
473void
475{
476 if (Handle) {
477 if (IsResHandle) {
478 }
479 else {
481 }
482 clipboard.SetClipboardData(CF_DIB, Handle);
483 ShouldDelete = false;
484 Info = nullptr;
485 Bits = nullptr;
486 Handle = nullptr;
487 }
488}
489
490
491//
492/// Creates a DIB object from the given resource file (.bmp).
493//
499
500//
501/// String-aware overload
502//
508
509
510//
511/// Creates a DIB from the file.
512//
518
519//
520/// Creates a DIB from the file stream.
521//
527
528
529//
530/// Constructs an empty DIB for use by derived classes.
531//
533:
534 Info(nullptr), Mask(nullptr), Colors(nullptr), Bits(nullptr),
535 NumClrs(0),
536 IsResHandle(false)
537{
538 // Handle must be set by derived class
539 // InfoFromHandle() or equivalent must then be called
540}
541
542
543//
544/// Tests if the passed file is a Windows 3.x (or PM 1.x) DIB and if so read it.
545///
546/// Returns true if Dib was read OK.
547//
548bool
550{
552 if (!file.IsOpen()) {
553 TRACEX(OwlGDI, 0, "Cannot open bitmap file '" << name << "' to read");
554 return false;
555 }
556
557 // Read the bitmap in, file header & all
558 //
559 bool ok = Read(file, true);
560
561 file.Close();
562 return ok;
563}
564
565
566//
567/// Read a Windows 3.x or PM 1.x device independent bitmap from a TFile
568/// Return true iff Dib was read OK
569//
570bool
572{
573 TFileIO in(file);
574 return Read(in, readFileHeader);
575}
576
577//
578// The ios version of the DIB read requires large data model since the buffers
579// are quite large.
580//
581
582//
583//
584//
585class TStreamIn : public TDib::IFileIn {
586 public:
587 TStreamIn(istream& is) : Is(is) {}
588
589 virtual long Read(void* buffer, long size)
590 {
591 PRECONDITION(size >= 0);
592 streamsize n = Is.read(static_cast<char*>(buffer), size).gcount();
593
594 // Note: 'n' cannot be larger than 'size'; hence we can cast unchecked.
595 // TODO: Widen the return type to avoid the narrowing cast.
596
597 return static_cast<long>(n);
598 }
599
600 virtual void Skip(long size)
601 {
602 Is.seekg(size, ios::cur);
603 }
604
605 private:
606 istream& Is;
607};
608
609//
610//
611/// Read a Windows 3.0 or PM 1.X device independent bitmap from an istream
612///
613/// Checks header, read Info, palette and bitmap. PM DIBs can be converted to
614/// Win 3.x DIBs on the fly.
615///
616/// Returns true iff DIB was read OK
617//
618bool
620{
621 TStreamIn in(is);
622 return Read(in, readFileHeader);
623}
624
625
626//
627/// Reads a Windows 3.0 or PM 1.X device independent bitmap. (.BMP) from an
628/// implementor of TDib's IFileIn interface
629///
630/// Checks header, read Info, palette and bitmap. PM Dibs are converted to
631/// Windows 3.x Dibs on the fly.
632///
633/// Returns true iff Dib was read OK
634//
635bool
637{
638 long offBits = 0;
639
640 // Read file header and verify the signature. Grab bfOffBits if it is != 0
641 // We ignore all other information in the file header since some applications
642 // do not put correct information in the fields...
643 //
644 if (readFileHeader) {
646 if (static_cast<size_t>(in.Read(&bmf, sizeof(bmf))) != sizeof(bmf) || bmf.bfType != BFT_BITMAP) {
647 TRACEX(OwlGDI, 0, "Not a Windows 3.x or PM 1.x bitmap file");
649 return false;
650 }
651 if (bmf.bfOffBits)
652 offBits = bmf.bfOffBits - sizeof(BITMAPFILEHEADER);
653 }
654
655 // Read bitmap header size & check it. It must be one of the two known header
656 // sizes.
657 // Will add BITMAPV4HEADER support when available
658 //
660 size_t n = static_cast<size_t>(in.Read(&headerSize, sizeof(headerSize)));
661 if (n != sizeof(headerSize) ||
662 (headerSize != sizeof(BITMAPCOREHEADER) && headerSize != sizeof(BITMAPINFOHEADER)))
663 {
664 TRACEX(OwlGDI, 0, "Not a Windows 3.x or PM 1.x bitmap file");
666 return false;
667 }
668
669 // Prepare to build or read a header that is an Info (Windows) type
670 //
672 infoHeader.biSize = sizeof(BITMAPINFOHEADER);
673
674 // If this is a PM 1.x DIB, read the core header & copy over to the Info header
675 //
676 bool isCore = headerSize == sizeof(BITMAPCOREHEADER);
677 if (isCore) {
678 // Read in the rest of the core header, aborting if it is truncated
679 //
681 int size = static_cast<int>(headerSize)-sizeof(uint32);
682 if (in.Read(&coreHeader.bcWidth, size) != size) {
683 TRACEX(OwlGDI, 0, "Invalid PM 1.x DIB Header");
685 return false;
686 }
687
688 // Copy core fields over to info fields, filling in the missing pieces
689 //
690 infoHeader.biWidth = coreHeader.bcWidth;
691 infoHeader.biHeight = coreHeader.bcHeight;
692 infoHeader.biPlanes = coreHeader.bcPlanes;
693 infoHeader.biBitCount = coreHeader.bcBitCount;
694 infoHeader.biCompression = BI_RGB; // No compression
695 infoHeader.biSizeImage = 0; // Calculate this below
696 infoHeader.biXPelsPerMeter = 0; // Zero is OK
697 infoHeader.biYPelsPerMeter = 0; // Zero is OK
698 infoHeader.biClrUsed = 0; // Calculate this below
699 infoHeader.biClrImportant = 0; // Zero is OK
700 }
701 // This is a Win 3.x DIB, read the info header
702 //
703 else {
704 // Read in the rest of the info header, aborting if it is truncated
705 //
706 int size = static_cast<int>(headerSize)-sizeof(uint32);
707 if (in.Read(&infoHeader.biWidth, size) != size) {
708 TRACEX(OwlGDI, 0, "Invalid Win 3.x DIB Header");
710 return false;
711 }
712 }
713
714 // Check number of planes. Windows supports only 1 plane DIBs
715 //
716 if (infoHeader.biPlanes != 1) {
717 TRACEX(OwlGDI, 0, "Invalid number of planes in DIB");
719 return false;
720 }
721
722 // Fill in the default value for biClrsUsed, if not supplied, using the
723 // bit count. Will remain 0 for 16bpp or greater.
724 //
725 if (!infoHeader.biClrUsed)
726 infoHeader.biClrUsed = NColors(infoHeader.biBitCount);
727
728 // Some applications do not fill in the biSizeImage field in the header.
729 // (Actually the truth is more likely that some drivers do not fill the
730 // field in and the apps do not compensate for these buggy drivers.)
731 //
732 // Therefore, if compression was not used, we (re)compute the size,
733 // but if compression is used, we have no choice but to trust the size.
734 //
735 if (infoHeader.biCompression == BI_RGB ||
736 infoHeader.biCompression == BI_BITFIELDS)
737 infoHeader.biSizeImage =
738 ScanBytes(infoHeader.biWidth,
739 infoHeader.biBitCount) * infoHeader.biHeight;
740
741 // Setup all members based on InfoHeader
742 //
744
745 // Read color mask directly into allocated memory
746 //
747 if (Mask) {
748 int size = 3*sizeof(uint32);
749 if (in.Read(reinterpret_cast<char *>(Mask), size) != size) {
750 TRACEX(OwlGDI, 0, "Could not read DIB color mask");
752 return false;
753 }
754 }
755
756 // Read color table directly into allocated memory
757 // Walk backwards & expand to RGBQUADs if it is a PM Core DIB
758 //
759 int colorRead = isCore ? // Color table size on disk
760 static_cast<int>(NumClrs) * sizeof(RGBTRIPLE) :
761 static_cast<int>(NumClrs) * sizeof(RGBQUAD);
762 if (Colors) {
763 if (in.Read(reinterpret_cast<char *>(Colors), colorRead) != colorRead) {
764 TRACEX(OwlGDI, 0, "Could not read DIB color table");
766 return false;
767 }
768 if (isCore) {
769 for (int i = int(NumClrs-1); i >= 0; i--) {
770 Colors[i].rgbRed = (reinterpret_cast<RGBTRIPLE*>(Colors))[i].rgbtRed;
771 Colors[i].rgbGreen = (reinterpret_cast<RGBTRIPLE*>(Colors))[i].rgbtGreen;
772 Colors[i].rgbBlue = (reinterpret_cast<RGBTRIPLE*>(Colors))[i].rgbtBlue;
773 Colors[i].rgbReserved = 0;
774 }
775 }
776 }
777
778 // Locate & Read Bits, skipping Pad if any.
779 // Ignore offBits if it is zero, or if less than the current position--it's
780 // probably bad
781 //
782 if (offBits && offBits - static_cast<long>(headerSize+colorRead) > 0)
783 in.Skip(offBits - (headerSize+colorRead));
784 if (!in.Read(Bits, infoHeader.biSizeImage)) {
785 TRACEX(OwlGDI, 0, "Could not read DIB bits");
786 return false;
787 }
788
789 return true;
790}
791
792
793//
794/// Creates a TDib given a module instance and a resource name or int Id
795//
797:
798 Info(nullptr), Mask(nullptr), Colors(nullptr), Bits(nullptr),
799 NumClrs(0),
800 IsResHandle(false)
801{
804}
805
806
807//
808/// Loads this DIB from the given resource and returns true if successful.
809//
810bool
812{
814
815 // First, load the resource into a global memory block.
816 //
817 HRSRC resHandle = ::FindResource(instance, resId, RT_BITMAP);
819 if (!Handle) {
820 TRACEX(OwlGDI, 0, "Cannot access bitmap resource");
821 return false;
822 }
823 IsResHandle = true;
824
825 // Then update our pointers & other info.
826 //
828
829 // Under Win32, resources are read-only. So, to allow for later modification
830 // of the Dib, a copy must be made.
831 //
832 // Could postpone this until dib needed to be written on...
833 //
835
836 return true;
837}
838
839
840//
841/// Writes the DIB into an external file.
842///
843/// Returns true if the call is successful; otherwise returns false.
844//
845bool
847{
849
850 if (!file.IsOpen()) {
851 TRACEX(OwlGDI, 0, "Cannot open bitmap file '" << name << "' to write");
852 return false;
853 }
854
855 bool ok = Write(file, true);
856
857 file.Close();
858 if (!ok) {
859 TRACEX(OwlGDI, 0, "Disk error writing file '" << name << "'");
860 return false;
861 }
862 return true;
863}
864
865
866//
867/// Write this DIB to a file object.
868//
869bool
871{
872 TFileIO out(file);
873 return Write(out, writeFileHeader);
874}
875
876//
877// The ios version of the DIB read requires large data model since the buffers
878// are quite large.
879//
880
881
882//
883//
884//
885class TStreamOut : public TDib::IFileOut {
886 public:
887 TStreamOut( ostream& os) : Os(os) {}
888
889 virtual bool Write(void * buffer, long size)
890 {
891 return Os.write(reinterpret_cast<char*>(buffer), size).good();
892 }
893 private:
894 ostream& Os;
895};
896
897//
898/// Writes this DIB to an ostream.
899//
900bool
902{
903 TStreamOut out(os);
904 return Write(out, writeFileHeader);
905}
906
907
908//
909/// Writes the DIB into a file stream.
910//
911bool
913{
914 size_t size = ::GlobalSize(Handle);
915
916 // Write file header.
917 //
918 if (writeFileHeader)
919 {
920 size_t bfSize = size + sizeof(BITMAPFILEHEADER);
922 return false;
923
924 const char* begin = reinterpret_cast<const char*>(Info);
925 const char* end = static_cast<const char*>(Bits) + sizeof(BITMAPFILEHEADER);
926 size_t bfOffBits = end - begin;
928 return false;
929
931 bmf.bfType = BFT_BITMAP;//'BM';
932 bmf.bfSize = static_cast<DWORD>(bfSize);
933 bmf.bfReserved1 = 0;
934 bmf.bfReserved2 = 0;
935 bmf.bfOffBits = static_cast<DWORD>(bfOffBits);
936 if (!out.Write(&bmf, sizeof(bmf)))
937 return false;
938 }
939
940 // Write rest of dib, including dib header, color table & bits.
941 //
942 if (!IsRepresentable<long>(size))
943 return false;
944 if (!out.Write(Info, static_cast<long>(size))) // TODO: Widen parameter type to avoid this narrowing cast.
945 return false;
946
947 return true;
948}
949
950
951//
952/// Creates a DIB object with the given width, height, number of colors, mode
953/// values.
954//
955TDib::TDib(int width, int height, uint32 nColors, uint16 mode)
956{
957 PRECONDITION(width && height && nColors);
958
960 infoHeader.biSize = sizeof(BITMAPINFOHEADER);
961 infoHeader.biWidth = width;
962 infoHeader.biHeight = height;
963 infoHeader.biPlanes = 1;
964 infoHeader.biBitCount = NBits(nColors);
965 infoHeader.biCompression = BI_RGB;
966 uint32 bytes = ScanBytes(width, infoHeader.biBitCount);
967 infoHeader.biSizeImage = bytes * height;
968 infoHeader.biXPelsPerMeter = 0;
969 infoHeader.biYPelsPerMeter = 0;
970 infoHeader.biClrUsed = infoHeader.biBitCount > 8 ? 0 : nColors;
971 infoHeader.biClrImportant = 0;
972
973 // Setup all members based on infoHeader
974 //
976
977 // Initialize the color table--either Palette or RGB
978 //
979 Mode = mode;
980 if (Mode == DIB_PAL_COLORS) {
981 // Generate a 1:1 palette relative color table- it can later be translated
982 // to RGB given a palette.
983 //
984 for (uint i = 0; i < nColors; i++)
985 (reinterpret_cast<uint16*>(Colors))[i] = static_cast<uint16>(i);
986 }
987 else if(nColors){
988 // Get the system palette and convert to RGB quad format if exist support.
989 //
990 TScreenDC dc;
992 uint clrCnt = ::GetSystemPaletteEntries(dc, 0, nColors, reinterpret_cast<LPPALETTEENTRY>(Colors));
993 for (uint32 i = 0; i < clrCnt; i++) {
994 Swap(Colors[i].rgbRed, Colors[i].rgbBlue);
995 Colors[i].rgbReserved = 0;
996 }
997 }
998 }
999}
1000
1001
1002//
1003/// Creates a DIB object from the given resource bitmap and palette. If pal is 0
1004/// (the default), the default palette is used.
1005//
1007{
1008 BITMAP bm;
1009 bitmap.GetObject(bm);
1010
1012 infoHeader.biSize = sizeof(BITMAPINFOHEADER);
1013 infoHeader.biWidth = bm.bmWidth;
1014 infoHeader.biHeight = bm.bmHeight;
1015 infoHeader.biPlanes = 1;
1017 if (palette) {
1018 palette->GetObject(nColors);
1019 infoHeader.biBitCount = NBits(nColors);
1020 }
1021 else {
1022 infoHeader.biBitCount = uint16(bm.bmBitsPixel*bm.bmPlanes);
1023 nColors = static_cast<uint16>(NColors(infoHeader.biBitCount));
1024 }
1025 infoHeader.biCompression = BI_RGB;
1026 infoHeader.biSizeImage = ScanBytes(infoHeader.biWidth,
1027 infoHeader.biBitCount) * infoHeader.biHeight;
1028 infoHeader.biXPelsPerMeter = 0;
1029 infoHeader.biYPelsPerMeter = 0;
1030 infoHeader.biClrUsed = nColors;
1031 infoHeader.biClrImportant = 0;
1032
1033 // Setup all members based on infoHeader
1034 //
1036
1037 // Copy pixels from given bitmap into our new empty DIB, selecting palette
1038 // if provided
1039 //
1040 TScreenDC dc;
1041 if (palette)
1042 dc.SelectObject(*palette, false);
1043 dc.GetDIBits(bitmap, StartScan(), NumScans(), Bits, *Info, Usage());
1044}
1045
1046
1047//
1048/// Modifies this DIB so that the pixels and color table coincide with a given
1049/// palette.
1050/// !CQ 8bpp only!
1051//
1052void
1054{
1055 // Create a mapping from our current color table to the target palette
1056 //
1057 uint8 map[256];
1058 for (int i = 0; i < 256; i++)
1059 map[i] = static_cast<uint8>(pal.GetNearestPaletteIndex(GetColor(i)));
1060
1061 // Use the map to translate all of the pixels into indexes in the target
1062 // palette
1063 //
1064 uint8 * bits = reinterpret_cast<uint8 *>(GetBits());
1065 long size = Pitch() * Height();
1066 while (size--) {
1067 *bits = map[*bits];
1068 bits++;
1069 }
1070
1071 // Now copy the target palette into our color table
1072 //
1073 PALETTEENTRY pe[256];
1074 pal.GetPaletteEntries(0, 256, pe);
1076 for (int j = 0; j < 256; j++) {
1077 colorTab->rgbRed = pe[j].peRed;
1078 colorTab->rgbGreen = pe[j].peGreen;
1079 colorTab->rgbBlue = pe[j].peBlue;
1080 colorTab++;
1081 }
1082}
1083
1084
1085} // OWL namespace
1086
#define PRECONDITION(condition)
Definition checks.h:227
#define DIAG_DECLARE_GROUP(group)
Definition checks.h:404
#define TRACEX(group, level, message)
Definition checks.h:263
TBitmap is the GDI bitmap class derived from TGdiObject.
Definition gdiobjec.h:510
The clipboard class encapsulates the methods for the clipboard object of Windows.
Definition clipboar.h:32
HANDLE SetClipboardData(uint format, HANDLE handle)
Copy the data onto the clipboard in the format.
Definition clipboar.h:282
Class wrapper for management of color values.
Definition color.h:245
static const TColor LtMagenta
Static TColor object with fixed Value set by RGB(255, 0, 255).
Definition color.h:312
static const TColor SysBtnText
The symbolic system color value for the text on buttons.
Definition color.h:342
static const TColor Sys3dHilight
The symbolic system color value for highlighted 3-dimensional display elements (for edges facing the ...
Definition color.h:344
static const TColor SysWindowFrame
The symbolic system color value for the frame around each window.
Definition color.h:330
static const TColor LtYellow
Static TColor object with fixed Value set by RGB(255, 255, 0).
Definition color.h:310
static const TColor LtGray
Static TColor object with fixed Value set by RGB(192, 192, 192).
Definition color.h:306
static const TColor Sys3dShadow
The symbolic system color value for the shadow regions of 3-dimensional display elements (for edges f...
Definition color.h:340
static const TColor Sys3dFace
The symbolic system color value for the face color of 3-dimensional display elements.
Definition color.h:339
static const TColor Gray
Static TColor object with fixed Value set by RGB(128, 128, 128).
Definition color.h:307
static const TColor White
Static TColor object with fixed Value set by RGB(255, 255, 255).
Definition color.h:314
static const TColor SysWindow
The symbolic system color value for the background of each window.
Definition color.h:329
static const TColor Black
Static TColor object with fixed Value set by RGB(0, 0, 0).
Definition color.h:305
virtual int GetDeviceCaps(int index) const
Used under WIN3.1 or later, GetDeviceCaps returns capability information about this DC.
Definition dc.cpp:373
void SelectObject(const TBrush &brush)
Selects the given GDI brush object into this DC.
Definition dc.cpp:113
int GetDIBits(const TBitmap &bitmap, uint startScan, uint numScans, void *bits, const BITMAPINFO &info, uint16 usage)
The first version retrieves some or all of the bits from the given bitmap on this DC and copies them ...
Definition dc.h:2668
Internal DIB file Reda/Write functions talk to these interfaces.
Definition gdiobjec.h:923
Pseudo-GDI object Device Independent Bitmap (DIB) class.
Definition gdiobjec.h:795
uint NumScans() const
Returns the number of scans in this DIB.
Definition gdiobjec.h:1926
TColor GetColor(int entry) const
Returns the color for the given palette entry.
Definition dib.cpp:314
uint16 Usage() const
Returns the Mode for this DIB.
Definition gdiobjec.h:1954
const uint16 * GetIndices() const
Returns the bmiColors indexes of this DIB.
Definition gdiobjec.h:1711
uint16 GetIndex(int entry) const
Definition dib.cpp:373
int FindIndex(uint16 index)
Returns the palette entry corresponding to the given index.
Definition dib.cpp:399
@ MapHighlight
Definition gdiobjec.h:913
bool Write(TFile &file, bool writeFileHeader=false)
Write this DIB to a file object.
Definition dib.cpp:870
void MapUIColors(uint mapColors, const TColor *bkColor=nullptr)
Maps the UI colors to the value specified in the parameter, mapColors, which is one of the values of ...
Definition dib.cpp:446
bool Read(TFile &file, bool readFileHeader=false)
Read a Windows 3.x or PM 1.x device independent bitmap from a TFile Return true iff Dib was read OK.
Definition dib.cpp:571
void ResToMemHandle()
Under Win32, resources are read-only.
Definition dib.cpp:143
int FindColor(const TColor &color)
Returns the palette entry for the given color.
Definition dib.cpp:340
bool WriteFile(const tstring &filename)
Writes the DIB into an external file.
Definition dib.cpp:846
void SetColor(int entry, const TColor &color)
Sets the given color for the given palette entry.
Definition dib.cpp:328
bool LoadResource(HINSTANCE, TResId)
Loads this DIB from the given resource and returns true if successful.
Definition dib.cpp:811
int MapColor(const TColor &fromColor, const TColor &toColor, bool doAll=false)
Maps the first or all occurances of fromColor to the toColor in the current palette of this DIB.
Definition dib.cpp:355
int MapIndex(uint16 fromIndex, uint16 toIndex, bool doAll=false)
Maps the fromIndex to the toIndex in the current palette of this DIB.
Definition dib.cpp:413
bool ReadFile(const tstring &name)
Tests if the passed file is a Windows 3.x (or PM 1.x) DIB and if so read it.
Definition dib.cpp:549
int Pitch() const
Size of scan in bytes = Pixel Width * bits per pixel rounded up to a uint32 boundary.
Definition gdiobjec.h:1882
TDib()
Protected ctor- derived classes need to fill in handle & get info.
Definition dib.cpp:532
void MapToPalette(const TPalette &pal)
Modifies this DIB so that the pixels and color table coincide with a given palette.
Definition dib.cpp:1053
void ToClipboard(TClipboard &clipboard)
Moves this dib to the clipboard.
Definition dib.cpp:474
static int ScanBytes(long w, int bpp)
Width+bpp to dword aligned bytes.
Definition gdiobjec.h:1865
bool ChangeModeToRGB(const TPalette &pal)
Converts the existing color table in place to use absolute RGB values.
Definition dib.cpp:284
int Height() const
Returns the height of the DIB.
Definition gdiobjec.h:1840
void InfoFromHeader(const BITMAPINFOHEADER &infoHeader)
Given a BITMAPINFOHEADER, allocate a global buffer for Handle & init Info.
Definition dib.cpp:60
void SetIndex(int entry, uint16 index)
Sets the given index for the given entry.
Definition dib.cpp:387
bool ShouldDelete
Should object delete GDI handle in dtor?
Definition gdibase.h:82
virtual ~TDib()
Destruct a TDib by unlocking & freeing its global memory handle as required.
Definition dib.cpp:233
uint StartScan() const
Returns the starting scan line.
Definition gdiobjec.h:1916
HANDLE Handle
GDI handle of this object.
Definition gdibase.h:81
void InfoFromHandle()
Locks the global/res handle if needed and extracts the pointers and cached info maintained as member ...
Definition dib.cpp:88
bool ChangeModeToPal(const TPalette &pal)
Converts the existing color table in place to use palette relative values.
Definition dib.cpp:250
const void * GetBits() const
Returns the Bits data member for this DIB.
Definition gdiobjec.h:1727
const TRgbQuad * GetColors() const
Returns the bmiColors value of this DIB.
Definition gdiobjec.h:1695
The TFile class encapsulates standard file characteristics and operations.
Definition file.h:120
virtual uint64 Seek(int64 offset, TSeekDir origin=beg)
Repositions the file pointer to offset bytes from the specified origin.
Definition file.h:875
@ ReadOnly
Definition file.h:130
@ WriteOnly
Definition file.h:131
@ OpenExisting
Opens the file. The function fails if the file does not exist.
Definition file.h:151
@ PermExclusive
Definition file.h:141
@ CreateAlways
Creates a new file. The function overwrites the file if it exists.
Definition file.h:148
virtual uint32 Read(void *buffer, uint32 numBytes)
Reads numBytes from the file into buffer. The number of bytes read is returned.
Definition file.h:805
virtual bool Write(const void *buffer, uint32 numBytes)
Writes numbytes of buffer to the file.
Definition file.h:813
@ cur
Seek from the current position in the file.
Definition file.h:124
Root and abstract class for Windows object wrappers.
Definition gdibase.h:79
TPalette is the GDI Palette class derived from TGdiObject.
Definition gdiobjec.h:413
Wrapper for Windows' RBGQUAD type.
Definition color.h:433
Derived from TWindowDC, TScreenDC is a DC class that provides direct access to the screen bitmap.
Definition dc.h:610
static void Raise()
Construct a TXBadFormat exception from scratch, and throws it.
Definition file.cpp:62
static void Raise(uint resId=IDS_GDIFAILURE, HANDLE handle=0)
Throws the exception.
Definition gdibase.cpp:112
Definition of classes for clipboard Encapsulation.
#define BFT_BITMAP
Definition dib.cpp:22
Definition of abstract GDI object class and derived classes.
TAutoDelete
Flag for Handle ctors to control Handle deletion in dtor.
Definition gdibase.h:70
static void Raise()
Construct a TXOutOfMemory exception from scratch, and throw it.
Definition except.cpp:301
Definition of TMetafilePict, a MetaFile wrapper class.
Object Windows Library (OWLNext Core)
Definition animctrl.h:22
long NColors(uint16 bitCount)
Functions to convert number of bits to number of palette colors and back, and build an RGB COLORREF.
Definition color.cpp:188
unsigned long uint32
Definition number.h:34
uint16 NBits(long colors)
Return the number of bits required to represent a given number of colors.
Definition color.cpp:201
OWL_DIAGINFO
Definition animctrl.cpp:14
unsigned short uint16
Definition number.h:33
std::string tstring
Definition defs.h:79
unsigned int uint
Definition number.h:25
ObjectWindows exception class & function definitions.
void Swap(T &a, T &b)
Definition defs.h:365
Classes for window system structure and type encapsulation.