位图切割器&位图裁剪器
位图切割器:
虽然网上有类似的工具,PhotoShop 也有类似功能,但前者似乎不支持超大位图切割(以 G 计大小),而后者的切割块数量好像有比较小的限定范围,于是自己动手写了这个工具。
至于为什么是“位图”切割器,原因只是我实在不想费力去解析譬如 JPG、PNG、TGA 等图像格式,而大家都知道解析 BMP 文件比较简单。
核心处理代码很简单,无外乎 ReadFile、SetFilePointer 等之类 API 调用而已。
function HandleSplit(const FileName, DstPath, ImgName: string; UnitW, UnitH: Integer): Boolean; var Handle : Integer; FileHeader : TBitmapFileHeader; BmpInfoHeader: TBitmapInfoHeader; Offset : Integer;
VOffset : Integer; Mem, DstMem : TMemoryStream; LineLen : Integer; PerBits : Integer; I, J, W, H : Integer; X, Y : string; procedure ReadAreaImgData(L, T, W, H: Integer; Dst: PByte); var N : Integer; Len: Integer; begin Len := W * PerBits; for N := VOffset + T to VOffset + T + H - 1 do begin FileSeek(Handle, Offset + LineLen * N + L * PerBits, 0); FileRead(Handle, Dst^, Len); Inc(Dst, Len); end; end; begin Result := False; Handle := FileOpen(FileName, fmOpenRead or fmShareDenyWrite); if Handle < 0 then Exit; try if FileRead(Handle, FileHeader, SizeOf(FileHeader)) <> SizeOf(FileHeader) then Exit; if FileHeader.bfType <> $4D42 then Exit; if FileRead(Handle, BmpInfoHeader, SizeOf(BmpInfoHeader)) <> SizeOf(BmpInfoHeader) then Exit; case BmpInfoHeader.biBitCount of 16: begin PerBits := 2; end; 24: begin PerBits := 3; end; 32: begin PerBits := 4; end else Exit; end; Offset := SizeOf(FileHeader) + SizeOf(BmpInfoHeader);
VOffset := BmpInfoHeader.biHeight - BmpInfoHeader.biHeight div UnitH * UnitH; LineLen := (BmpInfoHeader.biWidth * PerBits + 3) div 4 * 4; Mem := TMemoryStream.Create; DstMem := TMemoryStream.Create; W := BmpInfoHeader.biWidth div UnitW; H := BmpInfoHeader.biHeight div UnitH; for J := 0 to H - 1 do begin for I := 0 to W - 1 do begin X := Format('%.3d', [I]); Y := Format('%.3d', [H - 1 - J]); Mem.Clear; Mem.SetSize(UnitW * PerBits * UnitH); Mem.Position := 0; ReadAreaImgData(I * UnitW, J * UnitH, UnitW, UnitH, Mem.Memory); DstMem.Clear; DstMem.Write(FileHeader, SizeOf(FileHeader)); BmpInfoHeader.biWidth := UnitW; BmpInfoHeader.biHeight := UnitH; BmpInfoHeader.biSizeImage := 0; DstMem.Write(BmpInfoHeader, SizeOf(BmpInfoHeader)); DstMem.Write(Mem.Memory^, Mem.Size); DstMem.SaveToFile(ImgName + '_' + Y + '_' + X + '.bmp'); end; end; FreeAndNil(Mem); FreeAndNil(DstMem); Result := True; finally FileClose(Handle); end; end;
工具下载链接在这里。
位图裁剪器:写这个程序的初衷是因找不到方便的图片截取工具,尤其是在需要精确裁剪较大的图片时——这里的“较大”,和上文的切割器不一样,它不大可能能裁剪以 G 计大小的位图——这个工具写得较早些,当时没考虑支持超大图片,现在也没意愿去改进了。
此工具的下载链接在这里。