开发工具:lazarus
算法仍有问题。
unit unit_main;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
LCLType, LCLIntf, ExtCtrls, IntfGraphics, GraphType, ComCtrls, regexpr,
Math,BGRABitmap, BGRABitmapTypes, BCImageButton;
type
{ TFormMain }
TFormMain = class(TForm)
Button2: TButton;
ButtonBrowsePic: TButton;
Button4: TButton;
BtnCut: TButton;
Button6: TButton;
BtnPreview: TButton;
CombxSrcPic: TComboBox;
CombxMin: TComboBox;
CombxMax: TComboBox;
EditPmzbY: TEdit;
EditPmzbX: TEdit;
EditClipBoard: TEdit;
EditJD: TEdit;
EditWD: TEdit;
EditSrcPic: TEdit;
EditDstPath: TEdit;
GroupBox1: TGroupBox;
Image1: TImage;
Image2: TImage;
Image3: TImage;
Image0: TImage;
ImageAll: TImage;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
Label4: TLabel;
Label5: TLabel;
Label6: TLabel;
Label7: TLabel;
Label8: TLabel;
LabelLink: TLabel;
Memo1: TMemo;
MemoMap: TMemo;
OpenDialog1: TOpenDialog;
Panel1: TPanel;
pbar: TProgressBar;
rbPng: TRadioButton;
rbJpg: TRadioButton;
SDirDiog: TSelectDirectoryDialog;
procedure ButtonBrowsePicClick(Sender: TObject);
procedure Button4Click(Sender: TObject);
procedure BtnCutClick(Sender: TObject);
procedure Button6Click(Sender: TObject);
procedure BtnPreviewClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure LabelLinkClick(Sender: TObject);
private
{ private declarations }
//AImage: TLazIntfImage;
//lRawImage: TRawImage;
BGRABmpAll, BGRAImgText: TBGRABitmap;
procedure SaveToPng(bmp: TBitmap; PngFileName: String);
// 加载图片文件
procedure loadPic;
public
tukuaiCenterX, tukuaiCenterY: integer; // 中心图块坐标
procedure ShowForm(FormClass: TFormClass);
{ public declarations }
end;
var
FormMain: TFormMain;
implementation
uses unit_map, Unit_PicShow;
{$R *.lfm}
{ TFormMain }
procedure TFormMain.ShowForm(FormClass: TFormClass);
begin
with FormClass.Create(self) do
try
ShowModal;
finally
Free;
end;
end;
procedure TFormMain.SaveToPng(bmp: TBitmap; PngFileName: String);
var
png : TPortableNetworkGraphic;
begin
png := TPortableNetworkGraphic.Create;
try
png.Assign(bmp);
png.SaveToFile(PngFileName);
finally
png.Free;
end;
end;
// 加载图片文件
procedure TFormMain.loadPic;
var
BGRABmpPart, BGRAStretch: TBGRABitmap;
i,j: Integer;
fn,fnJpg,fnPng: string;
Rect:TRect;
begin
// 加载完整图片
BGRABmpAll := TBGRABitmap.Create(utf8ToSys(EditSrcPic.Text));
ImageAll.Picture.LoadFromFile((EditSrcPic.Text));
// 显示打开图片的宽度及高度
memo1.Lines.Add('图片宽度:' + intToStr(BGRABmpAll.Width) + '; 图片高度:' + intToStr(BGRABmpAll.Height));
// 完整预览选择的图片
BGRAStretch := BGRABmpAll.Resample(Panel1.Width, Panel1.Height) as TBGRABitmap;
// 显示左上角图片 ---------
//Rect.TopLeft:=Point(0,0);
//Rect.BottomRight:=Point(256, 256);
//BGRABmpAll.DrawPart(Rect, Image0.Canvas, 0, 0, true);
// 显示左上角图片 =========
//
BGRABmpPart := TBGRABitmap.Create(256, 256);
for i := 0 to 1 do
for j := 0 to 1 do
begin
Rect.TopLeft:=Point(256 * i, 256 * j);
Rect.BottomRight:=Point(256 * (i + 1), 256 * (j + 1));
//BGRABmpPart.FillRect(0, 0, 256, 256, BGRA(0,0,0,0), dmset);
BGRABmpAll.DrawPart(Rect, BGRABmpPart.Canvas, 0, 0, true);
if (i = 0) and (j = 0) then
begin
BGRABmpAll.DrawPart(Rect, Image0.Canvas, 0, 0, true);
memo1.Lines.Add('第1样张图片显示完毕,图片加黑边为正常。');
end;
fnPng := extractFilePath(paramStr(0)) + intToStr(i) + '_' + intToStr(j) + '.png';
BGRABmpPart.SaveToFile(fnPng);
memo1.Lines.Add('测试图片存储为:' + sysToUtf8(fnPng));
fnJpg := extractFilePath(paramStr(0)) + intToStr(i) + '_' + intToStr(j) + '.jpg';
BGRABmpPart.SaveToFile(fnJpg);
memo1.Lines.Add('测试图片存储为:' + sysToUtf8(fnJpg));
end;
memo1.Lines.Add('测试图片处理完毕。');
BGRABmpPart.Free;
BGRAStretch.Free;
end;
// 源图片定位按钮
procedure TFormMain.ButtonBrowsePicClick(Sender: TObject);
var
fn: string;
begin
memo1.Clear;
OpenDialog1.Filter:='jpeg文件|*.jpg|png文件|*.png';
if OpenDialog1.Execute then
EditSrcPic.Text := OpenDialog1.FileName;
fn := trim(EditSrcPic.Text);
if fn = '' then
exit;
loadPic;
BtnCut.Enabled := true;
BtnPreview.Enabled := true;
end;
// 目标路径
procedure TFormMain.Button4Click(Sender: TObject);
begin
if SDirDiog.Execute then
begin
EditDstPath.Text := SDirDiog.FileName;
end;
end;
// 开始切图按钮
procedure TFormMain.BtnCutClick(Sender: TObject);
var
iGradeMin, iGradeMax, iGradeDef, xiangsuX, xiangsuY: integer;
picSrc, destPath, destFn, f: string;
srcPicStrechW, srcPicStrechH, rectBotmRighX, rectBotmRighY, srcTileWidth,
tilCoordX, tilCoordY, iGradeCur, i, j, Vtimes, Htimes: integer;
strList: TStringList;
Rect:TRect;
BGRAStretch, BGRABmpPart: TBGRABitmap;
clrText: TBGRAPixel;
begin
memo1.Clear;
picSrc := trim(EditSrcPic.Text);
if picSrc = '' then
begin
showmessage('请定位待处理图片。');
exit;
end;
destPath := EditDstPath.Text;
if destPath = '' then
begin
showmessage('请定义输出路径');
exit;
end;
// 创建 tiles 目录 ----
destPath := trim(EditDstPath.Text) + '\tiles';
if not DirectoryExists(destPath) then
CreateDir(destPath);
// 创建 tiles 目录 ====
iGradeMin := strToInt(CombxMin.Text); // 最小级别
iGradeMax := strToInt(CombxMax.Text); // 最大级别
iGradeDef := strToInt(CombxSrcPic.Text); // 原图所在的级别
pbar.Min := 0;
//生成 map.html ------------------------------------
strList:= TStringList.Create;
strList.LoadFromFile(ExtractFilePath(ParamStr(0)) + '\t.html');
strList.Text := stringReplace(strList.Text, '#minZoom#', intToStr(iGradeMin), [rfReplaceAll]);
strList.Text := stringReplace(strList.Text, '#maxZoom#', intToStr(iGradeMax), [rfReplaceAll]);
strList.Text := stringReplace(strList.Text, '#center_x#', EditJD.Text, [rfReplaceAll]);
strList.Text := stringReplace(strList.Text, '#center_y#', EditWD.Text, [rfReplaceAll]);
strList.Text := stringReplace(strList.Text, '#defaultZoom#', intToStr(iGradeDef), [rfReplaceAll]);
f := trim(EditDstPath.Text) + '\map.html';
DeleteFile(f);
strList.SaveToFile(f);
strList.Free;
//生成 map.html ====================================
for iGradeCur := iGradeMin to iGradeMax do
//for l := 6 to 8 do
begin
// 计算中心像素坐标
// 像素坐标 = |平面坐标 × 2 iGradeCur - 18| (iGradeCur - 18是2的指数)
xiangsuX := trunc(abs(strToFloat(EditPmzbX.Text) * power(2, iGradeCur - 18)));
xiangsuY := trunc(abs(strToFloat(EditPmzbY.Text) * power(2, iGradeCur - 18)));
memo1.Lines.Add('---------------------------------------');
memo1.Lines.Add('处理级别:' + intToStr(iGradeCur));
memo1.Lines.Add('中心像素坐标:' + intToStr(xiangsuX) + '-' + intToStr(xiangsuY));
// 计算中心图块坐标
// 图块坐标 = |像素坐标 ÷ 256|
tukuaiCenterX := trunc(xiangsuX / 256);
tukuaiCenterY := trunc(xiangsuY / 256);
memo1.Lines.Add('中心图块坐标:' + intToStr(tukuaiCenterX) + '-' + intToStr(tukuaiCenterY));
// 生成当前级别目录
destPath := trim(EditDstPath.Text) + '\tiles\' + intToStr(iGradeCur);
if not DirectoryExists(destPath) then
CreateDir(destPath);
// widthSingle := 256 div iGradeCur * gradeDef; // 源图切割后,单个图片的边长
// srcPicStrechW := trunc(abs(BGRABmpAll.Width * power(2, iGradeDef - iGradeCur))); // 计算某级别下,变形后源图宽度
// srcPicStrechH := trunc(abs(BGRABmpAll.Height * power(2, iGradeDef - iGradeCur))); // 计算某级别下,变形后源图高度
//memo1.Lines.Add('变形w:' + intToStr(srcPicStrechW));
//memo1.Lines.Add('变形H:' + intToStr(srcPicStrechH));
srcTileWidth := trunc(abs(256 * power(2, iGradeDef - iGradeCur))); // 计算源瓦片宽度
memo1.Lines.Add('单个源瓦片宽度:' + intToStr(srcTileWidth));
if srcTileWidth <=0 then
begin
memo1.Lines.Add('瓦片宽度不可小于1。');
exit;
end;
// 创建宽度为 srcTileWidth 的 BGRABitmap,临时存储未变形的切片
// BGRABmpPart := TBGRABitmap.Create(srcTileWidth, srcTileWidth);
pbar.Max := iGradeCur - 1;
// 横向分割块数
if BGRABmpAll.Width mod srcTileWidth = 0 then
Htimes := BGRABmpAll.Width div srcTileWidth
else
Htimes := BGRABmpAll.Width div srcTileWidth + 1;
// 纵向分割块数
if BGRABmpAll.Height mod srcTileWidth = 0 then
Vtimes := BGRABmpAll.Height div srcTileWidth
else
Vtimes := BGRABmpAll.Height div srcTileWidth + 1;
memo1.Lines.Add('Htimes:' + intToStr(Htimes));
memo1.Lines.Add('Vtimes:' + intToStr(Vtimes));
for i := 1 to Htimes do // 横向循环
begin
pbar.Position:=i;
for j := 1 to Vtimes do // 纵向循环
begin
// 创建宽度为 srcTileWidth 的 BGRABitmap,复制BGRABmpPart后用于变形
BGRAStretch := TBGRABitmap.Create(srcTileWidth, srcTileWidth);
// 创建宽度为 srcTileWidth 的 BGRABitmap,临时存储未变形的切片
BGRABmpPart := TBGRABitmap.Create(srcTileWidth, srcTileWidth);
// 定义待复制的源瓦片 Rect 参数 ----------------
Rect.TopLeft:=Point(srcTileWidth * (i - 1), srcTileWidth * (j - 1));
// 右下角坐标,如果超出变形后原图大小,会出错
// Rect.BottomRight:=Point(srcTileWidth * i, srcTileWidth * j);
// srcPicStrechW rectBotmRighX, rectBotmRighY
//取得 rect 右下角横坐标位置
if srcTileWidth * i <= BGRABmpAll.Width then
rectBotmRighX := srcTileWidth * i
else
rectBotmRighX := BGRABmpAll.Width; // srcPicStrechW 变形后原图宽度
//取得 rect 右下角纵坐标位置
if srcTileWidth * j <= BGRABmpAll.Height then
rectBotmRighY := srcTileWidth * j
else
rectBotmRighY := BGRABmpAll.Height; // srcPicStrechW 变形后原图宽度
Rect.BottomRight:=Point(rectBotmRighX, rectBotmRighY);
// 定义待复制的源瓦片 Rect 参数 ================
// 切出指定位置、宽度为 srcTileWidth 的图形
BGRABmpAll.DrawPart(Rect, BGRABmpPart.Canvas, 0, 0, true);
// 变形为边长256的图形
BGRAStretch := BGRABmpPart.Resample(256, 256) as TBGRABitmap;
// BGRAStretch.TextOutAngle(100, 100, -450, 'Hello world',c,);
BGRAStretch.FontHeight := 50;
BGRAStretch.FontAntialias := true;
clrText := ColorToBGRA(ColorToRGB(clYellow)); // 字体颜色
BGRAStretch.TextOutAngle(0, 0, 0, intToStr(iGradeCur) + ':' + intToStr(i) + ',' + intToStr(j), clrText, taLeftJustify);
clrText := ColorToBGRA(ColorToRGB(clBtnText)); // 为产生阴影,换一种字体颜色
BGRAStretch.TextOutAngle(1, 1, 0, intToStr(iGradeCur) + ':' + intToStr(i) + ',' + intToStr(j), clrText, taLeftJustify);
//BGRAStretch.SetPixel(30,5, cText);
//destFn := destPath + '\tile' + intToStr(tukuaiCenterX + i - iGradeCur div 2) + '_' + intToStr(tukuaiCenterY - (j - iGradeCur div 2)) + '.jpg';
//destFn := destPath + '\tile' + intToStr(tukuaiCenterX - Htimes div 2 + i - 1) + '_' + intToStr(tukuaiCenterY + Vtimes div 2 - j) + '.jpg';
tilCoordX := tukuaiCenterX - Htimes div 2 + i - 1;
tilCoordY := tukuaiCenterY + (Vtimes + 1) div 2 - j;
BGRAStretch.FontHeight := 30;
clrText := ColorToBGRA(ColorToRGB(clYellow)); // 字体颜色
BGRAStretch.TextOutAngle(10, 160, 0, intToStr(tilCoordX) + ',' + intToStr(tilCoordY), clrText, taLeftJustify);
clrText := ColorToBGRA(ColorToRGB(clBtnText)); // 为产生阴影,换一种字体颜色
BGRAStretch.TextOutAngle(11, 161, 0, intToStr(tilCoordX) + ',' + intToStr(tilCoordY), clrText, taLeftJustify);
if (tilCoordX = tukuaiCenterX) and (tilCoordY = tukuaiCenterY) then // 中心图块
begin
BGRAStretch.FontHeight := 60;
clrText := ColorToBGRA(ColorToRGB(clWhite)); // 字体颜色
BGRAStretch.TextOutAngle(0, 10, 0, '中心图块', clrText, taLeftJustify);
clrText := ColorToBGRA(ColorToRGB(clBtnText)); // 为产生阴影,换一种字体颜色
BGRAStretch.TextOutAngle(1, 11, 0, '中心图块', clrText, taLeftJustify);
end;
destFn := destPath + '\tile' + intToStr(tilCoordX) + '_' + intToStr(tilCoordY) + '.jpg';
memo1.Lines.Add(destFn);
BGRAStretch.SaveToFile(destFn);
BGRAStretch.Free;
BGRABmpPart.Free;
end;
end;
// BGRABmpPart.Free;
pbar.Position:=0;
end;
memo1.Lines.Add('');
memo1.Lines.Add('切片完成。');
//bitA.Free;
//bitTile.Free;
end;
// 获取经纬度
procedure TFormMain.Button6Click(Sender: TObject);
var
s,jwd_x,jwd_y: string;
RegexObj: TRegExpr;
i, xiangsuX, xiangsuY,
iYutuJibie // 当前级别
: integer;
//xiangsuX, xiangsuY: float;
begin
memo1.Clear;
if trim(CombxSrcPic.Text) = '' then
begin
showmessage('请确定当前级别。');
exit;
end;
iYutuJibie := strToInt(CombxSrcPic.Text);
if (iYutuJibie > 18) or (iYutuJibie < 1) then
begin
showmessage('级别范围1——18.');
exit;
end;
memoMap.Lines.SaveToFile(ExtractFilePath(ParamStr(0)) + 'locamap');
FormMap.ShowModal;
// 从剪贴板获得经纬度 格式: jwd:116.716754,40.049897;pmzb:12992991,4845443.71
EditClipBoard.PasteFromClipboard;
s := EditClipBoard.Text;
memo1.Lines.Add('点击的经纬度、平面坐标');
memo1.Lines.Add(s);
memo1.Lines.Add('');
RegexObj := TRegExpr.Create;
RegexObj.Expression := '\d+\.*\d+';
RegexObj.ModifierI := true;
// 取得经度 纬度 平面横坐标 平面纵坐标
i := 0;
if RegexObj.Exec(s) then
repeat
if i = 0 then
EditJD.Text := RegexObj.Match[0] // 经度
else if i = 1 then
EditWD.Text := RegexObj.Match[0] // 纬度
else if i = 2 then
EditPmzbX.Text := RegexObj.Match[0] // 平面坐标 x
else if i = 3 then
EditPmzbY.Text := RegexObj.Match[0]; // 平面坐标 y
i := i + 1;
until not RegexObj.ExecNext;
RegexObj.Free;
// 计算中心像素坐标
// 像素坐标 = |平面坐标 × 2 iGradeCur - 18| (iGradeCur - 18是2的指数)
xiangsuX := trunc(abs(strToFloat(EditPmzbX.Text) * power(2, iYutuJibie - 18)));
xiangsuY := trunc(abs(strToFloat(EditPmzbY.Text) * power(2, iYutuJibie - 18)));
memo1.Lines.Add('中心像素坐标:' + intToStr(xiangsuX) + '-' + intToStr(xiangsuY));
// 计算图块坐标
// 图块坐标 = |像素坐标 ÷ 256|
tukuaiCenterX := trunc(xiangsuX / 256);
tukuaiCenterY := trunc(xiangsuY / 256);
memo1.Lines.Add('中心图块坐标:' + intToStr(tukuaiCenterX) + '-' + intToStr(tukuaiCenterY));
end;
procedure TFormMain.BtnPreviewClick(Sender: TObject);
begin
FormPicShow.ShowModal;
end;
procedure TFormMain.FormCreate(Sender: TObject);
begin
LabelLink.Font.Style:= [fsUnderline];
LabelLink.Cursor:= crHandPoint;
EditSrcPic.Text := sysToUtf8(ExtractFilePath(paramStr(0)) + 'map.jpg');
//loadPic;
end;
procedure TFormMain.FormDestroy(Sender: TObject);
begin
BGRABmpAll.Free;
end;
procedure TFormMain.LabelLinkClick(Sender: TObject);
begin
OpenURL('http://api.map.baidu.com/lbsapi/getpoint/index.html');
end;
end.