我有一个奇怪的问题,我认为我无法解决它。 我有一个包含图层的ImgView(透明的png图像),我打算将所有图层保存为png文件(比如“保存项目”),以便稍后我可以重新打开它们并将它们放在我离开它们的位置。 (就像“开放项目”的事情) 这是我的问题,按照以下步骤正常工作:
如果我执行以下后续步骤,则会出现问题:
现在它只给我上面的错误,但是几个运行之前,它指出了这一行:
procedure TCustomBitmap32.ResetAlpha(const AlphaValue: Byte);
var
I: Integer;
P: PByteArray;
begin
if not FMeasuringMode then <<<<<------ this line
所以,如果我改变图层的索引...我不能再将它们保存为PNG了?!?!?!
这是我的保存程序:
for i:=0 to mainForm.ImgView.Layers.Count-2 do
begin
mylay := TBitmapLayer(mainForm.ImgView.Layers.Items[i]);
SaveBMPAsPng(mylay.Bitmap,'C:\MyApp\tmp\'+getLayerPan(i)+'.png');
end;
// where getLayerPan is a function that retrieves a name that I gave to the layer
...和
procedure SaveBmpAsPng(bmp:TBitmap32;dest:string);
var
Y: Integer;
X: Integer;
Png: TPortableNetworkGraphic32;
function IsWhite(Color32: TColor32): Boolean;
begin
Result:= (TColor32Entry(Color32).B = 255) and
(TColor32Entry(Color32).G = 255) and
(TColor32Entry(Color32).R = 255);
end;
begin
bmp.ResetAlpha;
for Y := 0 to bmp.Height-1 do
for X := 0 to bmp.Width-1 do
begin
if IsWhite(bmp.Pixel[X, Y]) then
bmp.Pixel[X,Y]:=Color32(255,255,255,0);
end;
Png:= TPortableNetworkGraphic32.Create;
Png.Assign(bmp);
Png.SaveToFile(dest);
Png.Free;
end;
可能有什么不对? 请帮忙......
修改 我想我发现了我的问题...... 当我移动图层时,唯一的方法(我知道)清理它是将所有图层加载到图像列表中(此时我选择TBitmap32List)然后清理图层并重新添加它们图像列表以我们想要的顺序到我的ImageView。 我只能假设这是出错的地方。 一定是因为在图层中我有透明的PNG,当我将它们加载到Bitmap32List中时,我将它们加载为BMP。 在继续之前,我必须寻找另一种重组我的图层的方法。我会用我的解决方案更新你。如果您有任何人知道在ImageView32中重新排序图层的更好方法,请告诉我。
修改
因此,请在下图中观察GUI已完成并正常工作。我有面板代表层,我可以移动它们(正如你在图像中看到的那样,我拖动图层'Elementul 0'并在链中移动它)。 我再说一遍,当我使用临时文件在订单中向上或向下移动图层时,我的逻辑也有效。其中一个答案表明我应该使用Index属性来更改图层层次结构中的图层位置,我说如果不至少在图像中添加新图层就无法完成。所以这不是一个双重问题。这只是对我收到的答案之一的回应。
谢谢
答案 0 :(得分:2)
你的问题比你想象的要简单得多。使用图层很自然:
发送回
将图层索引设置为0或只需调用SendToBack
。 之前的所有图层的索引都会增加1.之前的所有图层都会保持在同一位置。
向后发送
将图层的索引减少1. 之前的图层现在将在它之后,因此其索引增加了一个。
发送
将图层的索引增加1. 之前的图层现在将在它之前,因此其索引减少了一个。
发送到前面
将图层的索引设置为图层数减1. 之前的图层增加的图层减少了一个。
因此,绝对不需要触摸位图,将其保存到磁盘,或使用任何类型的临时图层来更改顺序。几乎在每种情况下,只要将图层的索引设置为您希望它出现的位置(从0开始,从前到后计数),就会发生正确的事情。在列表中移动面板后,您可以将相应图层的索引设置为列表中面板的新索引。但是,由于面板是从前到后排序的,而GR32是从前面开始订购的,因此您需要将面板的索引转换为所需的图层索引。
以下是如何使用TListBox
和TButton
执行此操作的示例:
procedure TForm1.SendBackwardButtonClick(Sender: TObject);
var
LNewListBoxItemIndex: Integer;
begin
// Calculate the new list index and make sure it's valid
LNewListBoxItemIndex := Max(0, Min(ListBox1.ItemIndex + 1, ListBox1.Items.Count - 1));
// Transform the current and new list indices and use them to move the layer
ImgView321.Layers[ListBox1.Items.Count - 1 - ListBox1.ItemIndex].Index :=
ListBox1.Items.Count - 1 - LNewListBoxItemIndex;
// Move the list item
ListBox1.Items.Move(ListBox1.ItemIndex, LNewListBoxItemIndex);
// Preserve the selection (if applicable)
ListBox1.ItemIndex := LNewListBoxItemIndex;
end;
您也可以决定将列表与图层完全同步。在这种情况下,您应该将每个项目(可能是TPanel
)与图层相关联。
// Create layers from front to back
LLayer := TBitmapLayer.Create(ImgView321.Layers);
ListBox1.Items.AddObject('First layer', LLayer);
// Could use LPanel := TPanel.Create(...); LPanel.Tag := Integer(Pointer(LLayer)) instead
LLayer := TBitmapLayer.Create(ImgView321.Layers);
ListBox1.Items.AddObject('Second layer', LLayer);
// Now the list is correct but the layers are not in the right order.
// Use the code listed below whenever you need to synchronize the layers
// with the list. In theory it may be slow (O(n^2)) but practically it
// won't matter much assuming you won't have hundreds of layers.
// Don't update the screen every time we move a layer to get closer to the final result
ImgView321.BeginUpdate;
try
for LIndex := 0 to ListBox1.Items.Count - 1 do
// Get the associated layer and make it the least visible of all processed so far
TCustomLayer(ListBox1.Items.Objects[LIndex]).SendToBack;
// Could use TCustomLayer(Pointer(SomePanel.Tag)).SendToBack instead
finally
// Always do this not to have strange behavior after an error
ImgView321.EndUpdate;
end;
// When it's done, update the screen
ImgView321.Changed;
答案 1 :(得分:1)
根据您对如何更改图层顺序的描述,这很可能是您遇到问题的原因。由于您没有发布该部分代码,因此无法确定地进行评估。
无论如何,要重新排列图层,您可以使用Index
TCustomLayer
的{{1}}属性(其中TBitmapLayer
是后代)
答案 2 :(得分:0)
因此问题的解决方案是在重新排序图层时不使用Bitmap32List作为png图层的临时容器,因为在此过程中会丢失某些内容。 所以尝试其他解决方案进行重新排序。我的解决方案是将图层作为PNG文件放到磁盘上,然后按所需顺序从磁盘重新加载它们。 另一个解决方案(尚未测试)将创建一些新层,等于现有层的数量,在那里移动实际层,然后按所需顺序逐个返回,然后删除多余的层。
反正。这就是问题,到目前为止这是答案