{
PixelGraphicSimpleScaling реализует алгоритм масштабирования растровой
графики «простое масштабирование», который написал(а) Andrea Mazzoleni.
Copyright © 2001–2004 Andrea Mazzoleni
Copyright © 2016–2017, 2019–2023 Малик Разработчик
Это свободная программа: вы можете перераспространять её и/или
изменять её на условиях Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 2 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она может быть полезна,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЁННЫХ ЦЕЛЕЙ. Подробнее см. в Стандартной
общественной лицензии GNU.
Вы должны были получить копию Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<http://www.gnu.org/licenses/>.
}
unit PixelGraphicSimpleScaling;
{$MODE DELPHI}
interface
uses
Lang,
PixelGraphicScaling;
{%region public }
type
Algorithm = class(RefCountInterfacedObject, PixelGraphicScalingAlgorithm)
private
pixels16bit: short_Array1d;
inp: PIntArray;
width: int;
height: int;
inScanline: int;
square3x3: int_Array1d;
intermediate: short_Array1d;
public
constructor create();
procedure setSource(pixels: PIntArray; width, height, scanline: int);
procedure scale2x(outp: PIntArray; outScanline: int; turned: boolean);
procedure scale3x(outp: PIntArray; outScanline: int; turned: boolean);
procedure scale4x(outp: PIntArray; outScanline: int; turned: boolean);
function getSourceWidth(): int;
function getSourceHeight(): int;
end;
{%endregion}
implementation
{%region Algorithm }
constructor Algorithm.create();
begin
inherited create();
square3x3 := int_Array1d_create(3 * 3);
end;
procedure Algorithm.setSource(pixels: PIntArray; width, height, scanline: int);
begin
self.pixels16bit := short_Array1d_create(width * height);
self.inp := pixels;
self.width := width;
self.height := height;
self.inScanline := scanline;
self.intermediate := nil;
end;
procedure Algorithm.scale2x(outp: PIntArray; outScanline: int; turned: boolean);
var
pixels: short_Array1d;
width: int;
height: int;
pixCurrLine: int;
pixPrevLine: int;
pixNextLine: int;
outCurrLine: int;
outNextLine: int;
outIndex: int;
i: int;
j: int;
p: int_Array1d;
begin
pixels := self.pixels16bit;
width := self.width;
height := self.height;
transformTo16bit(self.inp, width, height, self.inScanline, pixels);
p := square3x3;
pixCurrLine := 0;
outCurrLine := 0;
if turned then begin
outCurrLine := outScanline * (height * 2 - 1);
outScanline := -outScanline;
end;
for j := 0 to height - 1 do begin
if j > 0 then begin
pixPrevLine := pixCurrLine - width;
end else begin
pixPrevLine := pixCurrLine;
end;
if j < height - 1 then begin
pixNextLine := pixCurrLine + width;
end else begin
pixNextLine := pixCurrLine;
end;
outNextLine := outCurrLine + outScanline;
outIndex := 0;
for i := 0 to width - 1 do begin
p[1] := pixels[pixPrevLine + i];
p[4] := pixels[pixCurrLine + i];
p[7] := pixels[pixNextLine + i];
if i > 0 then begin
{p[0] := pixels[pixPrevLine + i - 1];}
p[3] := pixels[pixCurrLine + i - 1];
{p[6] := pixels[pixNextLine + i - 1];}
end else begin
{p[0] := p[1];}
p[3] := p[4];
{p[6] := p[7];}
end;
if i < width - 1 then begin
{p[2] := pixels[pixPrevLine + i + 1];}
p[5] := pixels[pixCurrLine + i + 1];
{p[8] := pixels[pixNextLine + i + 1];}
end else begin
{p[2] := p[1];}
p[5] := p[4];
{p[8] := p[7];}
end;
{
p:
+---+---+---+
| 0 | 1 | 2 |
+---+---+---+
| 3 | 4 | 5 |
+---+---+---+
| 6 | 7 | 8 |
+---+---+---+
}
{ Собственно сам алгоритм }
if (p[1] = p[3]) and (p[7] <> p[3]) and (p[1] <> p[5]) then begin
outp[outCurrLine + outIndex] := transformTo32bit(p[1]);
end else begin
outp[outCurrLine + outIndex] := transformTo32bit(p[4]);
end;
if (p[1] = p[5]) and (p[1] <> p[3]) and (p[7] <> p[5]) then begin
outp[outCurrLine + outIndex + 1] := transformTo32bit(p[5]);
end else begin
outp[outCurrLine + outIndex + 1] := transformTo32bit(p[4]);
end;
if (p[5] = p[7]) and (p[1] <> p[5]) and (p[3] <> p[7]) then begin
outp[outNextLine + outIndex + 1] := transformTo32bit(p[7]);
end else begin
outp[outNextLine + outIndex + 1] := transformTo32bit(p[4]);
end;
if (p[3] = p[7]) and (p[5] <> p[7]) and (p[3] <> p[1]) then begin
outp[outNextLine + outIndex] := transformTo32bit(p[3]);
end else begin
outp[outNextLine + outIndex] := transformTo32bit(p[4]);
end;
{ Конец алгоритма }
inc(outIndex, 2);
end;
inc(pixCurrLine, width);
inc(outCurrLine, outScanline * 2);
end;
end;
procedure Algorithm.scale3x(outp: PIntArray; outScanline: int; turned: boolean);
var
pixels: short_Array1d;
width: int;
height: int;
pixCurrLine: int;
pixPrevLine: int;
pixNextLine: int;
outCurrLine: int;
outNext1Line: int;
outNext2Line: int;
outIndex: int;
i: int;
j: int;
p: int_Array1d;
begin
pixels := self.pixels16bit;
width := self.width;
height := self.height;
transformTo16bit(self.inp, width, height, self.inScanline, pixels);
p := square3x3;
pixCurrLine := 0;
outCurrLine := 0;
if turned then begin
outCurrLine := outScanline * (height * 3 - 1);
outScanline := -outScanline;
end;
for j := 0 to height - 1 do begin
if j > 0 then begin
pixPrevLine := pixCurrLine - width;
end else begin
pixPrevLine := pixCurrLine;
end;
if j < height - 1 then begin
pixNextLine := pixCurrLine + width;
end else begin
pixNextLine := pixCurrLine;
end;
outNext1Line := outCurrLine + outScanline;
outNext2Line := outNext1Line + outScanline;
outIndex := 0;
for i := 0 to width - 1 do begin
p[1] := pixels[pixPrevLine + i];
p[4] := pixels[pixCurrLine + i];
p[7] := pixels[pixNextLine + i];
if i > 0 then begin
p[0] := pixels[pixPrevLine + i - 1];
p[3] := pixels[pixCurrLine + i - 1];
p[6] := pixels[pixNextLine + i - 1];
end else begin
p[0] := p[1];
p[3] := p[4];
p[6] := p[7];
end;
if i < width - 1 then begin
p[2] := pixels[pixPrevLine + i + 1];
p[5] := pixels[pixCurrLine + i + 1];
p[8] := pixels[pixNextLine + i + 1];
end else begin
p[2] := p[1];
p[5] := p[4];
p[8] := p[7];
end;
{
p:
+---+---+---+
| 0 | 1 | 2 |
+---+---+---+
| 3 | 4 | 5 |
+---+---+---+
| 6 | 7 | 8 |
+---+---+---+
}
{ Собственно сам алгоритм }
if (p[1] = p[3]) and (p[3] <> p[7]) and (p[1] <> p[5]) then begin
outp[outCurrLine + outIndex] := transformTo32bit(p[3]);
end else begin
outp[outCurrLine + outIndex] := transformTo32bit(p[4]);
end;
if ((p[1] = p[3]) and (p[3] <> p[7]) and (p[1] <> p[5]) and (p[4] <> p[2])) or ((p[1] = p[5]) and (p[1] <> p[3]) and (p[5] <> p[7]) and (p[4] <> p[0])) then begin
outp[outCurrLine + outIndex + 1] := transformTo32bit(p[1]);
end else begin
outp[outCurrLine + outIndex + 1] := transformTo32bit(p[4]);
end;
if (p[1] = p[5]) and (p[3] <> p[1]) and (p[7] <> p[5]) then begin
outp[outCurrLine + outIndex + 2] := transformTo32bit(p[5]);
end else begin
outp[outCurrLine + outIndex + 2] := transformTo32bit(p[4]);
end;
if ((p[7] = p[3]) and (p[5] <> p[7]) and (p[1] <> p[3]) and (p[4] <> p[0])) or ((p[1] = p[3]) and (p[7] <> p[3]) and (p[5] <> p[1]) and (p[4] <> p[6])) then begin
outp[outNext1Line + outIndex] := transformTo32bit(p[3]);
end else begin
outp[outNext1Line + outIndex] := transformTo32bit(p[4]);
end;
outp[outNext1Line + outIndex + 1] := transformTo32bit(p[4]);
if ((p[1] = p[5]) and (p[1] <> p[3]) and (p[5] <> p[7]) and (p[4] <> p[8])) or ((p[5] = p[7]) and (p[5] <> p[1]) and (p[3] <> p[7]) and (p[4] <> p[2])) then begin
outp[outNext1Line + outIndex + 2] := transformTo32bit(p[5]);
end else begin
outp[outNext1Line + outIndex + 2] := transformTo32bit(p[4]);
end;
if (p[3] = p[7]) and (p[7] <> p[5]) and (p[1] <> p[3]) then begin
outp[outNext2Line + outIndex] := transformTo32bit(p[3]);
end else begin
outp[outNext2Line + outIndex] := transformTo32bit(p[4]);
end;
if ((p[5] = p[7]) and (p[1] <> p[5]) and (p[3] <> p[7]) and (p[4] <> p[6])) or ((p[3] = p[7]) and (p[5] <> p[7]) and (p[1] <> p[3]) and (p[4] <> p[8])) then begin
outp[outNext2Line + outIndex + 1] := transformTo32bit(p[7]);
end else begin
outp[outNext2Line + outIndex + 1] := transformTo32bit(p[4]);
end;
if (p[7] = p[5]) and (p[1] <> p[5]) and (p[7] <> p[3]) then begin
outp[outNext2Line + outIndex + 2] := transformTo32bit(p[5]);
end else begin
outp[outNext2Line + outIndex + 2] := transformTo32bit(p[4]);
end;
{ Конец алгоритма }
inc(outIndex, 3);
end;
inc(pixCurrLine, width);
inc(outCurrLine, outScanline * 3);
end;
end;
procedure Algorithm.scale4x(outp: PIntArray; outScanline: int; turned: boolean);
var
pixels: short_Array1d;
inter: short_Array1d;
width: int;
height: int;
pixCurrLine: int;
pixPrevLine: int;
pixNextLine: int;
outCurrLine: int;
outNextLine: int;
outIndex: int;
i: int;
j: int;
p: int_Array1d;
begin
pixels := self.pixels16bit;
inter := self.intermediate;
width := self.width;
height := self.height;
if inter = nil then begin
inter := short_Array1d_create(4 * width * height);
self.intermediate := inter;
end;
transformTo16bit(self.inp, width, height, self.inScanline, pixels);
p := square3x3;
pixCurrLine := 0;
outCurrLine := 0;
for j := 0 to height - 1 do begin
if j > 0 then begin
pixPrevLine := pixCurrLine - width;
end else begin
pixPrevLine := pixCurrLine;
end;
if j < height - 1 then begin
pixNextLine := pixCurrLine + width;
end else begin
pixNextLine := pixCurrLine;
end;
outNextLine := outCurrLine + width * 2;
outIndex := 0;
for i := 0 to width - 1 do begin
p[1] := pixels[pixPrevLine + i];
p[4] := pixels[pixCurrLine + i];
p[7] := pixels[pixNextLine + i];
if i > 0 then begin
{p[0] := pixels[pixPrevLine + i - 1];}
p[3] := pixels[pixCurrLine + i - 1];
{p[6] := pixels[pixNextLine + i - 1];}
end else begin
{p[0] := p[1];}
p[3] := p[4];
{p[6] := p[7];}
end;
if i < width - 1 then begin
{p[2] := pixels[pixPrevLine + i + 1];}
p[5] := pixels[pixCurrLine + i + 1];
{p[8] := pixels[pixNextLine + i + 1];}
end else begin
{p[2] := p[1];}
p[5] := p[4];
{p[8] := p[7];}
end;
{
p:
+---+---+---+
| 0 | 1 | 2 |
+---+---+---+
| 3 | 4 | 5 |
+---+---+---+
| 6 | 7 | 8 |
+---+---+---+
}
{ Собственно сам алгоритм }
if (p[1] = p[3]) and (p[7] <> p[3]) and (p[1] <> p[5]) then begin
inter[outCurrLine + outIndex] := p[1];
end else begin
inter[outCurrLine + outIndex] := p[4];
end;
if (p[1] = p[5]) and (p[1] <> p[3]) and (p[7] <> p[5]) then begin
inter[outCurrLine + outIndex + 1] := p[5];
end else begin
inter[outCurrLine + outIndex + 1] := p[4];
end;
if (p[5] = p[7]) and (p[1] <> p[5]) and (p[3] <> p[7]) then begin
inter[outNextLine + outIndex + 1] := p[7];
end else begin
inter[outNextLine + outIndex + 1] := p[4];
end;
if (p[3] = p[7]) and (p[5] <> p[7]) and (p[3] <> p[1]) then begin
inter[outNextLine + outIndex] := p[3];
end else begin
inter[outNextLine + outIndex] := p[4];
end;
{ Конец алгоритма }
inc(outIndex, 2);
end;
inc(pixCurrLine, width);
inc(outCurrLine, width * 4);
end;
width := width shl 1;
height := height shl 1;
pixCurrLine := 0;
outCurrLine := 0;
if turned then begin
outCurrLine := outScanline * (height * 2 - 1);
outScanline := -outScanline;
end;
for j := 0 to height - 1 do begin
if j > 0 then begin
pixPrevLine := pixCurrLine - width;
end else begin
pixPrevLine := pixCurrLine;
end;
if j < height - 1 then begin
pixNextLine := pixCurrLine + width;
end else begin
pixNextLine := pixCurrLine;
end;
outNextLine := outCurrLine + outScanline;
outIndex := 0;
for i := 0 to width - 1 do begin
p[1] := inter[pixPrevLine + i];
p[4] := inter[pixCurrLine + i];
p[7] := inter[pixNextLine + i];
if i > 0 then begin
{p[0] := inter[pixPrevLine + i - 1];}
p[3] := inter[pixCurrLine + i - 1];
{p[6] := inter[pixNextLine + i - 1];}
end else begin
{p[0] := p[1];}
p[3] := p[4];
{p[6] := p[7];}
end;
if i < width - 1 then begin
{p[2] := inter[pixPrevLine + i + 1];}
p[5] := inter[pixCurrLine + i + 1];
{p[8] := inter[pixNextLine + i + 1];}
end else begin
{p[2] := p[1];}
p[5] := p[4];
{p[8] := p[7];}
end;
{
p:
+---+---+---+
| 0 | 1 | 2 |
+---+---+---+
| 3 | 4 | 5 |
+---+---+---+
| 6 | 7 | 8 |
+---+---+---+
}
{ Собственно сам алгоритм }
if (p[1] = p[3]) and (p[7] <> p[3]) and (p[1] <> p[5]) then begin
outp[outCurrLine + outIndex] := transformTo32bit(p[1]);
end else begin
outp[outCurrLine + outIndex] := transformTo32bit(p[4]);
end;
if (p[1] = p[5]) and (p[1] <> p[3]) and (p[7] <> p[5]) then begin
outp[outCurrLine + outIndex + 1] := transformTo32bit(p[5]);
end else begin
outp[outCurrLine + outIndex + 1] := transformTo32bit(p[4]);
end;
if (p[5] = p[7]) and (p[1] <> p[5]) and (p[3] <> p[7]) then begin
outp[outNextLine + outIndex + 1] := transformTo32bit(p[7]);
end else begin
outp[outNextLine + outIndex + 1] := transformTo32bit(p[4]);
end;
if (p[3] = p[7]) and (p[5] <> p[7]) and (p[3] <> p[1]) then begin
outp[outNextLine + outIndex] := transformTo32bit(p[3]);
end else begin
outp[outNextLine + outIndex] := transformTo32bit(p[4]);
end;
{ Конец алгоритма }
inc(outIndex, 2);
end;
inc(pixCurrLine, width);
inc(outCurrLine, outScanline * 2);
end;
end;
function Algorithm.getSourceWidth(): int;
begin
result := width;
end;
function Algorithm.getSourceHeight(): int;
begin
result := height;
end;
{%endregion}
end.