This commit is contained in:
csh
2023-04-18 15:34:45 +08:00
parent df79a459dd
commit 77762ce275
9 changed files with 244 additions and 243 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
// Version 1.2.9
// Version 1.3.0
Function TOfficeObj(n);
Begin
+1 -1
View File
@@ -1,4 +1,4 @@
// Version 1.2.9
// Version 1.3.0
Type TSDocxFile = Class
///Version: V1.0 2022-09-20
+1 -1
View File
@@ -1,4 +1,4 @@
// Version 1.2.9
// Version 1.3.0
Type TSExcelFile = Class
///Version: V1.0 2022-08-08
+2
View File
@@ -176,6 +176,7 @@ public
if istable(r) then Begin
r := r[0];
node := node.FirstChildElement(r['name']);
if not ifObj(node) and r['nodeType'] = 'empty' then return false;
if not ifObj(node) then return nil;
if r['nodeType'] = 'pcdata' then //返回文本串
return node.GetText();
@@ -183,6 +184,7 @@ public
return node.Data();
key := r['attrName'] ? r['attrName'] : r['attrEx'] ? r['attrEx'] : 'val';
value := node.GetAttribute(key);
if r['nodeType'] = 'empty' and value = '' then return true;
return trystrtofloat(value, r) ? r : value;
End;
return nil;
+127 -196
View File
@@ -2,220 +2,151 @@ Type TSImage = Class
Function Create(stream); overload;
Begin
content_ := stream;
imageDef := array(('Png', 0, (0x89, 'P', 'N', 'G', 0x0d, 0x0a, 0x1a, 0x0a),'png'),
('Jfif',6,'JFIF','Jfif'),
('Exif',6,'Exif','Exif'),
('Gif',0,'GIF87a','gif'),
('Gif',0,'GIF89a','gif'),
('Tiff',0,('M','M',0x00,'*'),'tiff'),
('Tiff',0,('I', 'I', '*', 0x00),'tiff'),
('Bmp',0,'BM','bmp'));
ind := getImageDef(stream, imageDef);
if ind >= 0 then Begin
ExtFileName := imageDef[ind][3];
case imageDef[ind][0] of
'Gif':
[px_width, px_height, horz_dpi, vert_dpi] := gif_dimensions(stream);
'Bmp':
[px_width, px_height, horz_dpi, vert_dpi] := bmp_dimensions(stream);
'Tiff':
[px_width, px_height, horz_dpi, vert_dpi] := tiff_dimensions(stream, imageDef[ind][2]);
End;
End;
//println('width={},height={}',px_width, px_height);
end;
width_ := 0;
height_ := 0;
imagetypeDef := array(
('name': 'bmp', 'position': 0, 'value': array(0x42, 0x4d)),
('name': 'png', 'position': 0, 'value': array(0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A)),
('name': 'gif', 'position': 0, 'value': array(0x47, 0x49, 0x46, 0x38, 0x39, 0x61)),
('name': 'gif', 'position': 0, 'value': array(0x47, 0x49, 0x46, 0x38, 0x37, 0x61)),
('name': 'jpeg', 'position': 0, 'value': array(0xFF, 0xD8, 0xFF, 0xE1)),
('name': 'jpg', 'position': 0, 'value': array(0xFF, 0xD8)),
('name': 'tiff', 'position': 0, 'value': array(0x49, 0x49), 'order': 'littleEndian'),
('name': 'tiff', 'position': 0, 'value': array(0x4D, 0x4D), 'order': 'bigEndian'),
);
stringObj_ := new TMemoryStream();
size := length(stream);
stringObj_.Write(stream[0:size-1], size);
index := getImageType(imagetypeDef);
ExtFileName := imagetypeDef[index]['name'];
case ExtFileName of
'bmp':
[width_, height_] := bmp_dimensions();
'png':
[width_, height_] := png_dimensions();
'gif':
[width_, height_] := gif_dimensions();
'tiff':
[width_, height_] := tiff_dimensions(imagetypeDef[i]['order']);
'jpeg', 'jpg':
[width_, height_] := jpeg_dimensions();
end
//println("width_ = {}, height_ = {}", width_, height_);
End;
Function getImageType(def);
Begin
for i:=0 to length(def)-1 do
begin
value := def[i]['value'];
stringObj_.Seek(def[i]['position']);
for j:=0 to length(value)-1 do
begin
r := 0;
stringObj_.Read(r, 1);
if r <> value[j] then break;
if j = length(value)-1 then return i;
end
end
return -1;
End
Function Width();
Begin
return integer((px_width / horz_dpi) * 914400);
return width_;
End;
Function Height();
Begin
return integer((px_height / vert_dpi) * 914400);
return height_;
End;
(*
Function exif_dimensions(stream, r);
Property Content read readContent;
Function readContent();
Begin
start := 0;
code := nil;
while code <> 0xd9 do Begin
[code, off] := _exif_next(start);
case code of
0xe0:
Begin
segment_length := _read_int(stream, off, '', 2);
density_units := _read_int(stream, off + 9, '', 1);
horz_dpi := read_int(stream, off + 10, '', 2);
vert_dpi := read_int(stream, off + 12, '', 2);
End;
End;
start := off + segment_length;
End;
return content_;
End;
Function _exif_next(start);
Function jpeg_dimensions();
Begin
while 1 do Begin
position := _offset_of_next_ff_byte(start);
[position, byte_] = _next_non_ff_byte(position+1);
start := position + 1;
if byte_ = 0x00 then continue;
marker_code := byte_;
segment_offset := position + 1;
break;
End;
return array(marker_code, segment_offset);
des1 := 0xff;
des2 := 0xc0;
flag := 1;
while flag do
begin
stringObj_.Read(byte1, 1);
stringObj_.Read(byte2, 1);
if byte1 = des1 and byte2 = des2 then flag := 0;
end
if flag then return array(0, 0);
stringObj_.Read(tmp, 3);
height := readBigEndianByte(2);
width := readBigEndianByte(2);
return array(width, height);
End;
Function _offset_of_next_ff_byte(start);
Function tiff_dimensions(byteOrder);
Begin
for i:=start to length(content_)-1 do Begin
byte_ := ord(content_[i]);
if byte_ <> 0xff then return array(start - 1, byte_);
return array(start, 0);
stringObj_.seek(4);
if byteOrder = 'bigEndian' then
IFD := readBigEndianByte(4);
else stringObj_.Read(IFD, 4);
return array(0, 0);
End;
Function _next_non_ff_byte(start);
Function bmp_dimensions();
Begin
for i:=start to length(content_)-1 do Begin
byte_ := ord(content_[i]);
if byte_ = 0xff then return start - 1;
return start;
stringObj_.Seek(0x12);
width := 0;
stringObj_.Read(width, 4);
height := 0;
stringObj_.Read(height, 4);
//stringObj_.Seek(0x26);
//horz_px_per_meter := 0;
//stringObj_.Read(horz_px_per_meter, 4);
//vert_px_per_meter := 0;
//stringObj_.Read(vert_px_per_meter, 4);
//horz_dpi_ := _bmp_dpi(horz_px_per_meter);
//vert_dpi_ := _bmp_dpi(vert_px_per_meter);
return array(width, height);
End;
*)
Function tiff_dimensions(stream, r);
Function png_dimensions();
Begin
off := _read_int(stream, 4, r[0], 4);
count := _read_int(stream, off, r[0], 2);
m := array();
for i:=0 to count-1 do Begin
dir_entry_offset := off + 2 + i*12;
tag_code := _read_int(stream, dir_entry_offset, r[0], 2);
field_type := _read_int(stream, dir_entry_offset + 2, r[0], 2);
value_count := _read_int(stream, dir_entry_offset + 4, r[0], 4);
value_offset := _read_int(stream, dir_entry_offset + 8, r[0], 4);
case field_type of
2:
val := stream[value_offset:value_offset+value_count-1];
3:
if value_count=1 then
val := _read_int(stream, dir_entry_offset + 8, r[0], 2);
4:
if value_count=1 then
val := _read_int(stream, dir_entry_offset + 8, r[0], 4);
5:
if value_count=1 then Begin
numerator := _read_int(stream, value_offset, r[0], 4);
denominator := _read_int(stream, value_offset + 4, r[0], 4);
val := numerator / denominator;
End;
End;
println('off={}, tag={},type={},value_count={},value_off={},val={}',off, tag_code,field_type,value_count,value_offset,val);
m[tag_code] := val;
End;
px_width := m[256];
px_height := m[257];
horz_dpi := _tiff_dpi(282, m);
vert_dpi := _tiff_dpi(283, m);
return array(px_width, px_height, horz_dpi, vert_dpi);
stringObj_.Seek(0x10);
width := readBigEndianByte(4);
height := readBigEndianByte(4);
return array(width, height);
End;
Function _read_int(stream, off, t, size);
Function gif_dimensions();
Begin
stm := new TMemoryStream();
if t = 'M' then Begin
s := '';
setlength(s, 8);
for i:=0 to size-1 do Begin
s[i] := stream[off + size - i - 1];
End;
stm.Write(s, size);
End
else Begin
stm.Write(stream[off:off + 7], size);
End;
stm.Seek(0);
v := 0;
stm.Read(v, size);
return v;
stringObj_.Seek(0x6);
width := 0;
stringObj_.Read(width, 2);
height := 0;
stringObj_.Read(height, 2);
return array(width, height);
End;
Function bmp_dimensions(stream);
Function readBigEndianByte(num);
Begin
s := new TMemoryStream();
s.Write(stream[0:63], 64);
s.Seek(0x12);
px_width := 0;
s.Read(px_width, 4);
px_height := 0;
s.Read(px_height, 4);
s.Seek(0x26);
horz_px_per_meter := 0;
s.Read(horz_px_per_meter, 4);
vert_px_per_meter := 0;
s.Read(vert_px_per_meter, 4);
horz_dpi := _bmp_dpi(horz_px_per_meter);
vert_dpi := _bmp_dpi(vert_px_per_meter);
return array(px_width, px_height, horz_dpi, vert_dpi);
ret := 0;
while num do
begin
stringObj_.Read(b, 1);
ret := _Shl(ret, 8);
ret += b;
num --;
end
return ret;
End;
Function gif_dimensions(stream);
Begin
s := new TMemoryStream();
s.Write(stream[6:9], 4);
s.Seek(0);
px_width := 0;
s.Read(px_width, 2);
px_height := 0;
s.Read(px_height, 2);
return array(px_width, px_height, 72, 72);
End;
Function getImageDef(stream, imageDef);
Begin
for i:=0 to length(imageDef)-1 do Begin
off := imageDef[i][1];
len := length(imageDef[i][2]);
buf := stream[off:off+len-1];
if eq(buf, imageDef[i][2]) then Begin
return i;
End;
End;
return -1;
End;
Function eq(buf, r);
Begin
for i:=0 to length(buf)-1 do Begin
c := ifstring(r) ? r[i + 1] : r[i];
if ifint(c) then c := chr(c);
if c <> buf[i+1] then return 0;
End;
return 1;
End;
Function _tiff_dpi(tag, m);
Begin
if not ifint(m[tag]) then return 72;
v := ifint(m[296]) ? m[296] : 2;
if v = 1 then return 72;
units_per_inch := (v=2 ? 2.54 : 1);
dots_per_unit := m[tag];
return integer(round(dots_per_unit * units_per_inch));
End;
Function _bmp_dpi(px_per_meter);
Begin
if px_per_meter = 0 then return 96;
return integer(round(px_per_meter * 0.0254));
End;
Name;
content_;
px_width:integer;
px_height:integer;
horz_dpi:integer;
vert_dpi:integer;
ExtFileName:string;
End;
Name:string;
content_;
stringObj_;
width_:integer;
height_:integer;
End;
+12 -9
View File
@@ -15,14 +15,16 @@ Type xlsxImage = Class
return new xlsxImage(sheet, excel);
End;
Function SetSheetBackground(picture);
Function SetSheetBackground(pic);
Begin
if not ifBinary(picture.Image) or length(picture.Image) = 0 then
if not ifBinary(pic.Image) or length(pic.Image) = 0 then
return "Invalid Image Data.";
picture := new TSImage(pic.Image);
image_file := getImageFileName(picture);
rels_xmlfile := excel_.WorkBook().GetSheetRelsFile(sheetName_);
prefix := ReplaceStr(image_file, 'xl/', '../');
//println("image_file = {}", image_file);
[rid, target] := class(TSXml).FindRelationshipRid(rels_xmlfile, prefix);
if target = '' then
begin
@@ -30,7 +32,7 @@ Type xlsxImage = Class
class(TSXml).AddRelationshipRid(rels_xmlfile, prefix, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image', 'rId' $ rid);
end
content_xml := excel_.WorkBook().GetXmlFileObj(class(TSXml).GetFileName('Content_Types'));
class(TSXml).AddDefaultContentType(content_xml, 'jpeg', 'image/jpeg');
class(TSXml).AddDefaultContentType(content_xml, picture.ExtFileName, 'image/' $ picture.ExtFileName);
sheet_xml := excel_.WorkBook().GetSheetXmlfile(sheetName_);
node := sheet_xml.FirstChildElement('worksheet');
@@ -44,10 +46,11 @@ Type xlsxImage = Class
picture_node.SetAttribute('r:id', 'rId' + inttostr(rid));
End
Function AddPicture(topLeft, bottomRight, picture, format);
Function AddPicture(topLeft, bottomRight, pic, format);
Begin
if not ifBinary(picture.Image) or length(picture.Image) = 0 then
if not ifBinary(pic.Image) or length(pic.Image) = 0 then
return "Invalid Image Data.";
picture := new TSImage(pic.Image);
[err1, col1, row1] := excel_.CellNameToCoordinates(topLeft);
[err2, col2, row2] := excel_.CellNameToCoordinates(bottomRight);
if err1 or err2 then return 'Invalid params.';
@@ -62,7 +65,7 @@ Type xlsxImage = Class
class(TSXml).AddRelationshipRid(drawing_rels, image_target, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image', 'rId' $ rid);
end
content_xml := excel_.WorkBook().GetXmlFileObj(class(TSXml).GetFileName('Content_Types'));
class(TSXml).AddDefaultContentType(content_xml, 'jpeg', 'image/jpeg');
class(TSXml).AddDefaultContentType(content_xml, picture.ExtFileName, 'image/' $ picture.ExtFileName);
sheet_xml := excel_.WorkBook().GetSheetXmlfile(sheetName_);
node := sheet_xml.FirstChildElement('worksheet');
drawing_node := node.FirstChildElement('drawing');
@@ -149,7 +152,7 @@ private
image_file := '';
for i:=0 to length(image_files)-1 do
begin
if zipfile_.Diff(image_files[i], picture.Image) = 0 then
if zipfile_.Diff(image_files[i], picture.Content) = 0 then
begin
image_file := image_files[i];
break;
@@ -158,8 +161,8 @@ private
if image_file = '' then
begin
image_count := length(image_files) + 1;
image_file := 'xl/media/image' $ image_count $ '.jpeg';
zipfile_.Add(image_file, picture.Image);
image_file := 'xl/media/image' $ image_count $ '.' $ picture.ExtFileName;
zipfile_.Add(image_file, picture.Content);
end
return image_file;
End