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
palette.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 TPalette, an encapsulation of the GDI Palette object
7//----------------------------------------------------------------------------
8#include <owl/pch.h>
9#include <owl/defs.h>
10#include <owl/gdiobjec.h>
11#include <owl/clipboar.h>
12#include <owl/file.h>
13#include <owl/filename.h>
14#include <memory.h>
15
16
17#if defined(__BORLANDC__)
18# pragma option -w-ccc // Disable "Condition is always true/false"
19#endif
20
21using namespace std;
22
23namespace owl {
24
26DIAG_DECLARE_GROUP(OwlGDI); // General GDI diagnostic group
27DIAG_DECLARE_GROUP(OwlGDIOrphan); // Orphan control tracing group
28
29//
30// Constructors
31//
32
33//
34/// Alias an existing palette handle. Assume ownership if autoDelete says so
35//
36/// Creates a TPalette object and sets the Handle data member to the given borrowed
37/// handle. The ShouldDelete data member defaults to false, ensuring that the
38/// borrowed handle will not be deleted when the C++ object is destroyed.
39//
47
48//
49/// Creates a TPalette object with values taken from the given clipboard.
50//
52:
53 TGdiObject(clipboard.GetClipboardData(CF_PALETTE))
54{
55 WARNX(OwlGDI, !Handle, 0, "Cannot create TPalette from the clipboard");
56 CheckValid();
59}
60
61//
62/// This public copy constructor creates a complete copy of the given palette object
63/// as in TPalette myPalette = yourPalette;
64//
65/// Always performs full, deep object copy
66//
68{
70 src.GetObject(nColors);
71 if (nColors) {
72 LOGPALETTE* logPal = reinterpret_cast<LOGPALETTE*>( new
73 uint8[sizeof(LOGPALETTE)+(nColors-1)*sizeof(PALETTEENTRY)]);
74
75 logPal->palVersion = 0x300; // !CQ check to see if we should use 0x400
76 logPal->palNumEntries = nColors;
77 src.GetPaletteEntries(0, nColors, logPal->palPalEntry);
79 delete[] logPal;
80 }
81 else
82 Handle = nullptr; // Force a failure
83
84 WARNX(OwlGDI, !Handle, 0, "Cannot create palette from palette " << static_cast<void*>(src.GetHandle()));
85 CheckValid();
87}
88
89//
90/// Creates a TPalette object from the given LOGPALETTE.
91//
93{
95 WARNX(OwlGDI, !Handle, 0, "Cannot create palette from LOGPALETTE @" << static_cast<const void*>(&logPalette));
96 CheckValid();
98}
99
100#if defined(OWL5_COMPAT)
101
102//
103/// Creates a TPalette object from the given LOGPALETTE.
104/// This overload is deprecated. Use the overload that takes a reference instead.
105//
107{
110 WARNX(OwlGDI, !Handle, 0, "Cannot create palette from LOGPALETTE @" << static_cast<const void*>(logPalette));
111 CheckValid();
113}
114
115#endif
116
117//
118/// Creates a TPalette object with count entries from the given entries array.
119//
121{
122 Init(entries, count);
123}
124
125//
126// Initializes a TPalette object with count entries from the given entries array.
127//
128void TPalette::Init(const PALETTEENTRY* entries, int count)
129{
130 LOGPALETTE* logPal = reinterpret_cast<LOGPALETTE*>(new uint8[
131 sizeof(LOGPALETTE)+(count-1)*sizeof(PALETTEENTRY) ]);
132
133 logPal->palVersion = 0x300;
134 logPal->palNumEntries = static_cast<uint16>(count);
135 memcpy(logPal->palPalEntry, entries, count*sizeof(PALETTEENTRY));
137 delete[] logPal;
138
139 WARNX(OwlGDI, !Handle, 0, "Cannot create palette from " << count <<
140 "palette entries @" << static_cast<const void*>(entries));
141 CheckValid();
143}
144
145//
146/// Creates a TPalette object from the color table following the given BITMAPINFO
147/// structure. This constructor works only for 2-color, 16-color, and 256-color
148/// bitmaps. A handle with value 0 (zero) is returned for other bitmaps, including
149/// 24-bit DIBs.
150//
152{
153 Create(&info, flags);
154}
155
156#if defined(OWL5_COMPAT)
157
158//
159/// Creates a TPalette object from the color table following the given BITMAPINFO
160/// structure. This constructor works only for 2-color, 16-color, and 256-color
161/// bitmaps. A handle with value 0 (zero) is returned for other bitmaps, including
162/// 24-bit DIBs.
163/// This overload is deprecated. Use the overload that takes a reference instead.
164//
166{
167 Create(info, flags);
168}
169
170#endif
171
172//
173/// Creates a TPalette object from the given DIB object. The flags argument
174/// represents the values of the LOGPALETTE data structure used to create the
175/// palette.
176//
178{
179 Create(dib.GetInfo(), flags);
180}
181
182//
183/// Read from file: *.dib,*.bmp,*.pal,*.aco,*.act
184//
186{
188 Handle = nullptr;
189
190 Read(fileName);
191
192 WARNX(OwlGDI, !Handle, 0, "Cannot create palette from file: " << fileName);
193
195 ShouldDelete = true;
197}
198
199//
200/// Accept a pointer to a BITMAPINFO structure and create a GDI logical
201/// palette from the color table which follows it, for 2, 16 and 256 color
202/// bitmaps. Fail for all others, including 24-bit DIB's
203///
204/// !CQ Don't fail for other formats!?
205//
206void
208{
210 const RGBQUAD * rgb = info->bmiColors;
211
212 // if the ClrUsed field of the header is non-zero,
213 // it means that we could have have a short color table.
214 //
215 uint16 nColors = uint16(info->bmiHeader.biClrUsed ?
216 info->bmiHeader.biClrUsed :
217 NColors(info->bmiHeader.biBitCount));
218
219 if (nColors) {
220 LOGPALETTE* logPal = reinterpret_cast<LOGPALETTE*>(
221 new uint8[sizeof(LOGPALETTE) + (nColors-1)*sizeof(PALETTEENTRY)]);
222
223 logPal->palVersion = 0x300; // Windows 3.0 version
224 logPal->palNumEntries = nColors;
225 for (uint16 n = 0; n < nColors; n++) {
226 logPal->palPalEntry[n].peRed = rgb[n].rgbRed;
227 logPal->palPalEntry[n].peGreen = rgb[n].rgbGreen;
228 logPal->palPalEntry[n].peBlue = rgb[n].rgbBlue;
229 logPal->palPalEntry[n].peFlags = static_cast<uint8>(flags);
230 }
232 delete[] logPal;
233 }
234 else
235 Handle = nullptr;
236
237 WARNX(OwlGDI, !Handle, 0, "Cannot create palette from bitmapinfo @" << static_cast<const void*>(info));
238 CheckValid();
240}
241
242//
243/// Moves this palette to the target Clipboard argument. If a copy is to be put on
244/// the Clipboard, use TPalette(myPalette).ToClipboard; to make a copy first. The
245/// handle in the temporary copy of the object is moved to the clipboard.
246/// ToClipboard sets ShouldDelete to false so that the object on the clipboard is
247/// not deleted. The handle will still be available for examination.
248//
249void
251{
252 if (Handle) {
254 ShouldDelete = false; // GDI object now owned by Clipboard
256 }
257}
258
259//
260/// Read palette from file
261//
262bool
264{
266 if (!file.IsOpen())
267 return false;
268
269 const tchar* lp = _tcsrchr(filename, _T('.'));
270 if(lp){
271 if(_tcsicmp(lp, _T(".pal"))==0) // check extension
272 return Read_PAL(file);
273 else if(_tcsicmp(lp,_T(".aco"))==0)
274 return Read_ACO(file);
275 else if(_tcsicmp(lp,_T(".act"))==0)
276 return Read_ACT(file);
277 else if(_tcsicmp(lp,_T(".bmp"))==0)
278 return Read_BMP(file);
279 else if(_tcsicmp(lp,_T(".dib"))==0)
280 return Read_BMP(file);
281 }
282 return false;
283}
284
285//
286/// Write this palette into file: *.dib,*.bmp,*.pal,*.aco,*.act
287//
288bool
290{
292 if (!file.IsOpen())
293 return false;
294
295 bool bOk = false;
296 const tchar* lp = _tcsrchr(filename, _T('.'));
297 if(lp){
298 if(_tcsicmp(lp, _T(".pal"))==0) // check extension
299 bOk = Write_PAL(file);
300 else if(_tcsicmp(lp, _T(".aco"))==0)
301 bOk = Write_ACO(file);
302 else if(_tcsicmp(lp, _T(".act"))==0)
303 bOk = Write_ACT(file);
304 else if(_tcsicmp(lp, _T(".bmp"))==0)
305 bOk = Write_BMP(file);
306 else if(_tcsicmp(lp, _T(".dib"))==0)
307 bOk = Write_BMP(file);
308 }
309 if(!bOk)
311
312 return bOk;
313}
314//------------------------------------------------------------------------------
315static TBinField PALHDR_Fields[] = {
316 {varSHORT,2, 1}, /* uint16 Version; */
317 {varSHORT,2, 1}, /* uint16 Count; */
318 {varEnd, 0, 0},
319};
320
321//
322/// read Microsoft *.pal format, return true if success
323//
324bool
326{
327 // Check whether it's a RIFF PAL file.
329 ckFile.Type = owlFCC('P','A','L',' ');
330 if(!file.Descent(ckFile, nullptr, TRiffFile::ffFindRiff)) {
331 WARNX(OwlGDI, 1, 0, "TPalette::Read_PAL() Not a RIFF or PAL file");
333 return false;
334 }
335 // Find the 'data' chunk.
337 ckChunk.CkId = owlFCC('d','a','t','a');
338 if (!file.Descent(ckChunk, &ckFile, TRiffFile::ffFindChunk)) {
339 WARNX(OwlGDI, 1, 0, "TPalette::Read_PAL() No data chunk in file");
341 return false;
342 }
343 // Allocate some memory for the data chunk.
344 int iSize = static_cast<int>(ckChunk.Size);
345 TAPointer<char> pdata(new char[iSize]);
347 // Read the data chunk.
348 if(!file.ReadStruct((char*)pLogPal, PALHDR_Fields, boLittle_Endian)){
349 WARNX(OwlGDI, 1, 0, "TPalette::Read_PAL() Failed to PAL Colors, line" << __LINE__);
350 return false;
351 }
352 uint count = (iSize - sizeof(uint16)*2);
353 if (file.Read(pLogPal->palPalEntry, count) == TFILE_ERROR) {
354 WARNX(OwlGDI, 1, 0, "TPalette::Read_PAL() Failed to PAL Colors, line" << __LINE__);
355 return false;
356 }
357 // The data chunk should be a LOGPALETTE structure
358 // that we can create a palette from.
359 if (pLogPal->palVersion != 0x300) {
360 WARNX(OwlGDI, 1, 0, "TPalette::Read_PAL(): Invalid version number");
362 return false;
363 }
364 // Get the number of entries.
365 if (pLogPal->palNumEntries <= 0){
366 WARNX(OwlGDI, 1, 0, "TPalette::Read_PAL(): No colors in palette");
368 return false;
369 }
371 return true;
372}
373
374/// write Microsoft *.pal format
375///
376/// return true if success
377bool
379{
380 // Create a RIFF chunk for a PAL file.
382 ckFile.Size = 0; // Corrected later
383 ckFile.Type = owlFCC('P','A','L',' ');
384 if (!file.CreateChunk(ckFile, TRiffFile::cfCreateRiff)) {
385 WARNX(OwlGDI, 1, 0, "TPalette::Write_PAL() Failed to create RIFF-PAL chunk");
386 return false;
387 }
388 // Create the LOGPALETTE data which will become
389 // the data chunk.
392 if (!nColors){
393 WARNX(OwlGDI, 1, 0, "TPalette::Write_PAL() no colors in palette");
394 return false;
395 }
396 int iSize = sizeof(LOGPALETTE)+(nColors-1)*sizeof(PALETTEENTRY);
397 TAPointer<char> pdata(new char[iSize]);
398 LOGPALETTE* logPal = reinterpret_cast<LOGPALETTE*>((char*)pdata);
399 logPal->palVersion = 0x300;
400 logPal->palNumEntries = nColors;
401 GetPaletteEntries(0, nColors, logPal->palPalEntry);
402
403 // create the data chunk.
405 ckData.Size = iSize;
406 ckData.CkId = owlFCC('d','a','t','a');
407 if (!file.CreateChunk(ckData)) {
408 WARNX(OwlGDI, 1, 0, "TPalette::Write_PAL() Failed to create data chunk");
409 return false;
410 }
411 // Write the data chunk.
412 if(!file.Write((char*)pdata, iSize)) {
413 WARNX(OwlGDI, 1, 0, "TPalette::Write_PAL() Failed to write data chunk");
414 return false;
415 }
416 // Ascend from the data chunk which will correct the length.
417 file.Ascent(ckData);
418 // Ascend from the RIFF-PAL chunk.
419 file.Ascent(ckFile);
420
421 return true;
422}
423/* -------------------------------------------------------------------------- */
424/// convert HSL to RGB
425///
426/// given h,s,l on [0..1],return r,g,b on [0..1]
427void HSL_to_RGB(double& h, double& sl, double& l, double* r, double* g, double* b)
428{
429 double v;
430 v = (l <= 0.5) ? (l * (1.0 + sl)) : (l + sl - l * sl);
431 if (v <= 0)
432 *r = *g = *b = 0.0;
433 else {
434 double m;
435 double sv;
436 int sextant;
437 double fract, vsf, mid1, mid2;
438
439 m = l + l - v;
440 sv = (v - m ) / v;
441 h *= 6.0;
442 sextant = static_cast<int>(h); //JJH added static cast
443 fract = h - sextant;
444 vsf = v * sv * fract;
445 mid1 = m + vsf;
446 mid2 = v - vsf;
447 switch (sextant) {
448 case 0: *r = v; *g = mid1; *b = m; break;
449 case 1: *r = mid2; *g = v; *b = m; break;
450 case 2: *r = m; *g = v; *b = mid1; break;
451 case 3: *r = m; *g = mid2; *b = v; break;
452 case 4: *r = mid1; *g = m; *b = v; break;
453 case 5: *r = v; *g = m; *b = mid2; break;
454 }
455 }
456}
457#include <pshpack1.h>
458/// ACO header
459struct ACO_Hdr{
460 uint16 Version; ///< Version== 1
461 uint16 Count; ///< number of color
462};
463static TBinField ACO_HdrFields[] = {
464 {varSHORT,2, 1}, /* uint16 Version; */
465 {varSHORT,2, 1}, /* uint16 Count; */
466 {varEnd, 0, 0},
467};
468/// ACO color structure
469struct ACO_Color{
470 uint16 clrSpace; ///< color space
471 uint16 Color1; ///< color value1
472 uint16 Color2; ///< color value2
473 uint16 Color3; ///< color value3
474 uint16 Color4; ///< color value4
475};
476static TBinField ACO_ColorFields[] = {
477 {varSHORT,2, 1}, /* uint16 clrSpace; */
478 {varSHORT,2, 1}, /* uint16 Color1; */
479 {varSHORT,2, 1}, /* uint16 Color2; */
480 {varSHORT,2, 1}, /* uint16 Color3; */
481 {varSHORT,2, 1}, /* uint16 Color4; */
482 {varEnd, 0, 0},
483};
484struct MLOGPALETTE { // lgpl
485 WORD palVersion;
486 WORD palNumEntries;
487 PALETTEENTRY palPalEntry[256];
488};
489#include <poppack.h>
490
491#if !defined(CMYK)
492#define CMYK(c,m,y,k) (static_cast<COLORREF>((((BYTE)(c)|((WORD)((BYTE)(m))<<8))|(((DWORD)(BYTE)(y))<<16))|(((DWORD)(BYTE)(k))<<24)))
493/* Macros to retrieve CMYK values from a COLORREF */
494#define GetCValue(cmyk) ((BYTE)(cmyk))
495#define GetMValue(cmyk) ((BYTE)((cmyk)>> 8))
496#define GetYValue(cmyk) ((BYTE)((cmyk)>>16))
497#define GetKValue(cmyk) ((BYTE)((cmyk)>>24))
498#endif
499
500/* -------------------------------------------------------------------------- */
501/// Read Adobe Photoshop *.ACO color table
502///
503/// return true if success
504//
506{
507 ACO_Hdr hdr;
508 // Read the Header.
509 if(!file.ReadStruct(&hdr, ACO_HdrFields, boBig_Endian)){
510 WARNX(OwlGDI, 1, 0, "TPalette::Read_ACO() Failed to read ACO header");
511 return false;
512 }
513 TRACEX(OwlGDI, 1, "TPalette::Read_ACO() Data for header: hdr.Version = " << dec << hdr.Version <<", hdr.Count = " << hdr.Count);
514 if(hdr.Version != 1){ // equial to 1 ///////////////////////////////
515 WARNX(OwlGDI, 1, 0, "TPalette::Read_ACO() Invalid version number");
517 return false;
518 }
519
520 TAPointer<ACO_Color> clr(new ACO_Color[hdr.Count]);
521
522 // Read the Colors.
523 for(int i = 0; i < hdr.Count; i++){
524 if(!file.ReadStruct((char*)&clr[i], ACO_ColorFields, boBig_Endian)){
525 WARNX(OwlGDI, 1, 0, "TPalette::Read_ACO() Failed to ACO Colors, line" << __LINE__);
526 return false;
527 }
528 }
529#if defined(__TRACE)
530 TRACEX(OwlGDI, 1, "TPalette::Read_ACO() Data for Colors:");
531 for (int j= 0; j < hdr.Count; j++){
532 TRACEX(OwlGDI, 1, "TPalette::Read_ACO() index("<< dec << j << "), clrSpace("
533 << clr[j].clrSpace << "), Color1("<< clr[j].Color1<< "), Color2(" <<
534 clr[j].Color2<< "), Color3("<< clr[j].Color3<<"), Color4("<<
535 clr[j].Color4<< ")");
536 }
537#endif
538 MLOGPALETTE LogPal;
539 LogPal.palVersion = 0x300;
540 LogPal.palNumEntries = 256;
541 memset(&LogPal.palPalEntry, 0, sizeof(LogPal.palPalEntry));
542
543 //////////////////////////////////////////////////////////////////////////////
544 // copy color values from ACO_Clr to logical palette
545 uint colors = 0;
546
547 // only 256 colors use !!!!!!!!!!!!!!!!!!
548 if(hdr.Count > 256)
549 hdr.Count = 256;
550
551 for (int k= 0; k < hdr.Count; k++){
552 switch(clr[k].clrSpace){
553 default:
554 break;
555
556 case 0: // RGB
557 LogPal.palPalEntry[k].peRed = uint8(clr[k].Color1*255ul/65535u);
558 LogPal.palPalEntry[k].peGreen = uint8(clr[k].Color2*255ul/65535u);
559 LogPal.palPalEntry[k].peBlue = uint8(clr[k].Color3*255ul/65535u);
560 LogPal.palPalEntry[k].peFlags = 0;
561 break;
562
563 // not checked
564 case 1: { // HSB (HSL) ?????????????????????????????????????
565 double h,s,l,r,g,b;
566 h = clr[k].Color1/65535.0;
567 s = clr[k].Color2/65535.0;
568 l = clr[k].Color3/65535.0;
569 HSL_to_RGB(h, s, l, &r, &g, &b);
570
571 LogPal.palPalEntry[k].peRed = uint8(r*255u);
572 LogPal.palPalEntry[k].peGreen = uint8(g*255u);
573 LogPal.palPalEntry[k].peBlue = uint8(b*255u);
574 LogPal.palPalEntry[k].peFlags = 0;
575 }
576 break;
577
578 // not checked
579 case 2: { // CMYK
580 COLORREF clrRef = CMYK( uint8(clr[k].Color1*255ul/65535u),
581 uint8(clr[k].Color2*255ul/65535u),
582 uint8(clr[k].Color3*255ul/65535u),
583 uint8(clr[k].Color4*255ul/65535u)
584 );
585 LogPal.palPalEntry[k].peRed = GetRValue(clrRef);
586 LogPal.palPalEntry[k].peGreen = GetGValue(clrRef);
587 LogPal.palPalEntry[k].peBlue = GetBValue(clrRef);
588 LogPal.palPalEntry[k].peFlags = 0;
589 break;
590 }
591
592 // if I must do it also ??????????????????
593 //case 7: // LAB
594 // LogPal.palPalEntry[k].peRed = uint8(clr[k].Color1*255ul/65535u);
595 // LogPal.palPalEntry[k].peGreen = uint8(clr[k].Color2*255ul/65535u);
596 // LogPal.palPalEntry[k].peBlue = uint8(clr[k].Color3*255ul/65535u);
597 // LogPal.palPalEntry[k].peFlags = 0;
598 // break;
599
600 // not checked
601 case 8: // GrayScale
602 LogPal.palPalEntry[k].peRed = uint8(clr[k].Color1*255ul/10000u);
603 LogPal.palPalEntry[k].peGreen = uint8(clr[k].Color1*255ul/10000u);
604 LogPal.palPalEntry[k].peBlue = uint8(clr[k].Color1*255ul/10000u);
605 LogPal.palPalEntry[k].peFlags = 0;
606 break;
607 }
608 colors++;
609 }
610 if(!colors){
611 WARNX(OwlGDI, 1, 0, "TPalette::Read_ACO() Error no colors found.");
612 //TXGdi::Raise(IDS_BADFORMAT);
613 return false;
614 }
616 return true;
617}
618/* -------------------------------------------------------------------------- */
619/// Write Adobe Photoshop *.ACO color table
620///
621/// return true if success
623{
624 // Create the LOGPALETTE data which will become
625 // the data chunk.
628 if (!nColors){
629 WARNX(OwlGDI, 1, 0, "TPalette::Write_ACO() Error no colors in palette");
631 return false;
632 }
635
636 ACO_Hdr hdr;
637 hdr.Version = 0x1;
638 hdr.Count = nColors;
639
640 // Write the Header.
641 if(!file.WriteStruct(&hdr, ACO_HdrFields, boBig_Endian)){
642 WARNX(OwlGDI, 1, 0, "TPalette::Write_ACO() Failed to write ACO header");
643 return false;
644 }
645
646 ACO_Color clr[256];
647 for (int i= 0; i < nColors; i++){
648 clr[i].clrSpace = 0; // RGB
649 clr[i].Color1 = uint16(pColors[i].peRed*65535ul/255);
650 clr[i].Color2 = uint16(pColors[i].peGreen * 65535ul/255);
651 clr[i].Color3 = uint16(pColors[i].peBlue * 65535ul/255);
652 clr[i].Color4 = 0;
653 }
654 // Read the Colors.
655 for(int j = 0; j < nColors; j++){
656 if(!file.WriteStruct(reinterpret_cast<char*>(&clr[j]), ACO_ColorFields, boBig_Endian)){
657 WARNX(OwlGDI, 1, 0, "TPalette::Write_ACO() Failed to write ACO Colors, line" << __LINE__);
658 return false;
659 }
660 }
661 return true;
662}
663// -----------------------------------------------------------------------------
664/// ACT color structure
665struct ACT_Color{
666 uint8 Red; ///< Red compponent
667 uint8 Green; ///< Green compponent
668 uint8 Blue; ///< Blue compponent
669};
670// -----------------------------------------------------------------------------
671/// Read Adobe Photoshop *.ACT color table
672///
673/// return true if success
675{
676 MLOGPALETTE LogPal;
677 LogPal.palVersion = 0x300;
678 LogPal.palNumEntries = 256;
679 memset(&LogPal.palPalEntry, 0, sizeof(LogPal.palPalEntry));
680
681 ACT_Color clr[256];
682
683 // Read the Color table.
684 if(file.Read((char*)&clr, sizeof(clr)) == TFILE_ERROR){
685 WARNX(OwlGDI, 1, 0, "TPalette::Read_ACT() Failed to read ACT colors");
686 return false;
687 }
688 for (int i= 0; i < 256; i++){
689 LogPal.palPalEntry[i].peRed = clr[i].Red;
690 LogPal.palPalEntry[i].peGreen = clr[i].Green;
691 LogPal.palPalEntry[i].peBlue = clr[i].Blue;
692 LogPal.palPalEntry[i].peFlags = 0;
693 }
695 return true;
696}
697/* -------------------------------------------------------------------------- */
698/// Read Adobe Photoshop *.ACT color table
699///
700/// return true if success
702{
703 // Create the LOGPALETTE data which will become
706 if (!nColors){
707 WARNX(OwlGDI, 1, 0, "TPalette::Write_ACT() Error no colors in palette");
708 return false;
709 }
712
713 ACT_Color clr[256];
714 int i = 0;
715 for (; i < nColors; i++){
716 clr[i].Red = pColors[i].peRed;
717 clr[i].Green = pColors[i].peGreen;
718 clr[i].Blue = pColors[i].peBlue;
719 }
720 for (; i < 256; i++){
721 clr[i].Red = 0;
722 clr[i].Green = 0;
723 clr[i].Blue = 0;
724 }
725
726 // Write the data
727 if(!file.Write(reinterpret_cast<char*>(&clr), sizeof(clr))) {
728 WARNX(OwlGDI, 1, 0, "TPalette::Write_ACT() Failed to write ACT data");
729 return false;
730 }
731 return true;
732}
733/* -------------------------------------------------------------------------- */
734/// Read color table from *.DIB
735///
736/// return true if success
738{
739 // Read the Header.
741 // Read the Header.
742 if(file.Read(&bmf, sizeof bmf) == TFILE_ERROR){
743 WARNX(OwlGDI, 1, 0, "TPalette::Read_BMP() Failed to read BMP header");
744 return false;
745 }
746 uint16 bmp_id = 0x4D42; // 'BM'
747 if(bmf.bfType != bmp_id) {
748 WARNX(OwlGDI, 1, 0, "TPalette::Read_BMP() Not a Windows 3.x or PM 1.x bitmap file");
750 return false;
751 }
752 // Read bitmap header size & check it. It must be one of the two known header
753 // sizes.
754 // Will add BITMAPV4HEADER support when available
756 if (file.Read(reinterpret_cast<char*>(&headerSize), sizeof headerSize) == TFILE_ERROR ||
757 (headerSize != sizeof(BITMAPCOREHEADER) && headerSize != sizeof(BITMAPINFOHEADER)))
758 {
759 WARNX(OwlGDI, 1, 0, "TPalette::Read_BMP() Not a Windows 3.x or PM 1.x bitmap file");
761 return false;
762 }
764 int ClrUsed;
765
766 // If this is a PM 1.x DIB, read the core header & copy over to the Info header
767 bool isCore = headerSize == sizeof(BITMAPCOREHEADER);
768 if (isCore) {
769 // Read in the rest of the core header, aborting if it is truncated
771 if (file.Read(reinterpret_cast<char*>(&coreHeader.bcWidth),
772 static_cast<int>(headerSize)-sizeof(uint32))==TFILE_ERROR) {
773 WARNX(OwlGDI, 1, 0, "TPalette::Read_BMP() Invalid PM 1.x DIB Header");
775 return false;
776 }
777 BitCount = coreHeader.bcBitCount;
778 biPlanes = coreHeader.bcPlanes;
779 ClrUsed = 0;
780 }
781 else {
783 infoHeader.biSize = sizeof(BITMAPINFOHEADER);
784 // Read in the rest of the info header, aborting if it is truncated
785 if (file.Read((char*)&infoHeader.biWidth,
786 static_cast<int>(headerSize)-sizeof(uint32))==TFILE_ERROR){
787 WARNX(OwlGDI, 1, 0, "TPalette::Read_BMP() Invalid Win 3.x DIB Header");
789 return false;
790 }
791 BitCount = infoHeader.biBitCount;
792 biPlanes = infoHeader.biPlanes;
793 ClrUsed = infoHeader.biClrUsed;
794 }
795 // Check number of planes. Windows supports only 1 plane DIBs
796 if (biPlanes != 1) {
797 WARNX(OwlGDI, 1, 0, "TPalette::Read_BMP() Invalid number of planes in DIB");
799 return false;
800 }
801
802 // Fill in the default value for biClrsUsed, if not supplied, using the
803 // bit count. Will remain 0 for 16bpp or greater.
804 if (!ClrUsed)
806
807 // Read color table directly into allocated memory
808 // Walk backwards & expand to RGBQUADs if it is a PM Core DIB
809 int colorRead = isCore ? // Color table size on disk
810 static_cast<int>(ClrUsed) * sizeof(RGBTRIPLE) :
811 static_cast<int>(ClrUsed) * sizeof(RGBQUAD);
812
813 RGBQUAD Colors[256];
814 if(ClrUsed){
815 if (file.Read((char*)&Colors, colorRead)==TFILE_ERROR) {
816 WARNX(OwlGDI, 1, 0, "TPalette::Read_BMP() Could not read DIB color table");
817 return false;
818 }
819 if(isCore) {
820 for (int i = int(ClrUsed-1); i >= 0; i--) {
821 Colors[i].rgbRed = ((RGBTRIPLE*)Colors)[i].rgbtRed;
822 Colors[i].rgbGreen = ((RGBTRIPLE*)Colors)[i].rgbtGreen;
823 Colors[i].rgbBlue = ((RGBTRIPLE*)Colors)[i].rgbtBlue;
824 }
825 }
826 }
827 MLOGPALETTE LogPal;
828 LogPal.palVersion = 0x300;
829 LogPal.palNumEntries = 256;
830 memset(&LogPal.palPalEntry, 0, sizeof(LogPal.palPalEntry));
831 int i = 0;
832 for(; i < ClrUsed; i++){
833 LogPal.palPalEntry[i].peRed = Colors[i].rgbRed;
834 LogPal.palPalEntry[i].peGreen = Colors[i].rgbGreen;
835 LogPal.palPalEntry[i].peBlue = Colors[i].rgbBlue;
836 LogPal.palPalEntry[i].peFlags = 0;
837 }
838 for(; i < 256; i++){
839 LogPal.palPalEntry[i].peRed = 0;
840 LogPal.palPalEntry[i].peGreen = 0;
841 LogPal.palPalEntry[i].peBlue = 0;
842 LogPal.palPalEntry[i].peFlags = 0;
843 }
845 return true;
846}
847/* -------------------------------------------------------------------------- */
848/// Write Color table to *.DIB with dimensions 1x1 pixel
849///
850/// return true if success
852{
854 bmf.bfType = 0x4D42; // 'BM'
855 bmf.bfSize = sizeof(bmf) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*256 + sizeof(uint8);
856 bmf.bfReserved1 = 0;
857 bmf.bfReserved2 = 0;
858 bmf.bfOffBits = sizeof bmf + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*256;
859 if(!file.Write((char*)&bmf, sizeof bmf)){
860 WARNX(OwlGDI, 1, 0, "TPalette::Write_BMP() Error write header");
861 return false;
862 }
863
865 infoHeader.biSize = sizeof(BITMAPINFOHEADER);
866 infoHeader.biWidth = 1;
867 infoHeader.biHeight = 1;
868 infoHeader.biPlanes = 1;
869 infoHeader.biBitCount = 8;
870 infoHeader.biCompression = BI_RGB; // No compression
871 infoHeader.biSizeImage = 1; // Calculate this below
872 infoHeader.biXPelsPerMeter = 0; // Zero is OK
873 infoHeader.biYPelsPerMeter = 0; // Zero is OK
874 infoHeader.biClrUsed = 256; // Calculate this below
875 infoHeader.biClrImportant = 256; // Zero is OK
876
877 // Write the data
878 if(!file.Write((char*)&infoHeader, sizeof(infoHeader))){
879 WARNX(OwlGDI, 1, 0, "TPalette::Write_BMP() Failed to write BMP Info header");
880 return false;
881 }
882
885 if (!nColors){
886 WARNX(OwlGDI, 1, 0, "TPalette::Write_BMP() no colors in palette");
887 return false;
888 }
891
892 RGBQUAD clr[256];
893 int i = 0;
894 for (; i < nColors; i++){
895 clr[i].rgbRed = pColors[i].peRed;
896 clr[i].rgbGreen = pColors[i].peGreen;
897 clr[i].rgbBlue = pColors[i].peBlue;
898 clr[i].rgbReserved = 0;
899 }
900 for (; i < 256; i++){
901 clr[i].rgbRed = 0;
902 clr[i].rgbGreen = 0;
903 clr[i].rgbBlue = 0;
904 clr[i].rgbReserved = 0;
905 }
906
907 // Write the Colors
908 if(!file.Write((char*)&clr, sizeof(clr))) {
909 WARNX(OwlGDI, 1, 0, "TPalette::Write_BMP() Failed to write BMP Colors");
910 return false;
911 }
912 // Write the 1x1 bitmap
913 uint32 pixel = 0;
914 if(!file.Write((char*)&pixel, sizeof(pixel))) {
915 WARNX(OwlGDI, 1, 0, "TPalette::Write_BMP() Failed to write BMP 1x1 bitmap");
916 return false;
917 }
918 return true;
919}
920
921} // OWL namespace
#define WARNX(group, condition, level, message)
Definition checks.h:277
#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
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
Pseudo-GDI object Device Independent Bitmap (DIB) class.
Definition gdiobjec.h:795
@ WriteOnly
Definition file.h:131
@ PermExclusive
Definition file.h:141
@ CreateAlways
Creates a new file. The function overwrites the file if it exists.
Definition file.h:148
The TFileName class constructs filenames.
Definition filename.h:37
bool Remove() const
Deletes this file associated with this name if possible; otherwise attempts to delete the directory a...
Definition filename.cpp:899
GdiObject is the root, pseudo-abstract base class for ObjectWindows' GDI (Graphics Device Interface) ...
Definition gdiobjec.h:68
static void RefInc(HANDLE handle)
Increments by 1 the reference count of the object associated with the given handle.
Definition gdiobjec.cpp:178
void CheckValid(uint resId=IDS_GDIFAILURE)
Definition gdibase.cpp:49
static void RefRemove(HANDLE handle)
Removes the reference entry to the object with the given handle.
Definition gdiobjec.cpp:163
bool ShouldDelete
Should object delete GDI handle in dtor?
Definition gdibase.h:82
static void RefAdd(HANDLE handle, TType type)
RefAdd adds a reference entry for the object with the given handle and type.
Definition gdiobjec.cpp:137
HANDLE Handle
GDI handle of this object.
Definition gdibase.h:81
TPalette is the GDI Palette class derived from TGdiObject.
Definition gdiobjec.h:413
TPalette(HPALETTE handle, TAutoDelete autoDelete=NoAutoDelete)
Alias an existing palette handle. Assume ownership if autoDelete says so.
Definition palette.cpp:40
bool Write_BMP(TRiffFile &file)
Write palette to BMP 1x1 file.
Definition palette.cpp:851
bool Read_BMP(TRiffFile &file)
Read palette from BMP file.
Definition palette.cpp:737
uint GetPaletteEntries(uint16 start, uint16 count, PALETTEENTRY *entries) const
Retrieves a range of entries in this logical palette and places them in the entries array.
Definition gdiobjec.h:1306
bool Write_PAL(TRiffFile &file)
Write Microsoft palette to file.
Definition palette.cpp:378
bool GetObject(uint16 &numEntries) const
Finds the number of entries in this logical palette and sets the value in the numEntries argument.
Definition gdiobjec.h:1336
bool Write(const tchar *fileName)
Write this palette into file: *.dib,*.bmp,*.pal,*.aco,*.act.
Definition palette.cpp:289
bool Read_ACO(TRiffFile &file)
Read Adobe palette from file.
Definition palette.cpp:505
void Create(const BITMAPINFO *info, uint flags)
Accept a pointer to a BITMAPINFO structure and create a GDI logical palette from the color table whic...
Definition palette.cpp:207
bool Read_PAL(TRiffFile &file)
Read Microsoft palette from file.
Definition palette.cpp:325
void ToClipboard(TClipboard &Clipboard)
Moves this palette to the target Clipboard argument.
Definition palette.cpp:250
bool Write_ACT(TRiffFile &file)
Write Adobe palette to file.
Definition palette.cpp:701
bool Read(const tchar *fileName)
Read palette from file.
Definition palette.cpp:263
bool Write_ACO(TRiffFile &file)
Write Adobe palette to file.
Definition palette.cpp:622
bool Read_ACT(TRiffFile &file)
Read Adobe palette from file.
Definition palette.cpp:674
The TRiffFile class is used for reading and writing RIFF files.
Definition file.h:563
static void Raise()
Construct a TXBadFormat exception from scratch, and throws it.
Definition file.cpp:62
Definition of classes for clipboard Encapsulation.
#define _tcsicmp
Definition cygwin.h:76
#define _T(x)
Definition cygwin.h:51
#define _tcsrchr
Definition cygwin.h:86
Definition of abstract GDI object class and derived classes.
TAutoDelete
Flag for Handle ctors to control Handle deletion in dtor.
Definition gdibase.h:70
#define owlFCC(ch0, ch1, ch2, ch3)
Definition file.h:531
#define TFILE_ERROR
Definition file.h:105
@ boLittle_Endian
LSB at lowest address: Intel //.
Definition file.h:49
@ boBig_Endian
MSB at lowest address: Motorola //.
Definition file.h:50
@ varEnd
Definition file.h:69
@ varSHORT
Definition file.h:73
Reliable platform independent header for common memory and string functions.
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 char uint8
Definition number.h:32
void HSL_to_RGB(double &h, double &sl, double &l, double *r, double *g, double *b)
convert HSL to RGB
Definition palette.cpp:427
char tchar
Definition defs.h:77
OWL_DIAGINFO
Definition animctrl.cpp:14
unsigned short uint16
Definition number.h:33
unsigned int uint
Definition number.h:25
General definitions used by all ObjectWindows programs.
#define CMYK(c, m, y, k)
Definition palette.cpp:492
The TBinField struct describes a group of like-typed fields in a structure to be read or written usin...
Definition file.h:98
RIFF chunk information data structure.
Definition file.h:541