27 constexpr
unsigned int Step = 5;
79 register unsigned int Best;
80 register uint_fast32_t Value;
81 register uint_fast32_t Maximum;
82 IndexType BestIndex [NUMBER_OF_NEIGHBOURS];
84 assert(NumberOfNeighbours == 3 or NumberOfNeighbours == 5 or
85 NumberOfNeighbours == 8);
87 Maximum = Neighbour [0].Attraction *
88 RepulsionPointer [Neighbour [0].Index].Repulsion;
89 BestIndex [0] = Neighbour [0].Index;
90 if ((Value = Neighbour [1].Attraction *
91 RepulsionPointer [Neighbour [1].Index].Repulsion) >= Maximum)
95 BestIndex [0] = Neighbour [1].Index;
99 BestIndex [1] = Neighbour [1].Index;
102 if ((Value = Neighbour [2].Attraction *
103 RepulsionPointer [Neighbour [2].Index].Repulsion) >= Maximum)
107 BestIndex [0] = Neighbour [2].Index;
111 BestIndex [Best++] = Neighbour [2].Index;
112 if (NumberOfNeighbours > 3)
114 if ((Value = Neighbour [3].Attraction *
115 RepulsionPointer [Neighbour [3].Index].Repulsion) >=
120 BestIndex [0] = Neighbour [3].Index;
124 BestIndex [Best++] = Neighbour [3].Index;
125 if ((Value = Neighbour [4].Attraction *
126 RepulsionPointer [Neighbour [4].Index].Repulsion) >=
131 BestIndex [0] = Neighbour [4].Index;
135 BestIndex [Best++] = Neighbour [4].Index;
136 if (NumberOfNeighbours > 5)
138 if ((Value = Neighbour [5].Attraction *
139 RepulsionPointer [Neighbour [5].Index].
140 Repulsion) >= Maximum)
144 BestIndex [0] = Neighbour [5].Index;
150 if ((Value = Neighbour [6].Attraction *
151 RepulsionPointer [Neighbour [6].Index].
152 Repulsion) >= Maximum)
156 BestIndex [0] = Neighbour [6].Index;
162 if ((Value = Neighbour [7].Attraction *
163 RepulsionPointer [Neighbour [7].Index].
164 Repulsion) >= Maximum)
168 BestIndex [0] = Neighbour [7].Index;
177 return BestIndex [0];
179 return UINT_FAST32_MAX;
180 return BestIndex [CurrentGenerator.Generate(Best - 1)];
223 uint_fast32_t Probability [NUMBER_OF_NEIGHBOURS];
225 assert(NumberOfNeighbours == 3 or NumberOfNeighbours == 5 or
226 NumberOfNeighbours == 8);
227 Probability [0] = Neighbour [0].Attraction *
228 RepulsionPointer [Neighbour [0].Index].Repulsion;
229 Probability [1] = Neighbour [1].Attraction *
230 RepulsionPointer [Neighbour [1].Index].Repulsion;
231 Probability [2] = Neighbour [2].Attraction *
232 RepulsionPointer [Neighbour [2].Index].Repulsion;
233 if (NumberOfNeighbours > 3)
235 Probability [3] = Neighbour [3].Attraction *
236 RepulsionPointer [Neighbour [3].Index].Repulsion;
237 Probability [4] = Neighbour [4].Attraction *
238 RepulsionPointer [Neighbour [4].Index].Repulsion;
239 if (NumberOfNeighbours > 5)
241 Probability [5] = Neighbour [5].Attraction *
242 RepulsionPointer [Neighbour [5].Index].
244 Probability [6] = Neighbour [6].Attraction *
245 RepulsionPointer [Neighbour [6].Index].
247 Probability [7] = Neighbour [7].Attraction *
248 RepulsionPointer [Neighbour [7].Index].
252 if ((Index = CurrentGenerator.Select(Probability,
253 NumberOfNeighbours)) == UINT_MAX)
254 return UINT_LEAST32_MAX;
255 return Neighbour [Index].Index;
300 register const uint8_t* ColorPointer,
301 register unsigned int Steps,
303 PixelInformationPointer,
306 register PathFunction PathFinder)
const noexcept
308 register unsigned int PathMaximum;
310 PathMaximum = ColorPointer [PixelIndex];
311 assert(PathMaximum < MaximumValue);
312 RepulsionPointer [PixelIndex].Repulsion =
313 RepulsionTable [++RepulsionPointer [PixelIndex].Visitors];
314 for (; Steps > 0; --Steps)
316 if ((PixelIndex = (PixelInformationPointer [PixelIndex].*
317 PathFinder)(CurrentGenerator, RepulsionPointer)) >
320 RepulsionPointer [PixelIndex].Repulsion =
321 RepulsionTable [++RepulsionPointer [PixelIndex].
323 if (ColorPointer [PixelIndex] > PathMaximum)
324 if ((PathMaximum = ColorPointer [PixelIndex]) ==
378 register const uint8_t* OriginalColorPointer,
379 register unsigned int StartRow,
register unsigned int EndRow,
380 register unsigned int MaximumValue,
383 register PathFunction PathFinder,
384 register const uint_least32_t DivisionTable [UINT8_MAX + 1])
387 register unsigned int Index;
390 register uint_fast32_t Sum;
396 for (; StartRow < EndRow; ++StartRow)
399 for (PixelIndex =
MakeIndex(StartRow, 0);
400 PixelIndex < LastIndex; ++PixelIndex)
402 if (OriginalColorPointer [PixelIndex] == MaximumValue)
408 for (Index = 0; Index < Parameters.
Termites; ++Index)
411 PixelIndex, OriginalColorPointer,
413 PixelInformationPointer,
414 RepulsionPointer, LocalGenerator,
416 CorrectedColorPointer [PixelIndex] =
418 OriginalColorPointer [PixelIndex],
422 delete [] RepulsionPointer;
475 register const uint8_t* OriginalColorPointer,
476 register unsigned int MaximumValue,
477 register const CorrectionParameters& Parameters,
478 register const PixelInformationType* PixelInformationPointer,
479 register PathFunction PathFinder,
480 register const uint_least32_t DivisionTable [UINT8_MAX + 1])
483 register unsigned int Index;
484 register unsigned int StartRow;
488 if (Parameters.Threads == 1)
489 CorrectStrip(CorrectedColorPointer, OriginalColorPointer,
490 0,
Height, MaximumValue, Parameters,
491 PixelInformationPointer, PathFinder, DivisionTable);
498 new CorrectionDescriptorType [
Strips];
501 CorrectedColorPointer;
503 OriginalColorPointer;
507 PixelInformationPointer;
510 for (Index = 0; Index <
Strips; ++Index)
521 for (Index = 0; Index < Parameters.Threads; ++Index)
523 for (Index = 0; Index < Parameters.Threads; ++Index)
524 CorrectorThread [Index].Join();
551 Value = &DescriptorPointer [--Strips];
574 BitsPerPixel(0), HorizontalResolution(0), VerticalResolution(0),
575 PixelPointer(), RepulsionTable(), InitialRepulsionPointer(),
576 Generator(), Strips(), StripMutex(), DescriptorPointer(
nullptr)
578 register unsigned int Color;
580 for (Color = 0; Color < NUMBER_OF_COLORS; ++Color)
581 PixelPointer [Color] =
nullptr;
599 Height(thisBitmap.Height), BitmapSize(thisBitmap.BitmapSize),
600 BitsPerPixel(thisBitmap.BitsPerPixel),
601 HorizontalResolution(thisBitmap.HorizontalResolution),
602 VerticalResolution(thisBitmap.VerticalResolution), PixelPointer(),
603 RepulsionTable(), InitialRepulsionPointer(),
604 Generator(thisBitmap.Generator), Strips(thisBitmap.Strips),
605 StripMutex(), DescriptorPointer(
nullptr)
607 register unsigned int Color;
611 for (Color = 0; Color < NUMBER_OF_COLORS; ++Color)
612 memcpy(PixelPointer [Color],
613 thisBitmap.PixelPointer [Color], BitmapSize);
631 Height(thisBitmap.Height), BitmapSize(thisBitmap.BitmapSize),
632 BitsPerPixel(thisBitmap.BitsPerPixel),
633 HorizontalResolution(thisBitmap.HorizontalResolution),
634 VerticalResolution(thisBitmap.VerticalResolution), PixelPointer(),
635 RepulsionTable(), InitialRepulsionPointer(),
636 Generator(thisBitmap.Generator), Strips(thisBitmap.Strips),
637 StripMutex(), DescriptorPointer(thisBitmap.DescriptorPointer)
639 register unsigned int Color;
641 for (Color = 0; Color < NUMBER_OF_COLORS; ++Color)
643 PixelPointer [Color] = thisBitmap.PixelPointer [Color];
644 thisBitmap.PixelPointer [Color] =
nullptr;
646 thisBitmap.DescriptorPointer =
nullptr;
664 if (DescriptorPointer !=
nullptr)
665 delete [] DescriptorPointer;
684 register unsigned int Color;
686 Width = thisBitmap.
Width;
687 Height = thisBitmap.Height;
688 BitmapSize = thisBitmap.BitmapSize;
689 BitsPerPixel = thisBitmap.BitsPerPixel;
690 HorizontalResolution = thisBitmap.HorizontalResolution;
691 VerticalResolution = thisBitmap.VerticalResolution;
692 Generator = thisBitmap.Generator;
696 for (Color = 0; Color < NUMBER_OF_COLORS; ++Color)
697 memcpy(PixelPointer [Color],
698 thisBitmap.PixelPointer [Color], BitmapSize);
718 register unsigned int Color;
720 Width = thisBitmap.
Width;
721 Height = thisBitmap.Height;
722 BitmapSize = thisBitmap.BitmapSize;
723 BitsPerPixel = thisBitmap.BitsPerPixel;
724 HorizontalResolution = thisBitmap.HorizontalResolution;
725 VerticalResolution = thisBitmap.VerticalResolution;
726 Generator = thisBitmap.Generator;
728 for (Color = 0; Color < NUMBER_OF_COLORS; ++Color)
730 PixelPointer [Color] = thisBitmap.PixelPointer [Color];
731 thisBitmap.PixelPointer [Color] =
nullptr;
826 register unsigned int Color;
827 register uint_fast32_t Value;
828 register uint_fast32_t Row;
829 register uint_fast32_t Column;
831 register FILE* InputFile;
832 int_fast32_t FileSize;
833 uint8_t Buffer [DIB_HEADER_SIZE];
835 if ((InputFile = fopen(Path, OpenReadBinary)) ==
nullptr)
837 if (fseek(InputFile, 0, SEEK_END) < 0)
839 if ((FileSize = ftell(InputFile)) < 0)
841 if (fseek(InputFile, 0, SEEK_SET) < 0)
843 if (fread(Buffer, 1, HEADER_SIZE, InputFile) != HEADER_SIZE)
845 if (
static_cast<uint_fast32_t
>(FileSize) !=
846 LoadInteger(Buffer + OFFSET_OF_FILE_SIZE, LONG_DATA_SIZE))
848 static_cast<uint_fast32_t
>(FileSize));
849 if (memcmp(Buffer, HeaderName, HEADER_NAME_LENGTH) != 0)
851 if ((Value = LoadInteger(Buffer + OFFSET_OF_BITMAP_OFFSET,
852 LONG_DATA_SIZE)) != HEADER_SIZE + DIB_HEADER_SIZE)
855 if (fread(Buffer, 1, DIB_HEADER_SIZE, InputFile) != DIB_HEADER_SIZE)
857 switch (Value = LoadInteger(Buffer, LONG_DATA_SIZE))
859 case DIB_HEADER_SIZE:
865 Width = LoadInteger(Buffer + OFFSET_OF_WIDTH, LONG_DATA_SIZE);
866 if (Width == 0 or Width > MAXIMUM_WIDTH)
869 Height = LoadInteger(Buffer + OFFSET_OF_HEIGHT, LONG_DATA_SIZE);
870 if (Height == 0 or Height > MAXIMUM_WIDTH)
873 BitmapSize = Width * Height;
877 if ((Value = LoadInteger(Buffer + OFFSET_OF_COLOR_PLANES,
878 SHORT_DATA_SIZE)) != NUMBER_OF_COLOR_PLANES)
881 if ((BitsPerPixel =
static_cast<uint16_t
>(LoadInteger(Buffer +
882 OFFSET_OF_BITS_PER_PIXEL, SHORT_DATA_SIZE))) !=
883 NUMBER_OF_COLORS * CHAR_BIT)
886 if ((Index = LoadInteger(Buffer + OFFSET_OF_COMPRESSION,
887 LONG_DATA_SIZE)) != VALID_COMPRESSION)
890 if ((Value = LoadInteger(Buffer + OFFSET_OF_IMAGE_SIZE,
891 LONG_DATA_SIZE)) != ComputeLineSize() * Height)
892 if (Index != 0 or Value != 0)
895 HorizontalResolution = LoadInteger(Buffer +
896 OFFSET_OF_HORIZONTAL_RESOLUTION, LONG_DATA_SIZE);
897 VerticalResolution = LoadInteger(Buffer + OFFSET_OF_VERTICAL_RESOLUTION,
899 if ((Value = LoadInteger(Buffer + OFFSET_OF_NUMBER_OF_COLORS,
900 LONG_DATA_SIZE)) != 0)
903 if ((Value = LoadInteger(Buffer + OFFSET_OF_NUMBER_OF_IMPORTANT_COLORS,
904 LONG_DATA_SIZE)) != 0)
909 Value = ComputeLineSize();
911 for (Row = 0; Row < Height; ++Row)
913 for (Column = 0; Column < Width; ++Column)
915 if (fread(Buffer, 1, NUMBER_OF_COLORS, InputFile) !=
919 for (Color = 0; Color < NUMBER_OF_COLORS; ++Color)
920 PixelPointer [Color] [Index] = Buffer [Color];
923 if (Column * NUMBER_OF_COLORS < Value)
924 if (fread(Buffer, 1, Value - Column * NUMBER_OF_COLORS,
925 InputFile) != Value - Column * NUMBER_OF_COLORS)
929 if (fclose(InputFile) != 0)
975 register unsigned int Color;
976 register uint_fast32_t Length;
977 register uint_fast32_t Row;
978 register uint_fast32_t Column;
980 register FILE* OutputFile;
981 uint8_t Buffer [DIB_HEADER_SIZE];
983 if ((OutputFile = fopen(Path, OpenWriteBinary)) ==
nullptr)
986 IgnoreValue(memcpy(Buffer, HeaderName, HEADER_NAME_LENGTH));
987 Length = ComputeLineSize();
988 StoreInteger(Buffer + OFFSET_OF_FILE_SIZE, HEADER_SIZE +
989 DIB_HEADER_SIZE + Length * Height, LONG_DATA_SIZE);
990 StoreInteger(Buffer + OFFSET_OF_BITMAP_OFFSET,
991 HEADER_SIZE + DIB_HEADER_SIZE, LONG_DATA_SIZE);
992 if (fwrite(Buffer, 1, HEADER_SIZE, OutputFile) != HEADER_SIZE)
995 StoreInteger(Buffer, DIB_HEADER_SIZE, LONG_DATA_SIZE);
996 StoreInteger(Buffer + OFFSET_OF_WIDTH, Width, LONG_DATA_SIZE);
997 StoreInteger(Buffer + OFFSET_OF_HEIGHT, Height, LONG_DATA_SIZE);
998 StoreInteger(Buffer + OFFSET_OF_COLOR_PLANES, NUMBER_OF_COLOR_PLANES,
1000 StoreInteger(Buffer + OFFSET_OF_BITS_PER_PIXEL, BitsPerPixel,
1002 StoreInteger(Buffer + OFFSET_OF_COMPRESSION, VALID_COMPRESSION,
1004 StoreInteger(Buffer + OFFSET_OF_HORIZONTAL_RESOLUTION,
1005 HorizontalResolution, LONG_DATA_SIZE);
1006 StoreInteger(Buffer + OFFSET_OF_VERTICAL_RESOLUTION, VerticalResolution,
1008 if (fwrite(Buffer, 1, DIB_HEADER_SIZE, OutputFile) != DIB_HEADER_SIZE)
1011 assert(Length >= Width * NUMBER_OF_COLORS);
1012 Length -= Width * NUMBER_OF_COLORS;
1013 for (Row = 0; Row < Height; ++Row)
1015 for (Column = 0; Column < Width; ++Column)
1017 for (Color = 0; Color < NUMBER_OF_COLORS; ++Color)
1018 Buffer [Color] = PixelPointer [Color] [Index];
1019 if (fwrite(Buffer, 1, NUMBER_OF_COLORS, OutputFile) !=
1028 if (fwrite(Buffer, 1, Length, OutputFile) != Length)
1033 if (fclose(OutputFile) != 0)
1079 register unsigned int FirstValue;
1080 register unsigned int SecondValue;
1082 register float Sqrt2;
1084 register PathFunction PathFinder;
1086 Bitmap LocalBitmap(*
this);
1087 uint_least32_t OrthogonalAttraction
1089 uint_least32_t DiagonalAttraction
1091 uint_least32_t DivisionTable [UINT8_MAX + 1];
1093 if (Parameters.Termites == 0 or Parameters.Termites >
1094 MAXIMUM_NUMBER_OF_TERMITES)
1097 if (Parameters.Steps == 0 or Parameters.Steps > MAXIMUM_NUMBER_OF_STEPS)
1100 if (Parameters.RepulsionStep < 0.0 or Parameters.RepulsionStep > 1.0)
1102 Parameters.RepulsionStep);
1103 if (Parameters.Alpha < 0.0 or Parameters.Alpha > 1.0)
1106 if (Parameters.Beta < 0.0 or Parameters.Beta > 1.0)
1109 PathFinder = Parameters.ChoiceKind == ChoiceType::RANDOM?
1110 &PixelInformationType::NextPixelRandom:
1111 &PixelInformationType::NextPixelMaximum;
1113 RepulsionTable [Index] =
static_cast<unsigned short>
1114 (lrintf(powf(
static_cast<float>(1) / (1 +
1115 static_cast<float>(Index) * Parameters.RepulsionStep),
1116 Parameters.Alpha) * REPULSION_SCALE));
1120 OrthogonalAttraction [Index] =
static_cast<uint_least32_t
>
1121 (lrintf(powf(
static_cast<float>(1 + Index) / Sqrt2,
1122 Parameters.Beta) * ATTRACTION_SCALE));
1123 DiagonalAttraction [Index] =
static_cast<uint_least32_t
>
1124 (lrintf(powf((Sqrt2 +
static_cast<float>(Index)) /
1125 Sqrt2, Parameters.Beta) * ATTRACTION_SCALE));
1128 DivisionTable [Index] =
static_cast<uint_least32_t
>
1129 (RoundedDivide(
static_cast<uint_least32_t
>(UINT8_MAX) *
1130 TERMITES_SUM_SCALE, Index));
1131 DivisionTable [0] = DivisionTable [1];
1135 InitialRepulsion.
Repulsion = RepulsionTable [0];
1136 for (Index = 0; Index < BitmapSize; ++Index)
1137 InitialRepulsionPointer [Index] = InitialRepulsion;
1138 for (FirstValue = 0; FirstValue < Height; ++FirstValue)
1139 for (SecondValue = 0; SecondValue < Width; ++SecondValue)
1140 PixelInformationPointer [MakeIndex(FirstValue,
1142 SetLinks(*
this, FirstValue, SecondValue);
1143 for (FirstValue = 0; FirstValue < NUMBER_OF_COLORS; ++FirstValue)
1145 SecondValue = Parameters.TruncatePath? 0: UINT8_MAX + 1;
1146 for (Index = 0; Index < BitmapSize; ++Index)
1148 PixelInformationPointer [Index].
1149 SetAttraction(*
this, PixelPointer [FirstValue],
1150 Index, OrthogonalAttraction,
1151 DiagonalAttraction);
1152 if (PixelPointer [FirstValue] [Index] > SecondValue)
1153 SecondValue = PixelPointer [FirstValue] [Index];
1156 PixelPointer [FirstValue], SecondValue, Parameters,
1157 PixelInformationPointer, PathFinder, DivisionTable);
1159 delete [] PixelInformationPointer;
1160 delete [] InitialRepulsionPointer;
1197 BitmapPointer =
static_cast<Bitmap*
>(Argument);