2
// This unit is part of the GLScene Engine https://github.com/glscene
5
Main purpose is as a fallback in cases where there is no other way to process images.
8
07/09/11 - Yar - Bugfixed memory overrun in Build2DMipmap (thanks to benok1)
9
09/04/11 - Yar - Added AlphaGammaBrightCorrection
10
08/04/11 - Yar - Complete Build2DMipmap
11
07/11/10 - YP - Inline removed from local functions with external var access (Fixes error E2449)
12
04/11/10 - DaStr - Added $I GLScene.inc
13
22/10/10 - Yar - Created
20
// TODO: Complite InfToXXX
21
// DONE: S3TC decompression
22
// DONE: LATC decompression
23
// DONE: RGTC decompression
24
// TODO: BPTC decompression
25
// TODO: S3TC compression
26
// TODO: LATC compression
27
// TODO: RGTC compression
28
// TODO: BPTC compression
46
vImageScaleFilterWidth: Integer = 5; // Relative sample radius for filtering
50
TIntermediateFormat = record
54
TPointerArray = array of Pointer;
56
PRGBA32F = ^TIntermediateFormat;
57
TIntermediateFormatArray = array [0 .. MaxInt div (2 * SizeOf(TIntermediateFormat))] of TIntermediateFormat;
58
PIntermediateFormatArray = ^TIntermediateFormatArray;
60
TU48BitBlock = array [0 .. 3, 0 .. 3] of Byte;
61
T48BitBlock = array [0 .. 3, 0 .. 3] of SmallInt;
63
EGLImageUtils = class(Exception);
65
TImageFilterFunction = function(Value: Single): Single;
66
TImageAlphaProc = procedure(var AColor: TIntermediateFormat);
68
function ImageBoxFilter(Value: Single): Single;
69
function ImageTriangleFilter(Value: Single): Single;
70
function ImageHermiteFilter(Value: Single): Single;
71
function ImageBellFilter(Value: Single): Single;
72
function ImageSplineFilter(Value: Single): Single;
73
function ImageLanczos3Filter(Value: Single): Single;
74
function ImageMitchellFilter(Value: Single): Single;
76
procedure ImageAlphaFromIntensity(var AColor: TIntermediateFormat);
77
procedure ImageAlphaSuperBlackTransparent(var AColor: TIntermediateFormat);
78
procedure ImageAlphaLuminance(var AColor: TIntermediateFormat);
79
procedure ImageAlphaLuminanceSqrt(var AColor: TIntermediateFormat);
80
procedure ImageAlphaOpaque(var AColor: TIntermediateFormat);
81
procedure ImageAlphaTopLeftPointColorTransparent(var AColor: TIntermediateFormat);
82
procedure ImageAlphaInverseLuminance(var AColor: TIntermediateFormat);
83
procedure ImageAlphaInverseLuminanceSqrt(var AColor: TIntermediateFormat);
84
procedure ImageAlphaBottomRightPointColorTransparent(var AColor: TIntermediateFormat);
86
procedure ConvertImage(const ASrc: Pointer; const ADst: Pointer; ASrcColorFormat, ADstColorFormat: TGLEnum; ASrcDataType, ADstDataType: TGLEnum; AWidth, AHeight: Integer);
88
procedure RescaleImage(const ASrc: Pointer; const ADst: Pointer; AColorFormat: TGLEnum; ADataType: TGLEnum; AFilter: TImageFilterFunction; ASrcWidth, ASrcHeight, ADstWidth, ADstHeight: Integer);
89
procedure Build2DMipmap(const ASrc: Pointer; const ADst: TPointerArray; AColorFormat: TGLEnum; ADataType: TGLEnum; AFilter: TImageFilterFunction; ASrcWidth, ASrcHeight: Integer);
91
procedure AlphaGammaBrightCorrection(const ASrc: Pointer; AColorFormat: TGLEnum; ADataType: TGLEnum; ASrcWidth, ASrcHeight: Integer; anAlphaProc: TImageAlphaProc; ABrightness: Single; AGamma: Single);
96
strInvalidType = 'Invalid data type';
99
cSuperBlack: TIntermediateFormat = (R: 0.0; G: 0.0; B: 0.0; A: 0.0);
102
TConvertToImfProc = procedure(ASource: Pointer; ADest: PIntermediateFormatArray; AColorFormat: TGLEnum; AWidth, AHeight: Integer);
103
TConvertFromInfProc = procedure(ASource: PIntermediateFormatArray; ADest: Pointer; AColorFormat: TGLEnum; AWidth, AHeight: Integer);
105
procedure Swap(var A, B: Integer);
106
{$IFDEF GLS_INLINE} inline;
116
{$IFDEF GLS_REGIONS}{$REGION 'OpenGL format image to RGBA Float'}{$ENDIF}
118
procedure UnsupportedToImf(ASource: Pointer; ADest: PIntermediateFormatArray; AColorFormat: TGLEnum; AWidth, AHeight: Integer);
120
raise EGLImageUtils.Create('Unimplemented type of conversion');
123
procedure UbyteToImf(ASource: Pointer; ADest: PIntermediateFormatArray; AColorFormat: TGLEnum; AWidth, AHeight: Integer);
129
function GetChannel: Single;
136
pSource := PByte(ASource);
139
{$INCLUDE ImgUtilCaseGL2Imf.inc}
141
raise EGLImageUtils.Create(strInvalidType);
145
procedure Ubyte332ToImf(ASource: Pointer; ADest: PIntermediateFormatArray; AColorFormat: TGLEnum; AWidth, AHeight: Integer);
148
c0, c1, c2, c3: Byte;
151
procedure GetChannel;
155
c2 := $E0 and (c0 shl 3);
156
c3 := $C0 and (c0 shl 6);
161
pSource := PByte(ASource);
166
for n := 0 to AWidth * AHeight - 1 do
175
for n := 0 to AWidth * AHeight - 1 do
183
raise EGLImageUtils.Create(strInvalidType);
187
procedure Ubyte233RToImf(ASource: Pointer; ADest: PIntermediateFormatArray; AColorFormat: TGLEnum; AWidth, AHeight: Integer);
190
c0, c1, c2, c3: Byte;
193
procedure GetChannel;
197
c2 := $E0 and (c0 shl 3);
198
c1 := $C0 and (c0 shl 6);
203
pSource := PByte(ASource);
208
for n := 0 to AWidth * AHeight - 1 do
217
for n := 0 to AWidth * AHeight - 1 do
225
raise EGLImageUtils.Create(strInvalidType);
229
procedure ByteToImf(ASource: Pointer; ADest: PIntermediateFormatArray; AColorFormat: TGLEnum; AWidth, AHeight: Integer);
235
function GetChannel: Single;
242
pSource := PShortInt(ASource);
245
{$INCLUDE ImgUtilCaseGL2Imf.inc}
247
raise EGLImageUtils.Create(strInvalidType);
251
procedure UShortToImf(ASource: Pointer; ADest: PIntermediateFormatArray; AColorFormat: TGLEnum; AWidth, AHeight: Integer);
257
function GetChannel: Single;
259
Result := pSource^ / $100;
264
pSource := PWord(ASource);
267
{$INCLUDE ImgUtilCaseGL2Imf.inc}
269
raise EGLImageUtils.Create(strInvalidType);
273
procedure ShortToImf(ASource: Pointer; ADest: PIntermediateFormatArray; AColorFormat: TGLEnum; AWidth, AHeight: Integer);
279
function GetChannel: Single;
281
Result := pSource^ / $100;
286
pSource := PSmallInt(ASource);
289
{$INCLUDE ImgUtilCaseGL2Imf.inc}
291
raise EGLImageUtils.Create(strInvalidType);
295
procedure UIntToImf(ASource: Pointer; ADest: PIntermediateFormatArray; AColorFormat: TGLEnum; AWidth, AHeight: Integer);
301
function GetChannel: Single;
303
Result := pSource^ / $1000000;
308
pSource := PLongWord(ASource);
311
{$INCLUDE ImgUtilCaseGL2Imf.inc}
313
raise EGLImageUtils.Create(strInvalidType);
317
procedure IntToImf(ASource: Pointer; ADest: PIntermediateFormatArray; AColorFormat: TGLEnum; AWidth, AHeight: Integer);
323
function GetChannel: Single;
325
Result := pSource^ / $1000000;
330
pSource := PLongInt(ASource);
333
{$INCLUDE ImgUtilCaseGL2Imf.inc}
335
raise EGLImageUtils.Create(strInvalidType);
339
procedure FloatToImf(ASource: Pointer; ADest: PIntermediateFormatArray; AColorFormat: TGLEnum; AWidth, AHeight: Integer);
345
function GetChannel: Single;
347
Result := pSource^ * 255.0;
352
pSource := PSingle(ASource);
355
{$INCLUDE ImgUtilCaseGL2Imf.inc}
357
raise EGLImageUtils.Create(strInvalidType);
361
procedure HalfFloatToImf(ASource: Pointer; ADest: PIntermediateFormatArray; AColorFormat: TGLEnum; AWidth, AHeight: Integer);
367
function GetChannel: Single;
369
Result := HalfToFloat(pSource^) * 255.0;
374
pSource := PHalfFloat(ASource);
377
{$INCLUDE ImgUtilCaseGL2Imf.inc}
379
raise EGLImageUtils.Create(strInvalidType);
383
procedure UInt8888ToImf(ASource: Pointer; ADest: PIntermediateFormatArray; AColorFormat: TGLEnum; AWidth, AHeight: Integer);
387
c0, c1, c2, c3: Byte;
389
procedure GetChannel;
402
pSource := PByte(ASource);
406
GL_RGBA, GL_RGBA_INTEGER:
407
for n := 0 to AWidth * AHeight - 1 do
416
GL_BGRA, GL_BGRA_INTEGER:
417
for n := 0 to AWidth * AHeight - 1 do
426
raise EGLImageUtils.Create(strInvalidType);
430
procedure UInt8888RevToImf(ASource: Pointer; ADest: PIntermediateFormatArray; AColorFormat: TGLEnum; AWidth, AHeight: Integer);
434
c0, c1, c2, c3: Byte;
436
procedure GetChannel;
449
pSource := PByte(ASource);
453
GL_RGBA, GL_RGBA_INTEGER:
454
for n := 0 to AWidth * AHeight - 1 do
463
GL_BGRA, GL_BGRA_INTEGER:
464
for n := 0 to AWidth * AHeight - 1 do
473
raise EGLImageUtils.Create(strInvalidType);
477
procedure UShort4444ToImf(ASource: Pointer; ADest: PIntermediateFormatArray; AColorFormat: TGLEnum; AWidth, AHeight: Integer);
481
c0, c1, c2, c3, c4: Byte;
483
procedure GetChannel;
486
c3 := $F0 and (c0 shl 4);
490
c1 := $F0 and (c0 shl 4);
496
pSource := PByte(ASource);
500
GL_RGBA, GL_RGBA_INTEGER:
501
for n := 0 to AWidth * AHeight - 1 do
510
GL_BGRA, GL_BGRA_INTEGER:
511
for n := 0 to AWidth * AHeight - 1 do
520
raise EGLImageUtils.Create(strInvalidType);
524
procedure UShort4444RevToImf(ASource: Pointer; ADest: PIntermediateFormatArray; AColorFormat: TGLEnum; AWidth, AHeight: Integer);
528
c0, c1, c2, c3, c4: Byte;
530
procedure GetChannel;
533
c1 := $F0 and (c0 shl 4);
537
c3 := $F0 and (c0 shl 4);
543
pSource := PByte(ASource);
547
GL_RGBA, GL_RGBA_INTEGER:
548
for n := 0 to AWidth * AHeight - 1 do
557
GL_BGRA, GL_BGRA_INTEGER:
558
for n := 0 to AWidth * AHeight - 1 do
567
raise EGLImageUtils.Create(strInvalidType);
571
procedure UShort565ToImf(ASource: Pointer; ADest: PIntermediateFormatArray; AColorFormat: TGLEnum; AWidth, AHeight: Integer);
578
procedure GetChannel;
581
c3 := (c0 and $001F) shl 3;
582
c2 := (c0 and $07E0) shr 3;
583
c1 := (c0 and $F800) shr 8;
588
pSource := PWord(ASource);
592
GL_RGB, GL_RGB_INTEGER:
593
for n := 0 to AWidth * AHeight - 1 do
601
GL_BGR, GL_BGR_INTEGER:
602
for n := 0 to AWidth * AHeight - 1 do
610
raise EGLImageUtils.Create(strInvalidType);
614
procedure UShort565RevToImf(ASource: Pointer; ADest: PIntermediateFormatArray; AColorFormat: TGLEnum; AWidth, AHeight: Integer);
621
procedure GetChannel;
624
c1 := (c0 and $001F) shl 3;
625
c2 := (c0 and $07E0) shr 3;
626
c3 := (c0 and $F800) shr 8;
631
pSource := PWord(ASource);
635
GL_RGB, GL_RGB_INTEGER:
636
for n := 0 to AWidth * AHeight - 1 do
644
GL_BGR, GL_BGR_INTEGER:
645
for n := 0 to AWidth * AHeight - 1 do
653
raise EGLImageUtils.Create(strInvalidType);
657
procedure UShort5551ToImf(ASource: Pointer; ADest: PIntermediateFormatArray; AColorFormat: TGLEnum; AWidth, AHeight: Integer);
662
c1, c2, c3, c4: Byte;
664
procedure GetChannel;
667
c4 := (c0 and $001F) shl 3;
668
c3 := (c0 and $03E0) shr 2;
669
c2 := (c0 and $7C00) shr 7;
670
c1 := (c0 and $8000) shr 8;
675
pSource := PWord(ASource);
679
GL_RGBA, GL_RGBA_INTEGER:
680
for n := 0 to AWidth * AHeight - 1 do
689
GL_BGRA, GL_BGRA_INTEGER:
690
for n := 0 to AWidth * AHeight - 1 do
699
raise EGLImageUtils.Create(strInvalidType);
703
procedure UShort5551RevToImf(ASource: Pointer; ADest: PIntermediateFormatArray; AColorFormat: TGLEnum; AWidth, AHeight: Integer);
708
c1, c2, c3, c4: Byte;
710
procedure GetChannel;
713
c1 := (c0 and $001F) shl 3;
714
c2 := (c0 and $03E0) shr 2;
715
c3 := (c0 and $7C00) shr 7;
716
c4 := (c0 and $8000) shr 8;
721
pSource := PWord(ASource);
725
GL_RGBA, GL_RGBA_INTEGER:
726
for n := 0 to AWidth * AHeight - 1 do
735
GL_BGRA, GL_BGRA_INTEGER:
736
for n := 0 to AWidth * AHeight - 1 do
745
raise EGLImageUtils.Create(strInvalidType);
749
procedure UInt_10_10_10_2_ToImf(ASource: Pointer; ADest: PIntermediateFormatArray; AColorFormat: TGLEnum; AWidth, AHeight: Integer);
754
c1, c2, c3, c4: Word;
756
procedure GetChannel;
759
c1 := (c0 and $000003FF) shl 6;
760
c2 := (c0 and $000FFC00) shr 4;
761
c3 := (c0 and $3FF00000) shr 14;
762
c4 := (c0 and $C0000000) shr 16;
767
pSource := PLongWord(ASource);
771
GL_RGBA, GL_RGBA_INTEGER:
772
for n := 0 to AWidth * AHeight - 1 do
775
ADest[n].R := c1 / $100;
776
ADest[n].G := c2 / $100;
777
ADest[n].B := c3 / $100;
781
GL_BGRA, GL_BGRA_INTEGER:
782
for n := 0 to AWidth * AHeight - 1 do
785
ADest[n].B := c1 / $100;
786
ADest[n].G := c2 / $100;
787
ADest[n].R := c3 / $100;
791
raise EGLImageUtils.Create(strInvalidType);
795
procedure UInt_10_10_10_2_Rev_ToImf(ASource: Pointer; ADest: PIntermediateFormatArray; AColorFormat: TGLEnum; AWidth, AHeight: Integer);
800
c1, c2, c3, c4: Word;
802
procedure GetChannel;
805
c1 := (c0 and $000003FF) shl 6;
806
c2 := (c0 and $000FFC00) shr 4;
807
c3 := (c0 and $3FF00000) shr 14;
808
c4 := (c0 and $C0000000) shr 16;
813
pSource := PLongWord(ASource);
817
GL_RGBA, GL_RGBA_INTEGER:
818
for n := 0 to AWidth * AHeight - 1 do
821
ADest[n].R := c1 / $100;
822
ADest[n].G := c2 / $100;
823
ADest[n].B := c3 / $100;
827
GL_BGRA, GL_BGRA_INTEGER:
828
for n := 0 to AWidth * AHeight - 1 do
831
ADest[n].B := c1 / $100;
832
ADest[n].G := c2 / $100;
833
ADest[n].R := c3 / $100;
837
raise EGLImageUtils.Create(strInvalidType);
841
{$IFDEF GLS_REGIONS}{$ENDREGION}{$ENDIF}
842
{$IFDEF GLS_REGIONS}{$REGION 'Decompression'}{$ENDIF}
844
procedure DecodeColor565(col: Word; out R, G, B: Byte);
847
G := (col shr 5) and $3F;
848
B := (col shr 11) and $1F;
851
procedure DXT1_ToImf(ASource: Pointer; ADest: PIntermediateFormatArray; AColorFormat: TGLEnum; AWidth, AHeight: Integer);
853
x, y, i, j, k, select, offset: Integer;
855
colors: TU48BitBlock;
858
r0, g0, b0, r1, g1, b1: Byte;
861
temp := PGLubyte(ASource);
862
for y := 0 to (AHeight div 4) - 1 do
864
for x := 0 to (AWidth div 4) - 1 do
866
col0 := PWord(temp)^;
868
col1 := PWord(temp)^;
870
bitmask := PCardinal(temp)^;
873
DecodeColor565(col0, r0, g0, b0);
874
DecodeColor565(col1, r1, g1, b1);
876
colors[0][0] := r0 shl 3;
877
colors[0][1] := g0 shl 2;
878
colors[0][2] := b0 shl 3;
880
colors[1][0] := r1 shl 3;
881
colors[1][1] := g1 shl 2;
882
colors[1][2] := b1 shl 3;
887
colors[2][0] := (2 * colors[0][0] + colors[1][0] + 1) div 3;
888
colors[2][1] := (2 * colors[0][1] + colors[1][1] + 1) div 3;
889
colors[2][2] := (2 * colors[0][2] + colors[1][2] + 1) div 3;
891
colors[3][0] := (colors[0][0] + 2 * colors[1][0] + 1) div 3;
892
colors[3][1] := (colors[0][1] + 2 * colors[1][1] + 1) div 3;
893
colors[3][2] := (colors[0][2] + 2 * colors[1][2] + 1) div 3;
898
colors[2][0] := (colors[0][0] + colors[1][0]) div 2;
899
colors[2][1] := (colors[0][1] + colors[1][1]) div 2;
900
colors[2][2] := (colors[0][2] + colors[1][2]) div 2;
902
colors[3][0] := (colors[0][0] + 2 * colors[1][0] + 1) div 3;
903
colors[3][1] := (colors[0][1] + 2 * colors[1][1] + 1) div 3;
904
colors[3][2] := (colors[0][2] + 2 * colors[1][2] + 1) div 3;
913
select := (bitmask and (3 shl (k * 2))) shr (k * 2);
914
if ((4 * x + i) < AWidth) and ((4 * y + j) < AHeight) then
916
offset := ((4 * y + j) * AWidth + (4 * x + i));
917
ADest[offset].B := colors[select][0];
918
ADest[offset].G := colors[select][1];
919
ADest[offset].R := colors[select][2];
920
ADest[offset].A := colors[select][3];
930
procedure DXT3_ToImf(ASource: Pointer; ADest: PIntermediateFormatArray; AColorFormat: TGLEnum; AWidth, AHeight: Integer);
932
x, y, i, j, k, select: Integer;
933
col0, col1, wrd: Word;
934
colors: TU48BitBlock;
935
bitmask, offset: Cardinal;
937
r0, g0, b0, r1, g1, b1: Byte;
938
alpha: array [0 .. 3] of Word;
940
temp := PGLubyte(ASource);
941
for y := 0 to (AHeight div 4) - 1 do
943
for x := 0 to (AWidth div 4) - 1 do
945
alpha[0] := PWord(temp)^;
947
alpha[1] := PWord(temp)^;
949
alpha[2] := PWord(temp)^;
951
alpha[3] := PWord(temp)^;
953
col0 := PWord(temp)^;
955
col1 := PWord(temp)^;
957
bitmask := PCardinal(temp)^;
960
DecodeColor565(col0, r0, g0, b0);
961
DecodeColor565(col1, r1, g1, b1);
963
colors[0][0] := r0 shl 3;
964
colors[0][1] := g0 shl 2;
965
colors[0][2] := b0 shl 3;
967
colors[1][0] := r1 shl 3;
968
colors[1][1] := g1 shl 2;
969
colors[1][2] := b1 shl 3;
971
colors[2][0] := (2 * colors[0][0] + colors[1][0] + 1) div 3;
972
colors[2][1] := (2 * colors[0][1] + colors[1][1] + 1) div 3;
973
colors[2][2] := (2 * colors[0][2] + colors[1][2] + 1) div 3;
975
colors[3][0] := (colors[0][0] + 2 * colors[1][0] + 1) div 3;
976
colors[3][1] := (colors[0][1] + 2 * colors[1][1] + 1) div 3;
977
colors[3][2] := (colors[0][2] + 2 * colors[1][2] + 1) div 3;
985
select := (bitmask and (3 shl (k * 2))) shr (k * 2);
986
if ((4 * x + i) < AWidth) and ((4 * y + j) < AHeight) then
988
offset := ((4 * y + j) * AWidth + (4 * x + i));
989
ADest[offset].B := colors[select][0];
990
ADest[offset].G := colors[select][1];
991
ADest[offset].R := colors[select][2];
992
ADest[offset].A := colors[select][3];
1003
if (((4 * x + i) < AWidth) and ((4 * y + j) < AHeight)) then
1005
offset := ((4 * y + j) * AWidth + (4 * x + i));
1007
ADest[offset].A := r0 or (r0 shl 4);
1017
procedure DXT5_ToImf(ASource: Pointer; ADest: PIntermediateFormatArray; AColorFormat: TGLEnum; AWidth, AHeight: Integer);
1019
x, y, i, j, k, select, offset: Integer;
1021
colors: TU48BitBlock;
1022
bits, bitmask: Cardinal;
1023
temp, alphamask: PGLubyte;
1024
r0, g0, b0, r1, g1, b1: Byte;
1025
alphas: array [0 .. 7] of Byte;
1027
temp := PGLubyte(ASource);
1028
for y := 0 to (AHeight div 4) - 1 do
1030
for x := 0 to (AWidth div 4) - 1 do
1038
col0 := PWord(temp)^;
1040
col1 := PWord(temp)^;
1042
bitmask := PCardinal(temp)^;
1045
DecodeColor565(col0, r0, g0, b0);
1046
DecodeColor565(col1, r1, g1, b1);
1048
colors[0][0] := r0 shl 3;
1049
colors[0][1] := g0 shl 2;
1050
colors[0][2] := b0 shl 3;
1051
colors[0][3] := $FF;
1052
colors[1][0] := r1 shl 3;
1053
colors[1][1] := g1 shl 2;
1054
colors[1][2] := b1 shl 3;
1055
colors[1][3] := $FF;
1056
colors[2][0] := (2 * colors[0][0] + colors[1][0] + 1) div 3;
1057
colors[2][1] := (2 * colors[0][1] + colors[1][1] + 1) div 3;
1058
colors[2][2] := (2 * colors[0][2] + colors[1][2] + 1) div 3;
1059
colors[2][3] := $FF;
1060
colors[3][0] := (colors[0][0] + 2 * colors[1][0] + 1) div 3;
1061
colors[3][1] := (colors[0][1] + 2 * colors[1][1] + 1) div 3;
1062
colors[3][2] := (colors[0][2] + 2 * colors[1][2] + 1) div 3;
1063
colors[3][3] := $FF;
1070
select := (bitmask and (3 shl (k * 2))) shr (k * 2);
1071
if ((4 * x + i) < AWidth) and ((4 * y + j) < AHeight) then
1073
offset := ((4 * y + j) * AWidth + (4 * x + i));
1074
ADest[offset].B := colors[select][0];
1075
ADest[offset].G := colors[select][1];
1076
ADest[offset].R := colors[select][2];
1082
if (alphas[0] > alphas[1]) then
1084
alphas[2] := (6 * alphas[0] + 1 * alphas[1] + 3) div 7;
1085
alphas[3] := (5 * alphas[0] + 2 * alphas[1] + 3) div 7;
1086
alphas[4] := (4 * alphas[0] + 3 * alphas[1] + 3) div 7;
1087
alphas[5] := (3 * alphas[0] + 4 * alphas[1] + 3) div 7;
1088
alphas[6] := (2 * alphas[0] + 5 * alphas[1] + 3) div 7;
1089
alphas[7] := (1 * alphas[0] + 6 * alphas[1] + 3) div 7;
1093
alphas[2] := (4 * alphas[0] + 1 * alphas[1] + 2) div 5;
1094
alphas[3] := (3 * alphas[0] + 2 * alphas[1] + 2) div 5;
1095
alphas[4] := (2 * alphas[0] + 3 * alphas[1] + 2) div 5;
1096
alphas[5] := (1 * alphas[0] + 4 * alphas[1] + 2) div 5;
1101
bits := PCardinal(alphamask)^;
1106
if (((4 * x + i) < AWidth) and ((4 * y + j) < AHeight)) then
1108
offset := ((4 * y + j) * AWidth + (4 * x + i));
1109
ADest[offset].A := alphas[bits and 7];
1116
bits := PCardinal(alphamask)^;
1121
if (((4 * x + i) < AWidth) and ((4 * y + j) < AHeight)) then
1123
offset := ((4 * y + j) * AWidth + (4 * x + i));
1124
ADest[offset].A := alphas[bits and 7];
1134
procedure Decode48BitBlock(ACode: Int64; out ABlock: TU48BitBlock); overload;
1141
ABlock[x][y] := Byte(ACode and $03);
1142
ACode := ACode shr 2;
1146
procedure Decode48BitBlock(ACode: Int64; out ABlock: T48BitBlock); overload;
1153
ABlock[x][y] := SmallInt(ACode and $03);
1154
ACode := ACode shr 2;
1158
procedure LATC1_ToImf(ASource: Pointer; ADest: PIntermediateFormatArray; AColorFormat: TGLEnum; AWidth, AHeight: Integer);
1160
x, y, i, j, offset: Integer;
1163
colors: TU48BitBlock;
1168
temp := PGLubyte(ASource);
1169
for y := 0 to (AHeight div 4) - 1 do
1171
for x := 0 to (AWidth div 4) - 1 do
1177
bitmask := PInt64(temp)^;
1179
Decode48BitBlock(bitmask, colors);
1186
case colors[j, i] of
1188
colors[j, i] := LUM0;
1190
colors[j, i] := LUM1;
1192
colors[j, i] := (6 * LUM0 + LUM1) div 7;
1194
colors[j, i] := (5 * LUM0 + 2 * LUM1) div 7;
1196
colors[j, i] := (4 * LUM0 + 3 * LUM1) div 7;
1198
colors[j, i] := (3 * LUM0 + 4 * LUM1) div 7;
1200
colors[j, i] := (2 * LUM0 + 5 * LUM1) div 7;
1202
colors[j, i] := (LUM0 + 6 * LUM1) div 7;
1205
case colors[j, i] of
1207
colors[j, i] := LUM0;
1209
colors[j, i] := LUM1;
1211
colors[j, i] := (4 * LUM0 + LUM1) div 5;
1213
colors[j, i] := (3 * LUM0 + 2 * LUM1) div 5;
1215
colors[j, i] := (2 * LUM0 + 3 * LUM1) div 5;
1217
colors[j, i] := (LUM0 + 4 * LUM1) div 5;
1221
colors[j, i] := 255;
1223
if ((4 * x + i) < AWidth) and ((4 * y + j) < AHeight) then
1225
offset := ((4 * y + j) * AWidth + (4 * x + i));
1226
lum := colors[j, i];
1227
ADest[offset].R := lum;
1228
ADest[offset].G := lum;
1229
ADest[offset].B := lum;
1230
ADest[offset].A := 255.0;
1239
procedure SLATC1_ToImf(ASource: Pointer; ADest: PIntermediateFormatArray; AColorFormat: TGLEnum; AWidth, AHeight: Integer);
1241
x, y, i, j, offset: Integer;
1242
LUM0, LUM1: SmallInt;
1244
colors: T48BitBlock;
1249
temp := PGLubyte(ASource);
1250
for y := 0 to (AHeight div 4) - 1 do
1252
for x := 0 to (AWidth div 4) - 1 do
1254
LUM0 := PSmallInt(temp)^;
1256
LUM1 := PSmallInt(temp)^;
1258
bitmask := PInt64(temp)^;
1260
Decode48BitBlock(bitmask, colors);
1267
case colors[j, i] of
1269
colors[j, i] := LUM0;
1271
colors[j, i] := LUM1;
1273
colors[j, i] := (6 * LUM0 + LUM1) div 7;
1275
colors[j, i] := (5 * LUM0 + 2 * LUM1) div 7;
1277
colors[j, i] := (4 * LUM0 + 3 * LUM1) div 7;
1279
colors[j, i] := (3 * LUM0 + 4 * LUM1) div 7;
1281
colors[j, i] := (2 * LUM0 + 5 * LUM1) div 7;
1283
colors[j, i] := (LUM0 + 6 * LUM1) div 7;
1286
case colors[j, i] of
1288
colors[j, i] := LUM0;
1290
colors[j, i] := LUM1;
1292
colors[j, i] := (4 * LUM0 + LUM1) div 5;
1294
colors[j, i] := (3 * LUM0 + 2 * LUM1) div 5;
1296
colors[j, i] := (2 * LUM0 + 3 * LUM1) div 5;
1298
colors[j, i] := (LUM0 + 4 * LUM1) div 5;
1300
colors[j, i] := -127;
1302
colors[j, i] := 127;
1304
if ((4 * x + i) < AWidth) and ((4 * y + j) < AHeight) then
1306
offset := ((4 * y + j) * AWidth + (4 * x + i));
1307
lum := 2 * colors[j, i];
1308
ADest[offset].R := lum;
1309
ADest[offset].G := lum;
1310
ADest[offset].B := lum;
1311
ADest[offset].A := 127.0;
1320
procedure LATC2_ToImf(ASource: Pointer; ADest: PIntermediateFormatArray; AColorFormat: TGLEnum; AWidth, AHeight: Integer);
1322
x, y, i, j, offset: Integer;
1325
colors: TU48BitBlock;
1330
temp := PGLubyte(ASource);
1331
for y := 0 to (AHeight div 4) - 1 do
1333
for x := 0 to (AWidth div 4) - 1 do
1339
bitmask := PInt64(temp)^;
1341
Decode48BitBlock(bitmask, colors);
1348
case colors[j, i] of
1350
colors[j, i] := LUM0;
1352
colors[j, i] := LUM1;
1354
colors[j, i] := (6 * LUM0 + LUM1) div 7;
1356
colors[j, i] := (5 * LUM0 + 2 * LUM1) div 7;
1358
colors[j, i] := (4 * LUM0 + 3 * LUM1) div 7;
1360
colors[j, i] := (3 * LUM0 + 4 * LUM1) div 7;
1362
colors[j, i] := (2 * LUM0 + 5 * LUM1) div 7;
1364
colors[j, i] := (LUM0 + 6 * LUM1) div 7;
1367
case colors[j, i] of
1369
colors[j, i] := LUM0;
1371
colors[j, i] := LUM1;
1373
colors[j, i] := (4 * LUM0 + LUM1) div 5;
1375
colors[j, i] := (3 * LUM0 + 2 * LUM1) div 5;
1377
colors[j, i] := (2 * LUM0 + 3 * LUM1) div 5;
1379
colors[j, i] := (LUM0 + 4 * LUM1) div 5;
1383
colors[j, i] := 255;
1385
if ((4 * x + i) < AWidth) and ((4 * y + j) < AHeight) then
1387
offset := ((4 * y + j) * AWidth + (4 * x + i));
1388
lum := colors[j][i];
1389
ADest[offset].R := lum;
1390
ADest[offset].G := lum;
1391
ADest[offset].B := lum;
1400
bitmask := PInt64(temp)^;
1402
Decode48BitBlock(bitmask, colors);
1409
case colors[j, i] of
1411
colors[j, i] := LUM0;
1413
colors[j, i] := LUM1;
1415
colors[j, i] := (6 * LUM0 + LUM1) div 7;
1417
colors[j, i] := (5 * LUM0 + 2 * LUM1) div 7;
1419
colors[j, i] := (4 * LUM0 + 3 * LUM1) div 7;
1421
colors[j, i] := (3 * LUM0 + 4 * LUM1) div 7;
1423
colors[j, i] := (2 * LUM0 + 5 * LUM1) div 7;
1425
colors[j, i] := (LUM0 + 6 * LUM1) div 7;
1428
case colors[j, i] of
1430
colors[j, i] := LUM0;
1432
colors[j, i] := LUM1;
1434
colors[j, i] := (4 * LUM0 + LUM1) div 5;
1436
colors[j, i] := (3 * LUM0 + 2 * LUM1) div 5;
1438
colors[j, i] := (2 * LUM0 + 3 * LUM1) div 5;
1440
colors[j, i] := (LUM0 + 4 * LUM1) div 5;
1444
colors[j, i] := 255;
1446
if ((4 * x + i) < AWidth) and ((4 * y + j) < AHeight) then
1447
ADest[((4 * y + j) * AWidth + (4 * x + i))].A := colors[j][i];
1455
procedure SLATC2_ToImf(ASource: Pointer; ADest: PIntermediateFormatArray; AColorFormat: TGLEnum; AWidth, AHeight: Integer);
1457
x, y, i, j, offset: Integer;
1458
LUM0, LUM1: SmallInt;
1460
colors: T48BitBlock;
1465
temp := PGLubyte(ASource);
1466
for y := 0 to (AHeight div 4) - 1 do
1468
for x := 0 to (AWidth div 4) - 1 do
1470
LUM0 := PSmallInt(temp)^;
1472
LUM1 := PSmallInt(temp)^;
1474
bitmask := PInt64(temp)^;
1476
Decode48BitBlock(bitmask, colors);
1483
case colors[j, i] of
1485
colors[j, i] := LUM0;
1487
colors[j, i] := LUM1;
1489
colors[j, i] := (6 * LUM0 + LUM1) div 7;
1491
colors[j, i] := (5 * LUM0 + 2 * LUM1) div 7;
1493
colors[j, i] := (4 * LUM0 + 3 * LUM1) div 7;
1495
colors[j, i] := (3 * LUM0 + 4 * LUM1) div 7;
1497
colors[j, i] := (2 * LUM0 + 5 * LUM1) div 7;
1499
colors[j, i] := (LUM0 + 6 * LUM1) div 7;
1502
case colors[j, i] of
1504
colors[j, i] := LUM0;
1506
colors[j, i] := LUM1;
1508
colors[j, i] := (4 * LUM0 + LUM1) div 5;
1510
colors[j, i] := (3 * LUM0 + 2 * LUM1) div 5;
1512
colors[j, i] := (2 * LUM0 + 3 * LUM1) div 5;
1514
colors[j, i] := (LUM0 + 4 * LUM1) div 5;
1516
colors[j, i] := -127;
1518
colors[j, i] := 127;
1520
if ((4 * x + i) < AWidth) and ((4 * y + j) < AHeight) then
1522
offset := ((4 * y + j) * AWidth + (4 * x + i));
1523
lum := 2 * colors[j][i];
1524
ADest[offset].R := lum;
1525
ADest[offset].G := lum;
1526
ADest[offset].B := lum;
1531
LUM0 := PSmallInt(temp)^;
1533
LUM1 := PSmallInt(temp)^;
1535
bitmask := PInt64(temp)^;
1537
Decode48BitBlock(bitmask, colors);
1544
case colors[j, i] of
1546
colors[j, i] := LUM0;
1548
colors[j, i] := LUM1;
1550
colors[j, i] := (6 * LUM0 + LUM1) div 7;
1552
colors[j, i] := (5 * LUM0 + 2 * LUM1) div 7;
1554
colors[j, i] := (4 * LUM0 + 3 * LUM1) div 7;
1556
colors[j, i] := (3 * LUM0 + 4 * LUM1) div 7;
1558
colors[j, i] := (2 * LUM0 + 5 * LUM1) div 7;
1560
colors[j, i] := (LUM0 + 6 * LUM1) div 7;
1563
case colors[j, i] of
1565
colors[j, i] := LUM0;
1567
colors[j, i] := LUM1;
1569
colors[j, i] := (4 * LUM0 + LUM1) div 5;
1571
colors[j, i] := (3 * LUM0 + 2 * LUM1) div 5;
1573
colors[j, i] := (2 * LUM0 + 3 * LUM1) div 5;
1575
colors[j, i] := (LUM0 + 4 * LUM1) div 5;
1577
colors[j, i] := -127;
1579
colors[j, i] := 127;
1581
if ((4 * x + i) < AWidth) and ((4 * y + j) < AHeight) then
1583
ADest[((4 * y + j) * AWidth + (4 * x + i))].A := 2 * colors[j][i];
1591
procedure RGTC1_ToImf(ASource: Pointer; ADest: PIntermediateFormatArray; AColorFormat: TGLEnum; AWidth, AHeight: Integer);
1593
x, y, i, j, offset: Integer;
1596
colors: TU48BitBlock;
1601
temp := PGLubyte(ASource);
1602
for y := 0 to (AHeight div 4) - 1 do
1604
for x := 0 to (AWidth div 4) - 1 do
1610
bitmask := PInt64(temp)^;
1612
Decode48BitBlock(bitmask, colors);
1619
case colors[j, i] of
1621
colors[j, i] := RED0;
1623
colors[j, i] := RED1;
1625
colors[j, i] := (6 * RED0 + RED1) div 7;
1627
colors[j, i] := (5 * RED0 + 2 * RED1) div 7;
1629
colors[j, i] := (4 * RED0 + 3 * RED1) div 7;
1631
colors[j, i] := (3 * RED0 + 4 * RED1) div 7;
1633
colors[j, i] := (2 * RED0 + 5 * RED1) div 7;
1635
colors[j, i] := (RED0 + 6 * RED1) div 7;
1638
case colors[j, i] of
1640
colors[j, i] := RED0;
1642
colors[j, i] := RED1;
1644
colors[j, i] := (4 * RED0 + RED1) div 5;
1646
colors[j, i] := (3 * RED0 + 2 * RED1) div 5;
1648
colors[j, i] := (2 * RED0 + 3 * RED1) div 5;
1650
colors[j, i] := (RED0 + 4 * RED1) div 5;
1654
colors[j, i] := 255;
1656
if ((4 * x + i) < AWidth) and ((4 * y + j) < AHeight) then
1658
offset := ((4 * y + j) * AWidth + (4 * x + i)) * 4;
1659
lum := colors[j][i];
1660
ADest[offset].R := lum;
1661
ADest[offset].G := 0.0;
1662
ADest[offset].B := 0.0;
1663
ADest[offset].A := 255.0;
1672
procedure SRGTC1_ToImf(ASource: Pointer; ADest: PIntermediateFormatArray; AColorFormat: TGLEnum; AWidth, AHeight: Integer);
1674
x, y, i, j, offset: Integer;
1675
RED0, RED1: SmallInt;
1677
colors: T48BitBlock;
1682
temp := PGLubyte(ASource);
1683
for y := 0 to (AHeight div 4) - 1 do
1685
for x := 0 to (AWidth div 4) - 1 do
1687
RED0 := PSmallInt(temp)^;
1689
RED1 := PSmallInt(temp)^;
1691
bitmask := PInt64(temp)^;
1693
Decode48BitBlock(bitmask, colors);
1700
case colors[j, i] of
1702
colors[j, i] := RED0;
1704
colors[j, i] := RED1;
1706
colors[j, i] := (6 * RED0 + RED1) div 7;
1708
colors[j, i] := (5 * RED0 + 2 * RED1) div 7;
1710
colors[j, i] := (4 * RED0 + 3 * RED1) div 7;
1712
colors[j, i] := (3 * RED0 + 4 * RED1) div 7;
1714
colors[j, i] := (2 * RED0 + 5 * RED1) div 7;
1716
colors[j, i] := (RED0 + 6 * RED1) div 7;
1719
case colors[j, i] of
1721
colors[j, i] := RED0;
1723
colors[j, i] := RED1;
1725
colors[j, i] := (4 * RED0 + RED1) div 5;
1727
colors[j, i] := (3 * RED0 + 2 * RED1) div 5;
1729
colors[j, i] := (2 * RED0 + 3 * RED1) div 5;
1731
colors[j, i] := (RED0 + 4 * RED1) div 5;
1733
colors[j, i] := -127;
1735
colors[j, i] := 127;
1737
if ((4 * x + i) < AWidth) and ((4 * y + j) < AHeight) then
1739
offset := ((4 * y + j) * AWidth + (4 * x + i));
1740
lum := 2 * colors[j][i];
1741
ADest[offset].R := lum;
1742
ADest[offset].G := 0.0;
1743
ADest[offset].B := 0.0;
1744
ADest[offset].A := 127.0;
1753
procedure RGTC2_ToImf(ASource: Pointer; ADest: PIntermediateFormatArray; AColorFormat: TGLEnum; AWidth, AHeight: Integer);
1755
x, y, i, j, offset: Integer;
1757
colors: TU48BitBlock;
1762
temp := PGLubyte(ASource);
1763
for y := 0 to (AHeight div 4) - 1 do
1765
for x := 0 to (AWidth div 4) - 1 do
1771
bitmask := PInt64(temp)^;
1773
Decode48BitBlock(bitmask, colors);
1780
case colors[j, i] of
1782
colors[j, i] := RED0;
1784
colors[j, i] := RED1;
1786
colors[j, i] := (6 * RED0 + RED1) div 7;
1788
colors[j, i] := (5 * RED0 + 2 * RED1) div 7;
1790
colors[j, i] := (4 * RED0 + 3 * RED1) div 7;
1792
colors[j, i] := (3 * RED0 + 4 * RED1) div 7;
1794
colors[j, i] := (2 * RED0 + 5 * RED1) div 7;
1796
colors[j, i] := (RED0 + 6 * RED1) div 7;
1799
case colors[j, i] of
1801
colors[j, i] := RED0;
1803
colors[j, i] := RED1;
1805
colors[j, i] := (4 * RED0 + RED1) div 5;
1807
colors[j, i] := (3 * RED0 + 2 * RED1) div 5;
1809
colors[j, i] := (2 * RED0 + 3 * RED1) div 5;
1811
colors[j, i] := (RED0 + 4 * RED1) div 5;
1815
colors[j, i] := 255;
1817
if ((4 * x + i) < AWidth) and ((4 * y + j) < AHeight) then
1819
offset := ((4 * y + j) * AWidth + (4 * x + i));
1820
ADest[offset].R := colors[j][i];
1821
ADest[offset].B := 0.0;
1830
bitmask := PInt64(temp)^;
1832
Decode48BitBlock(bitmask, colors);
1839
case colors[j, i] of
1841
colors[j, i] := RED0;
1843
colors[j, i] := RED1;
1845
colors[j, i] := (6 * RED0 + RED1) div 7;
1847
colors[j, i] := (5 * RED0 + 2 * RED1) div 7;
1849
colors[j, i] := (4 * RED0 + 3 * RED1) div 7;
1851
colors[j, i] := (3 * RED0 + 4 * RED1) div 7;
1853
colors[j, i] := (2 * RED0 + 5 * RED1) div 7;
1855
colors[j, i] := (RED0 + 6 * RED1) div 7;
1858
case colors[j, i] of
1860
colors[j, i] := RED0;
1862
colors[j, i] := RED1;
1864
colors[j, i] := (4 * RED0 + RED1) div 5;
1866
colors[j, i] := (3 * RED0 + 2 * RED1) div 5;
1868
colors[j, i] := (2 * RED0 + 3 * RED1) div 5;
1870
colors[j, i] := (RED0 + 4 * RED1) div 5;
1874
colors[j, i] := 255;
1876
if ((4 * x + i) < AWidth) and ((4 * y + j) < AHeight) then
1878
offset := ((4 * y + j) * AWidth + (4 * x + i));
1879
ADest[offset].G := colors[j][i];
1880
ADest[offset].A := 255.0;
1888
procedure SRGTC2_ToImf(ASource: Pointer; ADest: PIntermediateFormatArray; AColorFormat: TGLEnum; AWidth, AHeight: Integer);
1890
x, y, i, j, offset: Integer;
1891
RED0, RED1: SmallInt;
1893
colors: T48BitBlock;
1898
temp := PGLubyte(ASource);
1899
for y := 0 to (AHeight div 4) - 1 do
1901
for x := 0 to (AWidth div 4) - 1 do
1903
RED0 := PSmallInt(temp)^;
1905
RED1 := PSmallInt(temp)^;
1907
bitmask := PInt64(temp)^;
1909
Decode48BitBlock(bitmask, colors);
1916
case colors[j, i] of
1918
colors[j, i] := RED0;
1920
colors[j, i] := RED1;
1922
colors[j, i] := (6 * RED0 + RED1) div 7;
1924
colors[j, i] := (5 * RED0 + 2 * RED1) div 7;
1926
colors[j, i] := (4 * RED0 + 3 * RED1) div 7;
1928
colors[j, i] := (3 * RED0 + 4 * RED1) div 7;
1930
colors[j, i] := (2 * RED0 + 5 * RED1) div 7;
1932
colors[j, i] := (RED0 + 6 * RED1) div 7;
1935
case colors[j, i] of
1937
colors[j, i] := RED0;
1939
colors[j, i] := RED1;
1941
colors[j, i] := (4 * RED0 + RED1) div 5;
1943
colors[j, i] := (3 * RED0 + 2 * RED1) div 5;
1945
colors[j, i] := (2 * RED0 + 3 * RED1) div 5;
1947
colors[j, i] := (RED0 + 4 * RED1) div 5;
1949
colors[j, i] := -127;
1951
colors[j, i] := 127;
1953
if ((4 * x + i) < AWidth) and ((4 * y + j) < AHeight) then
1955
offset := ((4 * y + j) * AWidth + (4 * x + i));
1956
lum := 2 * colors[j][i];
1957
ADest[offset].R := lum;
1958
ADest[offset].B := 0.0;
1963
RED0 := PSmallInt(temp)^;
1965
RED1 := PSmallInt(temp)^;
1967
bitmask := PInt64(temp)^;
1969
Decode48BitBlock(bitmask, colors);
1976
case colors[j, i] of
1978
colors[j, i] := RED0;
1980
colors[j, i] := RED1;
1982
colors[j, i] := (6 * RED0 + RED1) div 7;
1984
colors[j, i] := (5 * RED0 + 2 * RED1) div 7;
1986
colors[j, i] := (4 * RED0 + 3 * RED1) div 7;
1988
colors[j, i] := (3 * RED0 + 4 * RED1) div 7;
1990
colors[j, i] := (2 * RED0 + 5 * RED1) div 7;
1992
colors[j, i] := (RED0 + 6 * RED1) div 7;
1995
case colors[j, i] of
1997
colors[j, i] := RED0;
1999
colors[j, i] := RED1;
2001
colors[j, i] := (4 * RED0 + RED1) div 5;
2003
colors[j, i] := (3 * RED0 + 2 * RED1) div 5;
2005
colors[j, i] := (2 * RED0 + 3 * RED1) div 5;
2007
colors[j, i] := (RED0 + 4 * RED1) div 5;
2009
colors[j, i] := -127;
2011
colors[j, i] := 127;
2013
if ((4 * x + i) < AWidth) and ((4 * y + j) < AHeight) then
2015
offset := ((4 * y + j) * AWidth + (4 * x + i));
2016
lum := 2 * colors[j][i];
2017
ADest[offset].G := lum;
2018
ADest[offset].A := 127.0;
2026
{$IFDEF GLS_REGIONS}{$ENDREGION 'Decompression'}{$ENDIF}
2027
{$IFDEF GLS_REGIONS}{$REGION 'RGBA Float to OpenGL format image'}{$ENDIF}
2029
procedure UnsupportedFromImf(ASource: PIntermediateFormatArray; ADest: Pointer; AColorFormat: TGLEnum; AWidth, AHeight: Integer);
2031
raise EGLImageUtils.Create('Unimplemented type of conversion');
2034
procedure ImfToUbyte(ASource: PIntermediateFormatArray; ADest: Pointer; AColorFormat: TGLEnum; AWidth, AHeight: Integer);
2039
procedure SetChannel(AValue: Single);
2041
pDest^ := Trunc(ClampValue(AValue, 0.0, 255.0));
2045
procedure SetChannelI(AValue: Single);
2047
pDest^ := Trunc(AValue);
2052
pDest := PByte(ADest);
2054
case AColorFormat of
2055
{$INCLUDE ImgUtilCaseImf2GL.inc}
2057
raise EGLImageUtils.Create(strInvalidType);
2061
procedure ImfToByte(ASource: PIntermediateFormatArray; ADest: Pointer; AColorFormat: TGLEnum; AWidth, AHeight: Integer);
2066
procedure SetChannel(AValue: Single);
2068
pDest^ := Trunc(ClampValue(AValue, -127.0, 127.0));
2072
procedure SetChannelI(AValue: Single);
2074
pDest^ := Trunc(AValue);
2079
pDest := PShortInt(ADest);
2081
case AColorFormat of
2082
{$INCLUDE ImgUtilCaseImf2GL.inc}
2084
raise EGLImageUtils.Create(strInvalidType);
2088
procedure ImfToUShort(ASource: PIntermediateFormatArray; ADest: Pointer; AColorFormat: TGLEnum; AWidth, AHeight: Integer);
2093
procedure SetChannel(AValue: Single);
2095
pDest^ := Trunc(ClampValue(AValue, 0.0, 65535.0));
2099
procedure SetChannelI(AValue: Single);
2101
pDest^ := Trunc(AValue);
2106
pDest := PWord(ADest);
2108
case AColorFormat of
2109
{$INCLUDE ImgUtilCaseImf2GL.inc}
2111
raise EGLImageUtils.Create(strInvalidType);
2115
procedure ImfToShort(ASource: PIntermediateFormatArray; ADest: Pointer; AColorFormat: TGLEnum; AWidth, AHeight: Integer);
2120
procedure SetChannel(AValue: Single);
2122
pDest^ := Trunc(ClampValue(AValue, -32767.0, 32767.0));
2126
procedure SetChannelI(AValue: Single);
2128
pDest^ := Trunc(AValue);
2133
pDest := PSmallInt(ADest);
2135
case AColorFormat of
2136
{$INCLUDE ImgUtilCaseImf2GL.inc}
2138
raise EGLImageUtils.Create(strInvalidType);
2142
procedure ImfToUInt(ASource: PIntermediateFormatArray; ADest: Pointer; AColorFormat: TGLEnum; AWidth, AHeight: Integer);
2147
procedure SetChannel(AValue: Single);
2149
pDest^ := Trunc(ClampValue(AValue, 0.0, $FFFFFFFF));
2153
procedure SetChannelI(AValue: Single);
2155
pDest^ := Trunc(AValue);
2160
pDest := PLongWord(ADest);
2162
case AColorFormat of
2163
{$INCLUDE ImgUtilCaseImf2GL.inc}
2165
raise EGLImageUtils.Create(strInvalidType);
2169
procedure ImfToInt(ASource: PIntermediateFormatArray; ADest: Pointer; AColorFormat: TGLEnum; AWidth, AHeight: Integer);
2174
procedure SetChannel(AValue: Single);
2176
pDest^ := Trunc(ClampValue(AValue, -$7FFFFFFF, $7FFFFFFF));
2180
procedure SetChannelI(AValue: Single);
2182
pDest^ := Trunc(AValue);
2187
pDest := PLongInt(ADest);
2189
case AColorFormat of
2190
{$INCLUDE ImgUtilCaseImf2GL.inc}
2192
raise EGLImageUtils.Create(strInvalidType);
2196
procedure ImfToFloat(ASource: PIntermediateFormatArray; ADest: Pointer; AColorFormat: TGLEnum; AWidth, AHeight: Integer);
2198
cInv255 = 1.0 / 255.0;
2204
procedure SetChannel(AValue: Single);
2206
pDest^ := AValue * cInv255;
2210
procedure SetChannelI(AValue: Single);
2212
pDest^ := AValue * cInv255;
2217
pDest := PSingle(ADest);
2219
case AColorFormat of
2220
{$INCLUDE ImgUtilCaseImf2GL.inc}
2222
raise EGLImageUtils.Create(strInvalidType);
2226
procedure ImfToHalf(ASource: PIntermediateFormatArray; ADest: Pointer; AColorFormat: TGLEnum; AWidth, AHeight: Integer);
2228
cInv255 = 1.0 / 255.0;
2234
procedure SetChannel(AValue: Single);
2236
pDest^ := FloatToHalf(AValue * cInv255);
2240
procedure SetChannelI(AValue: Single);
2242
pDest^ := FloatToHalf(AValue * cInv255);
2247
pDest := PHalfFloat(ADest);
2249
case AColorFormat of
2250
{$INCLUDE ImgUtilCaseImf2GL.inc}
2252
raise EGLImageUtils.Create(strInvalidType);
2255
{$IFDEF GLS_REGIONS}{$ENDREGION 'RGBA Float to OpenGL format image'}{$ENDIF}
2256
{$IFDEF GLS_REGIONS}{$REGION 'Compression'}{$ENDIF}
2257
{ function FloatTo565(const AColor: TIntermediateFormat): Integer;
2261
// get the components in the correct range
2262
r := Round( 31.0*AColor.R, 31 );
2263
g := Round( 63.0*AColor.G, 63 );
2264
b := Round( 31.0*AColor.B, 31 );
2265
// pack into a single value
2266
Result := ( r shl 11 ) or ( g shl 5 ) or b;
2269
procedure WriteColourBlock(a, b: Integer; const indices: PByteArray; out block: TU48BitBlock);
2273
// write the endpoints
2274
block[0][0] := a and $ff;
2275
block[0][1] := a shr 8;
2276
block[0][2] := b and $ff;
2277
block[0][3] := b shr 8;
2278
// write the indices
2282
block[1][i] = indices[J+0] or ( indices[J+1] shl 2 ) or ( indices[J+2] shl 4 ) or ( indices[J+3] shl 6 );
2286
procedure WriteColourBlock3(start, end_: TIntermediateFormat; const indices: PByteArray; out block: TU48BitBlock);
2289
remapped: array[0..15] of Byte;
2291
// get the packed values
2292
a := FloatTo565( start );
2293
b := FloatTo565( end_ );
2295
// remap the indices
2298
// use the indices directly
2300
remapped[i] := indices[i];
2308
if indices[i] = 0 then
2310
else if indices[i] = 1 then
2313
remapped[i] := indices[i];
2318
WriteColourBlock( a, b, remapped, block );
2321
procedure WriteColourBlock4(start, end_: TIntermediateFormat; const indices: PByteArray; out block: TU48BitBlock);
2324
remapped: array[0..15] of Byte;
2326
// get the packed values
2327
a := FloatTo565( start );
2328
b := FloatTo565( end_ );
2330
// remap the indices
2336
remapped[i] := ( indices[i] xor $01 ) and $03;
2346
// use the indices directly
2348
remapped[i] := indices[i];
2352
WriteColourBlock( a, b, remapped, block );
2355
{$IFDEF GLS_REGIONS}{$ENDREGION 'Compression'}{$ENDIF}
2356
{$IFDEF GLS_REGIONS}{$REGION 'Image filters'}{$ENDIF}
2358
function ImageBoxFilter(Value: Single): Single;
2360
if (Value > -0.5) and (Value <= 0.5) then
2366
function ImageTriangleFilter(Value: Single): Single;
2371
Result := 1.0 - Value
2376
function ImageHermiteFilter(Value: Single): Single;
2381
Result := (2 * Value - 3) * Sqr(Value) + 1
2386
function ImageBellFilter(Value: Single): Single;
2391
Result := 0.75 - Sqr(Value)
2392
else if Value < 1.5 then
2394
Value := Value - 1.5;
2395
Result := 0.5 * Sqr(Value);
2401
function ImageSplineFilter(Value: Single): Single;
2410
Result := 0.5 * temp * Value - temp + 2.0 / 3.0;
2412
else if Value < 2.0 then
2414
Value := 2.0 - Value;
2415
Result := Sqr(Value) * Value / 6.0;
2421
function ImageLanczos3Filter(Value: Single): Single;
2430
if Value < Radius then
2432
Value := Value * pi;
2433
Result := Radius * Sin(Value) * Sin(Value / Radius) / (Value * Value);
2439
function ImageMitchellFilter(Value: Single): Single;
2451
Value := (((12.0 - 9.0 * B - 6.0 * C) * (Value * temp)) + ((-18.0 + 12.0 * B + 6.0 * C) * temp) + (6.0 - 2.0 * B));
2452
Result := Value / 6.0;
2454
else if Value < 2.0 then
2456
Value := (((-B - 6.0 * C) * (Value * temp)) + ((6.0 * B + 30.0 * C) * temp) + ((-12.0 * B - 48.0 * C) * Value) + (8.0 * B + 24.0 * C));
2457
Result := Value / 6.0;
2463
const cInvThree = 1.0/3.0;
2465
procedure ImageAlphaFromIntensity(var AColor: TIntermediateFormat);
2467
AColor.A := (AColor.R + AColor.B + AColor.G) * cInvThree;
2470
procedure ImageAlphaSuperBlackTransparent(var AColor: TIntermediateFormat);
2472
if (AColor.R = 0.0) and (AColor.B = 0.0) and (AColor.G = 0.0) then
2478
procedure ImageAlphaLuminance(var AColor: TIntermediateFormat);
2480
AColor.A := (AColor.R + AColor.B + AColor.G) * cInvThree;
2481
AColor.R := AColor.A;
2482
AColor.G := AColor.A;
2483
AColor.B := AColor.A;
2486
procedure ImageAlphaLuminanceSqrt(var AColor: TIntermediateFormat);
2488
AColor.A := Sqrt((AColor.R + AColor.B + AColor.G) * cInvThree);
2491
procedure ImageAlphaOpaque(var AColor: TIntermediateFormat);
2497
vTopLeftColor: TIntermediateFormat;
2499
procedure ImageAlphaTopLeftPointColorTransparent(var AColor: TIntermediateFormat);
2501
if CompareMem(@AColor, @vTopLeftColor, 3*SizeOf(Single)) then
2505
procedure ImageAlphaInverseLuminance(var AColor: TIntermediateFormat);
2507
AColor.A := 255.0 - (AColor.R + AColor.B + AColor.G) * cInvThree;
2508
AColor.R := AColor.A;
2509
AColor.G := AColor.A;
2510
AColor.B := AColor.A;
2513
procedure ImageAlphaInverseLuminanceSqrt(var AColor: TIntermediateFormat);
2515
AColor.A := 255.0 - Sqrt((AColor.R + AColor.B + AColor.G) * cInvThree);
2519
vBottomRightColor: TIntermediateFormat;
2521
procedure ImageAlphaBottomRightPointColorTransparent(var AColor: TIntermediateFormat);
2523
if CompareMem(@AColor, @vBottomRightColor, 3*SizeOf(Single)) then
2529
// Contributor for a pixel
2530
TContributor = record
2531
pixel: Integer; // Source pixel
2532
weight: Single; // Pixel weight
2535
TContributorList = array [0 .. MaxInt div (2 * SizeOf(TContributor))] of TContributor;
2536
PContributorList = ^TContributorList;
2538
// List of source pixels contributing to a destination pixel
2541
p: PContributorList;
2544
TCListList = array [0 .. MaxInt div (2 * SizeOf(TCList))] of TCList;
2545
PCListList = ^TCListList;
2547
{$IFDEF GLS_REGIONS}{$ENDREGION 'Image filters'}{$ENDIF}
2548
{$IFDEF GLS_REGIONS}{$REGION 'Data type conversion table'}{$ENDIF}
2551
TConvertTableRec = record
2553
proc1: TConvertToImfProc;
2554
proc2: TConvertFromInfProc;
2558
cConvertTable: array [0 .. 36] of TConvertTableRec = (
2559
(type_: GL_UNSIGNED_BYTE; proc1: UbyteToImf; proc2: ImfToUbyte),
2561
(type_: GL_UNSIGNED_BYTE_3_3_2; proc1: Ubyte332ToImf; proc2: UnsupportedFromImf),
2563
(type_: GL_UNSIGNED_BYTE_2_3_3_REV; proc1: Ubyte233RToImf; proc2: UnsupportedFromImf),
2565
(type_: GL_BYTE; proc1: ByteToImf; proc2: ImfToByte),
2567
(type_: GL_UNSIGNED_SHORT; proc1: UShortToImf; proc2: ImfToUShort),
2569
(type_: GL_SHORT; proc1: ShortToImf; proc2: ImfToShort),
2571
(type_: GL_UNSIGNED_INT; proc1: UIntToImf; proc2: ImfToUInt),
2573
(type_: GL_INT; proc1: IntToImf; proc2: ImfToInt),
2575
(type_: GL_FLOAT; proc1: FloatToImf; proc2: ImfToFloat),
2577
(type_: GL_HALF_FLOAT; proc1: HalfFloatToImf; proc2: ImfToHalf),
2579
(type_: GL_UNSIGNED_INT_8_8_8_8; proc1: UInt8888ToImf; proc2: UnsupportedFromImf),
2581
(type_: GL_UNSIGNED_INT_8_8_8_8_REV; proc1: UInt8888RevToImf; proc2: UnsupportedFromImf),
2583
(type_: GL_UNSIGNED_SHORT_4_4_4_4; proc1: UShort4444ToImf; proc2: UnsupportedFromImf),
2585
(type_: GL_UNSIGNED_SHORT_4_4_4_4_REV; proc1: UShort4444RevToImf; proc2: UnsupportedFromImf),
2587
(type_: GL_UNSIGNED_SHORT_5_6_5; proc1: UShort565ToImf; proc2: UnsupportedFromImf),
2589
(type_: GL_UNSIGNED_SHORT_5_6_5_REV; proc1: UShort565RevToImf; proc2: UnsupportedFromImf),
2591
(type_: GL_UNSIGNED_SHORT_5_5_5_1; proc1: UShort5551ToImf; proc2: UnsupportedFromImf),
2593
(type_: GL_UNSIGNED_SHORT_1_5_5_5_REV; proc1: UShort5551RevToImf; proc2: UnsupportedFromImf),
2595
(type_: GL_UNSIGNED_INT_10_10_10_2; proc1: UInt_10_10_10_2_ToImf; proc2: UnsupportedFromImf),
2597
(type_: GL_UNSIGNED_INT_2_10_10_10_REV; proc1: UInt_10_10_10_2_Rev_ToImf; proc2: UnsupportedFromImf),
2599
(type_: GL_COMPRESSED_RGB_S3TC_DXT1_EXT; proc1: DXT1_ToImf; proc2: UnsupportedFromImf),
2601
(type_: GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; proc1: DXT1_ToImf; proc2: UnsupportedFromImf),
2603
(type_: GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; proc1: DXT3_ToImf; proc2: UnsupportedFromImf),
2605
(type_: GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; proc1: DXT5_ToImf; proc2: UnsupportedFromImf),
2607
(type_: GL_COMPRESSED_SRGB_S3TC_DXT1_EXT; proc1: UnsupportedToImf; proc2: UnsupportedFromImf),
2609
(type_: GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT; proc1: UnsupportedToImf; proc2: UnsupportedFromImf),
2611
(type_: GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT; proc1: UnsupportedToImf; proc2: UnsupportedFromImf),
2613
(type_: GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT; proc1: UnsupportedToImf; proc2: UnsupportedFromImf),
2615
(type_: GL_COMPRESSED_LUMINANCE_LATC1_EXT; proc1: LATC1_ToImf; proc2: UnsupportedFromImf),
2617
(type_: GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT; proc1: SLATC1_ToImf; proc2: UnsupportedFromImf),
2619
(type_: GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT; proc1: LATC2_ToImf; proc2: UnsupportedFromImf),
2621
(type_: GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT; proc1: SLATC2_ToImf; proc2: UnsupportedFromImf),
2623
(type_: GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI; proc1: UnsupportedToImf; proc2: UnsupportedFromImf),
2625
(type_: GL_COMPRESSED_RED_RGTC1; proc1: RGTC1_ToImf; proc2: UnsupportedFromImf),
2627
(type_: GL_COMPRESSED_SIGNED_RED_RGTC1; proc1: SRGTC1_ToImf; proc2: UnsupportedFromImf),
2629
(type_: GL_COMPRESSED_RG_RGTC2; proc1: RGTC2_ToImf; proc2: UnsupportedFromImf),
2631
(type_: GL_COMPRESSED_SIGNED_RG_RGTC2; proc1: SRGTC2_ToImf; proc2: UnsupportedFromImf));
2633
{$IFDEF GLS_REGIONS}{$ENDREGION 'Data type conversion table'}{$ENDIF}
2635
procedure ConvertImage(const ASrc: Pointer; const ADst: Pointer; ASrcColorFormat, ADstColorFormat: TGLEnum; ASrcDataType, ADstDataType: TGLEnum; AWidth, AHeight: Integer);
2637
ConvertToIntermediateFormat: TConvertToImfProc;
2638
ConvertFromIntermediateFormat: TConvertFromInfProc;
2640
tempBuf: PIntermediateFormatArray;
2644
AHeight := MaxInteger(1, AHeight);
2646
size := AWidth * AHeight * SizeOf(TIntermediateFormat);
2647
GetMem(tempBuf, size);
2648
FillChar(tempBuf^, size, $00);
2650
// Find function to convert external format to intermediate format
2651
ConvertToIntermediateFormat := UnsupportedToImf;
2652
for i := 0 to high(cConvertTable) do
2654
if ASrcDataType = cConvertTable[i].type_ then
2656
ConvertToIntermediateFormat := cConvertTable[i].proc1;
2662
ConvertToIntermediateFormat(ASrc, tempBuf, ASrcColorFormat, AWidth, AHeight);
2668
// Find function to convert intermediate format to external format
2669
ConvertFromIntermediateFormat := UnsupportedFromImf;
2670
for i := 0 to high(cConvertTable) do
2672
if ADstDataType = cConvertTable[i].type_ then
2674
ConvertFromIntermediateFormat := cConvertTable[i].proc2;
2680
ConvertFromIntermediateFormat(tempBuf, ADst, ADstColorFormat, AWidth, AHeight);
2689
procedure RescaleImage(
2690
const ASrc: Pointer;
2691
const ADst: Pointer;
2692
AColorFormat: TGLEnum;
2694
AFilter: TImageFilterFunction;
2695
ASrcWidth, ASrcHeight, ADstWidth, ADstHeight: Integer);
2698
ConvertToIntermediateFormat: TConvertToImfProc;
2699
ConvertFromIntermediateFormat: TConvertFromInfProc;
2700
i, j, k, n, size: Integer;
2701
tempBuf1, tempBuf2, SourceLine, DestLine: PIntermediateFormatArray;
2702
contrib: PCListList;
2703
xscale, yscale: Single; // Zoom scale factors
2704
width, fscale, weight: Single; // Filter calculation variables
2705
center: Single; // Filter calculation variables
2706
left, right: Integer; // Filter calculation variables
2707
color1, color2: TIntermediateFormat;
2709
if (ASrcWidth < 1) or (ADstWidth < 1) then
2711
ASrcHeight := MaxInteger(1, ASrcHeight);
2712
ADstHeight := MaxInteger(1, ADstHeight);
2715
size := ASrcWidth * ASrcHeight * SizeOf(TIntermediateFormat);
2716
GetMem(tempBuf1, size);
2717
FillChar(tempBuf1^, size, $00);
2719
// Find function to convert external format to intermediate format
2720
ConvertToIntermediateFormat := UnsupportedToImf;
2721
for i := 0 to high(cConvertTable) do
2723
if ADataType = cConvertTable[i].type_ then
2725
ConvertToIntermediateFormat := cConvertTable[i].proc1;
2726
ConvertFromIntermediateFormat := cConvertTable[i].proc2;
2732
ConvertToIntermediateFormat(ASrc, tempBuf1, AColorFormat, ASrcWidth, ASrcHeight);
2740
if ASrcWidth = 1 then
2741
xscale := ADstWidth / ASrcWidth
2743
xscale := (ADstWidth - 1) / (ASrcWidth - 1);
2744
if ASrcHeight = 1 then
2745
yscale := ADstHeight / ASrcHeight
2747
yscale := (ADstHeight - 1) / (ASrcHeight - 1);
2748
// Pre-calculate filter contributions for a row
2749
GetMem(contrib, ADstWidth * SizeOf(TCList));
2750
// Horizontal sub-sampling
2751
// Scales from bigger to smaller width
2752
if xscale < 1.0 then
2754
width := vImageScaleFilterWidth / xscale;
2755
fscale := 1.0 / xscale;
2756
for i := 0 to ADstWidth - 1 do
2759
GetMem(contrib^[i].p, Trunc(width * 2.0 + 1) * SizeOf(TContributor));
2760
center := i / xscale;
2761
left := floor(center - width);
2762
right := ceil(center + width);
2763
for j := left to right do
2765
weight := AFilter((center - j) / fscale) / fscale;
2766
if weight = 0.0 then
2770
else if (j >= ASrcWidth) then
2771
n := ASrcWidth - j + ASrcWidth - 1
2775
contrib^[i].n := contrib^[i].n + 1;
2776
contrib^[i].p^[k].pixel := n;
2777
contrib^[i].p^[k].weight := weight;
2782
// Horizontal super-sampling
2783
// Scales from smaller to bigger width
2785
for i := 0 to ADstWidth - 1 do
2788
GetMem(contrib^[i].p, Trunc(vImageScaleFilterWidth * 2.0 + 1) * SizeOf(TContributor));
2789
center := i / xscale;
2790
left := floor(center - vImageScaleFilterWidth);
2791
right := ceil(center + vImageScaleFilterWidth);
2792
for j := left to right do
2794
weight := AFilter(center - j);
2795
if weight = 0.0 then
2799
else if (j >= ASrcWidth) then
2800
n := ASrcWidth - j + ASrcWidth - 1
2804
contrib^[i].n := contrib^[i].n + 1;
2805
contrib^[i].p^[k].pixel := n;
2806
contrib^[i].p^[k].weight := weight;
2811
size := ADstWidth * ASrcHeight * SizeOf(TIntermediateFormat);
2812
GetMem(tempBuf2, size);
2814
// Apply filter to sample horizontally from Src to Work
2815
for k := 0 to ASrcHeight - 1 do
2817
SourceLine := @tempBuf1[k * ASrcWidth];
2818
DestLine := @tempBuf2[k * ADstWidth];
2819
for i := 0 to ADstWidth - 1 do
2821
color1 := cSuperBlack;
2822
for j := 0 to contrib^[i].n - 1 do
2824
weight := contrib^[i].p^[j].weight;
2825
if weight = 0.0 then
2827
color2 := SourceLine[contrib^[i].p^[j].pixel];
2828
color1.R := color1.R + color2.R * weight;
2829
color1.G := color1.G + color2.G * weight;
2830
color1.B := color1.B + color2.B * weight;
2831
color1.A := color1.A + color2.A * weight;
2833
// Set new pixel value
2834
DestLine[i] := color1;
2838
// Free the memory allocated for horizontal filter weights
2839
for i := 0 to ADstWidth - 1 do
2840
FreeMem(contrib^[i].p);
2843
// Pre-calculate filter contributions for a column
2844
GetMem(contrib, ADstHeight * SizeOf(TCList));
2845
// Vertical sub-sampling
2846
// Scales from bigger to smaller height
2847
if yscale < 1.0 then
2849
width := vImageScaleFilterWidth / yscale;
2850
fscale := 1.0 / yscale;
2851
for i := 0 to ADstHeight - 1 do
2854
GetMem(contrib^[i].p, Trunc(width * 2.0 + 1) * SizeOf(TContributor));
2855
center := i / yscale;
2856
left := floor(center - width);
2857
right := ceil(center + width);
2858
for j := left to right do
2860
weight := AFilter((center - j) / fscale) / fscale;
2861
if weight = 0.0 then
2865
else if (j >= ASrcHeight) then
2866
n := MaxInteger(ASrcHeight - j + ASrcHeight - 1, 0)
2870
contrib^[i].n := contrib^[i].n + 1;
2871
contrib^[i].p^[k].pixel := n;
2872
contrib^[i].p^[k].weight := weight;
2877
// Vertical super-sampling
2878
// Scales from smaller to bigger height
2880
for i := 0 to ADstHeight - 1 do
2883
GetMem(contrib^[i].p, Trunc(vImageScaleFilterWidth * 2.0 + 1) * SizeOf(TContributor));
2884
center := i / yscale;
2885
left := floor(center - vImageScaleFilterWidth);
2886
right := ceil(center + vImageScaleFilterWidth);
2887
for j := left to right do
2889
weight := AFilter(center - j);
2890
if weight = 0.0 then
2894
else if (j >= ASrcHeight) then
2895
n := MaxInteger(ASrcHeight - j + ASrcHeight - 1, 0)
2899
contrib^[i].n := contrib^[i].n + 1;
2900
contrib^[i].p^[k].pixel := n;
2901
contrib^[i].p^[k].weight := weight;
2906
size := ADstWidth * ADstHeight * SizeOf(TIntermediateFormat);
2907
ReallocMem(tempBuf1, size);
2909
// Apply filter to sample vertically from Work to Dst
2910
for k := 0 to ADstWidth - 1 do
2912
for i := 0 to ADstHeight - 1 do
2914
color1 := cSuperBlack;
2915
for j := 0 to contrib^[i].n - 1 do
2917
weight := contrib^[i].p^[j].weight;
2918
if weight = 0.0 then
2920
color2 := tempBuf2[k + contrib^[i].p^[j].pixel * ADstWidth];
2921
color1.R := color1.R + color2.R * weight;
2922
color1.G := color1.G + color2.G * weight;
2923
color1.B := color1.B + color2.B * weight;
2924
color1.A := color1.A + color2.A * weight;
2926
tempBuf1[k + i * ADstWidth] := color1;
2930
// Free the memory allocated for vertical filter weights
2931
for i := 0 to ADstHeight - 1 do
2932
FreeMem(contrib^[i].p);
2937
// Back to native image format
2939
ConvertFromIntermediateFormat(tempBuf1, ADst, AColorFormat, ADstWidth, ADstHeight);
2947
procedure Div2(var Value: Integer); {$IFDEF GLS_INLINE} inline; {$ENDIF}
2949
Value := Value div 2;
2954
procedure Build2DMipmap(
2955
const ASrc: Pointer;
2956
const ADst: TPointerArray;
2957
AColorFormat: TGLEnum;
2959
AFilter: TImageFilterFunction;
2960
ASrcWidth, ASrcHeight: Integer);
2963
ConvertToIntermediateFormat: TConvertToImfProc;
2964
ConvertFromIntermediateFormat: TConvertFromInfProc;
2965
ADstWidth, ADstHeight: Integer;
2966
i, j, k, n, size, level: Integer;
2967
tempBuf1, tempBuf2, storePtr, SourceLine, DestLine: PIntermediateFormatArray;
2968
contrib: PCListList;
2969
xscale, yscale: Single;
2970
width, fscale, weight: Single;
2972
left, right: Integer;
2973
color1, color2: TIntermediateFormat;
2974
tempW, tempH: Integer;
2977
if ASrcWidth < 1 then
2979
ASrcHeight := MaxInteger(1, ASrcHeight);
2983
tempH := ASrcHeight;
2985
for level := 0 to High(ADst) + 1 do
2987
Inc(size, tempW * tempH * SizeOf(TIntermediateFormat));
2991
GetMem(tempBuf1, size);
2992
storePtr := tempBuf1;
2993
FillChar(tempBuf1^, size, $00);
2994
GetMem(tempBuf2, ASrcWidth * ASrcHeight * SizeOf(TIntermediateFormat));
2996
// Find function to convert external format to intermediate format
2997
ConvertToIntermediateFormat := UnsupportedToImf;
2998
ConvertFromIntermediateFormat := UnsupportedFromImf;
2999
for i := 0 to high(cConvertTable) do
3001
if ADataType = cConvertTable[i].type_ then
3003
ConvertToIntermediateFormat := cConvertTable[i].proc1;
3004
ConvertFromIntermediateFormat := cConvertTable[i].proc2;
3010
ConvertToIntermediateFormat(ASrc, tempBuf1, AColorFormat, ASrcWidth, ASrcHeight);
3018
tempH := ASrcHeight;
3022
for level := 0 to High(ADst) do
3024
ADstWidth := ASrcWidth;
3025
ADstHeight := ASrcHeight;
3029
xscale := MaxFloat((ADstWidth - 1) / (ASrcWidth - 1), 0.25);
3030
yscale := MaxFloat((ADstHeight - 1) / (ASrcHeight - 1), 0.25);
3032
// Pre-calculate filter contributions for a row
3033
ReallocMem(contrib, ADstWidth * SizeOf(TCList));
3034
// Horizontal sub-sampling
3035
// Scales from bigger to smaller width
3036
width := vImageScaleFilterWidth / xscale;
3037
fscale := 1.0 / xscale;
3038
for i := 0 to ADstWidth - 1 do
3041
GetMem(contrib^[i].p, Trunc(width * 2.0 + 1.0) * SizeOf(TContributor));
3042
center := i / xscale;
3043
left := floor(center - width);
3044
right := ceil(center + width);
3045
for j := left to right do
3047
weight := AFilter((center - j) / fscale) / fscale;
3048
if weight = 0.0 then
3052
else if (j >= ASrcWidth) then
3053
n := MaxInteger(ASrcWidth - j + ASrcWidth - 1, 0)
3057
contrib^[i].n := contrib^[i].n + 1;
3058
contrib^[i].p^[k].pixel := n;
3059
contrib^[i].p^[k].weight := weight;
3063
// Apply filter to sample horizontally from Src to Work
3064
for k := 0 to ASrcHeight - 1 do
3066
SourceLine := @tempBuf1[k * ASrcWidth];
3067
DestLine := @tempBuf2[k * ADstWidth];
3068
for i := 0 to ADstWidth - 1 do
3070
color1 := cSuperBlack;
3071
for j := 0 to contrib^[i].n - 1 do
3073
weight := contrib^[i].p^[j].weight;
3074
if weight = 0.0 then
3076
color2 := SourceLine[contrib^[i].p^[j].pixel];
3077
color1.R := color1.R + color2.R * weight;
3078
color1.G := color1.G + color2.G * weight;
3079
color1.B := color1.B + color2.B * weight;
3080
color1.A := color1.A + color2.A * weight;
3082
// Set new pixel value
3083
DestLine[i] := color1;
3087
// Free the memory allocated for horizontal filter weights
3088
for i := 0 to ADstWidth - 1 do
3089
FreeMem(contrib^[i].p);
3091
// Pre-calculate filter contributions for a column
3092
ReallocMem(contrib, ADstHeight * SizeOf(TCList));
3093
// Vertical sub-sampling
3094
// Scales from bigger to smaller height
3095
width := vImageScaleFilterWidth / yscale;
3096
fscale := 1.0 / yscale;
3097
for i := 0 to ADstHeight - 1 do
3100
GetMem(contrib^[i].p, Trunc(width * 2.0 + 1) * SizeOf(TContributor));
3101
center := i / yscale;
3102
left := floor(center - width);
3103
right := ceil(center + width);
3104
for j := left to right do
3106
weight := AFilter((center - j) / fscale) / fscale;
3107
if weight = 0.0 then
3111
else if (j >= ASrcHeight) then
3112
n := MaxInteger(ASrcHeight - j + ASrcHeight - 1, 0)
3116
contrib^[i].n := contrib^[i].n + 1;
3117
contrib^[i].p^[k].pixel := n;
3118
contrib^[i].p^[k].weight := weight;
3122
size := ASrcWidth * ASrcHeight * SizeOf(TIntermediateFormat);
3123
Inc(PByte(tempBuf1), size);
3125
// Apply filter to sample vertically from Work to Dst
3126
for k := 0 to ADstWidth - 1 do
3128
for i := 0 to ADstHeight - 1 do
3130
color1 := cSuperBlack;
3131
for j := 0 to contrib^[i].n - 1 do
3133
weight := contrib^[i].p^[j].weight;
3134
if weight = 0.0 then
3136
n := k + contrib^[i].p^[j].pixel * ADstWidth;
3137
color2 := tempBuf2[n];
3138
color1.R := color1.R + color2.R * weight;
3139
color1.G := color1.G + color2.G * weight;
3140
color1.B := color1.B + color2.B * weight;
3141
color1.A := color1.A + color2.A * weight;
3143
tempBuf1[k + i * ADstWidth] := color1;
3147
// Free the memory allocated for vertical filter weights
3148
for i := 0 to ADstHeight - 1 do
3149
FreeMem(contrib^[i].p);
3151
ASrcWidth := ADstWidth;
3152
ASrcHeight := ADstHeight;
3154
// Back to native image format
3155
ConvertFromIntermediateFormat(
3156
tempBuf1, ADst[level], AColorFormat, ASrcWidth, ASrcHeight);
3159
if Assigned(contrib) then
3166
procedure AlphaGammaBrightCorrection(
3167
const ASrc: Pointer;
3168
AColorFormat: TGLEnum;
3170
ASrcWidth, ASrcHeight: Integer;
3171
anAlphaProc: TImageAlphaProc;
3172
ABrightness: Single;
3176
ConvertToIntermediateFormat: TConvertToImfProc;
3177
ConvertFromIntermediateFormat: TConvertFromInfProc;
3178
tempBuf1: PIntermediateFormatArray;
3181
if ASrcWidth < 1 then
3183
ASrcHeight := MaxInteger(1, ASrcHeight);
3184
Size := ASrcWidth * ASrcHeight;
3185
GetMem(tempBuf1, Size * SizeOf(TIntermediateFormat));
3187
// Find function to convert external format to intermediate format
3188
ConvertToIntermediateFormat := UnsupportedToImf;
3189
ConvertFromIntermediateFormat := UnsupportedFromImf;
3190
for i := 0 to high(cConvertTable) do
3192
if ADataType = cConvertTable[i].type_ then
3194
ConvertToIntermediateFormat := cConvertTable[i].proc1;
3195
ConvertFromIntermediateFormat := cConvertTable[i].proc2;
3201
ConvertToIntermediateFormat(
3202
ASrc, tempBuf1, AColorFormat, ASrcWidth, ASrcHeight);
3204
vTopLeftColor := tempBuf1[0];
3205
vBottomRightColor := tempBuf1[Size-1];
3207
if Assigned(anAlphaProc) then
3208
for I := Size - 1 downto 0 do
3209
anAlphaProc(tempBuf1[I]);
3211
if ABrightness <> 1.0 then
3212
for I := Size - 1 downto 0 do
3215
R := R * ABrightness;
3216
G := G * ABrightness;
3217
B := B * ABrightness;
3220
if AGamma <> 1.0 then
3221
for I := Size - 1 downto 0 do
3224
R := Power(R, AGamma);
3225
G := Power(G, AGamma);
3226
B := Power(B, AGamma);
3229
// Back to native image format
3230
ConvertFromIntermediateFormat(
3231
tempBuf1, ASrc, AColorFormat, ASrcWidth, ASrcHeight);