summaryrefslogtreecommitdiff
path: root/src/corelib/fpg_imgfmt_png.pas
blob: c0659d2e98b9d40eb38130b0b4e269cee7aa3356 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
{
    fpGUI  -  Free Pascal GUI Toolkit

    Copyright (C) 2006 - 2012 See the file AUTHORS.txt, included in this
    distribution, for details of the copyright.

    See the file COPYING.modifiedLGPL, included in this distribution,
    for details about redistributing fpGUI.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

    Description:
      PNG image loading using the Free Pascal library: fcl-image
}

unit fpg_imgfmt_png;

{$mode objfpc}{$H+}

interface

uses
  SysUtils,
  Classes,
  fpg_base,
  fpg_main,
  FPImage,
  FPReadPNG;

function LoadImage_PNG(const AFileName: TfpgString): TfpgImage; overload;
function LoadImage_PNG(AStream: TStream): TfpgImage; overload;
function LoadImage_PNG(AInstance: THandle; const AResName: String; AResType: PChar): TfpgImage; overload;
function LoadImage_PNGcrop(const AMaxWidth, AMaxHeight: integer; const AFileName: TfpgString): TfpgImage;


implementation

uses
  fpg_utils;

function FPImageToFPG(ASource: TFPCustomImage): TfpgImage;
var
  i, j: integer;
  colorA: TFPColor;   // struct Red, Green, Blue, Alpha: word
  colorB: TfpgColor;  // ONE long 32-bit-word
  xlocal, ylocal: integer;
begin
  Result := nil;
  if ASource=nil then Exit;

  xlocal := ASource.Width;
  ylocal := ASource.Height;
  Result := TfpgImage.Create;
  Result.AllocateImage(32, xlocal, ylocal); // 32=colordepth
  for i := 0 to ylocal - 1 do
    for j := 0 to xlocal - 1 do
    begin
      colorA := ASource.Colors[j, i];
      colorB := (colorA.Blue shr 8) or (colorA.Green and $FF00) or ((colorA.Red and $FF) shl 16) or ((colorA.Alpha and $FF) shl 24);
      Result.Colors[j, i] := colorB;
    end;
  Result.UpdateImage;
end;

function LoadImage_PNG(const AFileName: TfpgString): TfpgImage;
var
  imga: TFPCustomImage;
begin
  Result := nil;
  if not fpgFileExists(AFileName) then
    Exit; //==>

  imga := TFPMemoryImage.Create(0, 0);
  try
    imga.LoadFromFile(AFileName, TFPReaderPNG.Create); // auto size image
  except
    imga := nil;
  end;
  if imga <> nil then
  begin
    Result := FPImageToFPG(imga);
    imga.Free;
  end;
end;

function LoadImage_PNG(AStream: TStream): TfpgImage;
var
  imga: TFPMemoryImage;
  reader: TFPReaderPNG;
begin
  Result := nil;
  if AStream = nil then
    Exit;

  imga := TFPMemoryImage.Create(0, 0);
  try
    try
      AStream.Position := 0;
      reader := TFPReaderPNG.Create;
      imga.LoadFromStream(AStream, reader); // auto size image
      Result := FPImageToFPG(imga);
    except
      on e: Exception do
      begin
        Result := nil;
        raise; // so we can report PNG errors (eg: missing resource name)
      end;
    end;
  finally
    reader.Free;
    imga.Free;
  end;
end;

function LoadImage_PNG(AInstance: THandle; const AResName: String; AResType: PChar): TfpgImage;
var
  res: TResourceStream;
begin
  try
    res := TResourceStream.Create(AInstance, AResName, AResType);
    Result := LoadImage_PNG(res);
  finally
    if res <> nil then
      res.Free;
  end;
end;

function LoadImage_PNGcrop(const AMaxWidth, AMaxHeight: integer; const AFileName: TfpgString): TfpgImage;
var
  i, j: integer;
  colorA: TFPColor;   // struct Red, Green, Blue, Alpha: word
  colorB: TfpgColor;  // ONE long 32-bit-word
  imga: TFPCustomImage;
  imgb: TfpgImage;
  xlocal, ylocal: integer;
begin
  Result := nil;
  if not fpgFileExists(AFileName) then
    Exit; //==>

          // Maximum image size of AMaxWidth by AMaxHeight.
          // Actual image imga.Width (AMaxWidth) and imga.Height (AMaxHeight).
          // Calculated to fit the image within required size: xlocal, ylocal
  imga := TFPMemoryImage.Create(0, 0);
  try
    imga.LoadFromFile(AFileName, TFPReaderPNG.Create); // auto size image
  except
    imga := nil;
    imgb := nil;
  end;
  if imga <> nil then
  begin
    if imga.Width > AMaxWidth then
      xlocal := AMaxWidth
    else
      xlocal := imga.Width;
    if imga.Height > AMaxHeight then
      ylocal := AMaxHeight
    else
      ylocal := imga.Height;
    imgb := TfpgImage.Create;
    imgb.AllocateImage(32, xlocal, ylocal); // 32=colordepth
    for i := 0 to ylocal - 1 do
      for j := 0 to xlocal - 1 do
      begin
        colorA := imga.Colors[j, i];
        colorB := (colorA.Blue shr 8) or (colorA.Green and $FF00) or ((colorA.Red and $FF00) shl 8);
        imgb.Colors[j, i] := colorB;
      end;
    imgb.UpdateImage;
  end;
  imga.Free;
  Result := imgb;
end;


end.