//============================================================ // <T>导出多个打包到目录。</T> // // @param fileName 文件名称 // @param widthCount 横向分割个数 // @param hightCount 纵向分割个数 //============================================================ public void ExportPath(string path, int tileWidth, int tileHight, int colorCount, int widthCount, int hightCount) { // 计算分割数量 int tileCx = _bitmap.Width / tileWidth; int tileCy = _bitmap.Height / tileHight; // 分割图片 for (int y = 0; y < tileCy; y++) { for (int x = 0; x < tileCx; x++) { // 绘制局部图形 FBitmap bitmap = new FBitmap(tileWidth, tileHight); bitmap.Fill(_bitmap, tileWidth * x, tileHight * y); // 存储索引图片 string fileName = path + "_" + RString.PadLeft(y.ToString(), 2, '0') + "_" + RString.PadLeft(x.ToString(), 2, '0') + "." + EXTEND_NAME; _logger.Debug(this, "ExportPath", "Export path file. (file_name={0}, color_count={1}, width_count={2}, hight_count={3})", fileName, colorCount, widthCount, hightCount); FLzmaFile file = new FLzmaFile(); file.EnsureSize(tileWidth * tileHight); StoreCompress(file, bitmap.Native, colorCount, widthCount, hightCount); file.Compress(fileName); file.Reset(); } } }
//============================================================ // <T>存储压缩文件。</T> // // @param fileName 文件名称 // @param widthCount 横向分割个数 // @param hightCount 纵向分割个数 //============================================================ public void StoreCompress(IOutput output, Bitmap bitmap, int colorCount, int widthCount, int hightCount) { // 输出图片尺寸 int width = bitmap.Width; int height = bitmap.Height; output.WriteUint16((ushort)width); output.WriteUint16((ushort)height); // 输出分割尺寸 int splitWidth = width / widthCount; int splitHeight = height / hightCount; int splitCount = widthCount * hightCount; output.WriteUint16((ushort)splitCount); // 分割图片 for (int y = 0; y < hightCount; y++) { for (int x = 0; x < widthCount; x++) { FByteStream bs = new FByteStream(); bs.WriteUint16((ushort)splitWidth); bs.WriteUint16((ushort)splitHeight); // 绘制局部图形 FBitmap image = new FBitmap(splitWidth, splitHeight); image.CopyFrom(bitmap, splitWidth * x, splitHeight * y); // 存储索引图片 StoreIndexedColor(bs, image.Native, colorCount, x, y); // 输出数据 output.WriteInt32(bs.Length); output.WriteBytes(bs.Memory, 0, bs.Length); } } }
//============================================================ // <T>合并压缩。</T> // // @autor DYWEN 20120712 //============================================================ public void tsbShowImage_Click(object sender, EventArgs e) { GetRectangle(); SIntPoint2 sintp2 = GetAllRectangle(maxW, maxH); Bitmap _bitmap = new Bitmap(sintp2.X, sintp2.Y); FRsResourceClip rcl = _resourceAnimation.FristClip; Graphics g = Graphics.FromImage(_bitmap); for (int i = 0; i < rcl.FrameCount; i++) { Bitmap bmn = rcl.Frames.Items[i].Bitmap.Native; _fCutBitmap = new FBitmap(bmn); SIntRectangle rct = _fCutBitmap.TestValidRectangle(1); Bitmap p = bmn.Clone(new Rectangle(rct.Left, rct.Top, rct.Width, rct.Height), PixelFormat.Format32bppArgb); // 防止图片缩放问题 g.DrawImage(p, i * maxW, 0, p.Width, p.Height); } QDsResourceViewForm sci = new QDsResourceViewForm(); foreach (Control item in sci.Controls) { if (item is PictureBox) { PictureBox picbox = item as PictureBox; picbox.Width = _bitmap.Width; picbox.Height = _bitmap.Height; picbox.BackgroundImage = _bitmap; } } String mapInfo = "宽:" + _bitmap.Width + " " + "高:" + _bitmap.Height; sci.Text = mapInfo; g.Dispose(); sci.Show(); }
UnsettedBlock[,] ConvertCPP(ref Image sourceImage, ArtType type) { stateLabel?.BeginInvoke(new Action(() => { stateLabel.Text = "Serialization"; })); UnsettedBlock[,] result = new UnsettedBlock[sourceImage.Width, sourceImage.Height]; int[] image1 = new int[sourceImage.Width * sourceImage.Height * 3]; int h = sourceImage.Height; int w = sourceImage.Width; using (FBitmap fbmp = new FBitmap((Bitmap)sourceImage, true)) for (int i = 0; i < h; ++i) { for (int j = 0; j < w; ++j) { Color pixel = fbmp.GetPixel(j, i); image1[i * w * 3 + j * 3 + 0] = pixel.R; image1[i * w * 3 + j * 3 + 1] = pixel.G; image1[i * w * 3 + j * 3 + 2] = pixel.B; } } List <int> notes1 = new List <int>(_colors.Count * 4); foreach (ColorNote col in _colors) { if (col.Use) { notes1.Add(col.ColorID); notes1.Add(col.LightColor.R); notes1.Add(col.LightColor.G); notes1.Add(col.LightColor.B); } } stateLabel?.BeginInvoke(new Action(() => { stateLabel.Text = "Converting"; })); fixed(int *image = image1) fixed(int *notes = notes1.ToArray()) { int *res = Convert(image, image1.Length, (int)type, Properties.Settings.Default.ConvertingMethod == 1, notes, notes1.Count, () => { progress.BeginInvoke(new Action(() => { progress?.Increment(1); })); }, (e) => { for (int j = 0; j < _colors.Count; ++j) { _colors[j].Uses = e[j]; } }); int i = 0; for (int x = 0; x < h; ++x) { for (int y = 0; y < w; ++y) { result[y, x].ID = res[i++]; result[y, x].Set = (ColorType)res[i++]; } } } return(result); }
public SettedBlock[,] CreateScheme(ref Image sourceImage, ArtType type, out int maxHeight) { UnsettedBlock[,] RawScheme = ConvertCPP(ref sourceImage, type); stateLabel?.BeginInvoke(new Action(() => { stateLabel.Text = "Making image"; })); Bitmap tempImage = new Bitmap(RawScheme.GetLength(0), RawScheme.GetLength(1)); int gl0 = RawScheme.GetLength(0); int gl1 = RawScheme.GetLength(1); using (FBitmap fbmp = new FBitmap(tempImage, false)) for (int i = 0; i < gl0; ++i) { for (int j = 0; j < gl1; ++j) { switch (RawScheme[i, j].Set) { case ColorType.Dark: fbmp.SetPixel(i, j, _colors[RawScheme[i, j].ID - 1].DarkColor); break; case ColorType.Normal: fbmp.SetPixel(i, j, _colors[RawScheme[i, j].ID - 1].NormalColor); break; case ColorType.Light: fbmp.SetPixel(i, j, _colors[RawScheme[i, j].ID - 1].LightColor); break; } } } sourceImage = tempImage; stateLabel?.BeginInvoke(new Action(() => { stateLabel.Text = "Generating"; })); SchemeGenerator gen = new SchemeGenerator(ref RawScheme); SettedBlock[,] result; switch (Properties.Settings.Default.GeneratingMethod) { case 0: result = gen.GenerateFlow(out maxHeight); break; case 1: result = gen.GenerateSegmented(out maxHeight); break; case 2: result = gen.GenerateMixed(out maxHeight); break; default: throw new Exception("Unknown generating method"); } stateLabel?.BeginInvoke(new Action(() => { stateLabel.Text = "Done"; })); Done(); return(result); }
//============================================================ // <T>打开数据内容。</T> //============================================================ public void Open() { if (null != _image) { _image.Dispose(); _image = null; } _image = new FBitmap(); _image.LoadFile(_fileName); _size.Set(_image.Width, _image.Height); _length = new FileInfo(_fileName).Length; }
//============================================================ // <T>序列化多层数据。</T> // // @param output 输出流 //============================================================ public override void Serialize(IOutput output) { // 输出属性 output.WriteInt32(CodeNumber); // 输出位图列表 output.WriteInt16((short)_bitmaps.Count); foreach (FDrTextureBitmap bitmap in _bitmaps) { using (FBitmap dataBitmap = new FBitmap(bitmap.Image.Native)) { dataBitmap.SerializeSimple(output); } } }
//============================================================ // <T>序列化数据。</T> //============================================================ public void Export() { // 加载高度图 _heightData.LoadFile(_path + "/texture/" + _textureHeight); _colorData.LoadFile(_path + "/texture/" + _textureColor); for (int n = 1; n <= _layerCount; n++) { FBitmap layerBitmap = _layers[n - 1].Bitmap; layerBitmap.LoadFile(_path + "/texture/level-" + n + ".jpg"); } //............................................................ FCompressFile file = new FCompressFile(); // 存储编号 file.WriteUint32((uint)_id); // 存储层数 file.WriteUint16((ushort)_layerCount); // 当前地图的宽度和高度 file.WriteUint16((ushort)_size.Width); file.WriteUint16((ushort)_size.Height); // 当前范围的宽度和高度 file.WriteUint16((ushort)_range.Width); file.WriteUint16((ushort)_range.Height); file.WriteFloat(_deep); // 存储材质列表 file.WriteInt16((short)_layers.Count); foreach (FDrMapLayer layer in _layers) { string materialCode = RDrUtil.FormatPathToCode(layer.MaterialName); file.WriteInt16((short)layer.Index); file.WriteString(materialCode); FDrMaterialGroup material = RContent3dManager.MaterialConsole.FindGroup(layer.MaterialName); material.Serialize(file); } // 输出文件 file.SaveFile(_exportFilePath + "\\config.swf"); //............................................................ // 导出地图块 int cx = _size.Width / _range.Width; int cy = _size.Height / _range.Height; for (int y = 0; y < cy; y++) { for (int x = 0; x < cx; x++) { ExportRange(x, y); } } // RangeIncise(); _logger.Debug(this, "Export", "Export template success. (file_name={0})", _exportFileName); }
//============================================================ // <T>获取有效区域</T> // // @autor DYWEN 20120816 //============================================================ public void GetRectangle() { FRsResourceClip rcl = _resourceAnimation.FristClip; for (int i = 0; i < rcl.FrameCount; i++) { Bitmap bmn = rcl.Frames.Items[i].Bitmap.Native; FBitmap fbitmap = new FBitmap(bmn); SIntRectangle rcthw = fbitmap.TestValidRectangle(1); int height = rcthw.Height; if (maxH < height) { maxH = height; } int width = rcthw.Width; if (maxW < width) { maxW = width; } } }
//============================================================ // <T>序列化动画数据。</T> // // @param output 输出流 //============================================================ public override void Serialize(IOutput output) { base.Serialize(output); // 写入属性 FRsResourceClip firstClip = FristClip; _size.Serialize16(output); _validBarycenter.Serialize16(output); _mergeSize.Serialize16(output); // 写入帧延迟 if (firstClip != null) { output.WriteUint16((ushort)firstClip.FrameCount); } else { output.WriteUint16((ushort)0); } if (firstClip != null) { firstClip.SerializeDelay(output); } // 写入剪辑集合 int clipCount = ClipCount; output.WriteUint8((byte)clipCount); foreach (FRsResourceClip clip in _clips) { if (clip != null) { clip.Serialize(output); } } // 序列化位图 using (FBitmap bitmap = new FBitmap(_mergeFileName)){ bitmap.SerializeData(output); } }
//============================================================ // <T>打开资源。</T> //============================================================ public void Open() { if (!_opened) { // 加载图片 _bitmap = new FBitmap(_fileName); _size.Width = _bitmap.Width; _size.Height = _bitmap.Height; // 获取有效范围 _bitmap.TestValidRectangle(_validRectangle, 8); // 计算有效重心 _validBarycenter.X = (_size.Width / 2) - _validRectangle.Left; _validBarycenter.Y = (_size.Height / 2) - _validRectangle.Top; if (!_validRectangle.IsEmpty) { Bitmap nativeBitmap = _bitmap.Native.Clone(new Rectangle(_validRectangle.Left, _validRectangle.Top, _validRectangle.Width, _validRectangle.Height), PixelFormat.Format32bppArgb); _validBitmap = new FBitmap(nativeBitmap); int width = _validRectangle.Width; int height = _validRectangle.Height; } _opened = true; } }
//============================================================ public void RangeIncise() { FCompressFile file = new FCompressFile(); int height = _size.Height; int width = _size.Width; for (int y = 0; y <= height; y++) { for (int x = 0; x <= width; x++) { //............................................................ // 计算坐标位置 int positionX = x; if (positionX >= _size.Width) { positionX = _size.Width - 1; } int positionY = y; if (positionY >= _size.Height) { positionY = _size.Height - 1; } int positionHeight = 2 * (_size.Width * positionY + positionX); float h = _heightData[positionHeight] + _heightData[positionHeight + 1] * 256; // 计算点高度(1, 0) SFloatVector3 tangent = new SFloatVector3(1, 0, 0); if (positionX < _size.Width - 1) { int tangentPosition = 2 * (_size.Width * positionY + (positionX) + 1); float h1 = _heightData[tangentPosition] + _heightData[tangentPosition + 1] * 256; float dx = (h1 - h) / 65535 * _deep; tangent.Set(1, dx, 0); } tangent.Normalize(); // 计算点高度(0, 1) SFloatVector3 binormal = new SFloatVector3(0, 0, 1); if (positionY < _size.Height - 1) { int binormalPosition = 2 * (_size.Width * (positionY + 1) + positionX); float h2 = _heightData[binormalPosition] + _heightData[binormalPosition + 1] * 256; float dy = (h2 - h) / 65535 * _deep; binormal.Set(0, dy, 1); } binormal.Normalize(); // 计算法线 SFloatVector3 normal = new SFloatVector3(); binormal.Cross(tangent, normal); normal.Normalize(); //............................................................ // 输出像素的高度 file.WriteUint8(_heightData[positionHeight]); file.WriteUint8(_heightData[positionHeight + 1]); // 输出像素的颜色 Color color = _colorData.Bitmap.GetPixel(positionX, positionY); file.WriteUint8(color.R); file.WriteUint8(color.G); file.WriteUint8(color.B); // 输出像素的法线 file.WriteUint8((byte)((normal.X + 1) * 0.5 * 255)); file.WriteUint8((byte)((normal.Y + 1) * 0.5 * 255)); file.WriteUint8((byte)((normal.Z + 1) * 0.5 * 255)); // 输出像素的层数据 for (int n = 0; n < _layerCount; n++) { FBitmap layerData = _layers[n].Bitmap; Color layerColor = layerData.Bitmap.GetPixel(positionX, positionY); file.WriteUint8(layerColor.R); } x += 8; } y += 8; } /*string rangeFile = "tile_" + RInt.Pad(x, 2) + "_" + RInt.Pad(cy, 2) + ".swf"; */ }
//============================================================ // <T>序列化数据。</T> //============================================================ public void ExportRange(int cx, int cy) { FCompressFile file = new FCompressFile(); // 存储编号 file.WriteUint32((uint)_id); // 存储层数 file.WriteUint16((ushort)_layerCount); // 当前地图的宽度和高度 file.WriteUint16((ushort)_size.Width); file.WriteUint16((ushort)_size.Height); // 当前范围的宽度和高度 file.WriteUint16((ushort)_range.Width); file.WriteUint16((ushort)_range.Height); file.WriteFloat(_deep); // 当前范围的位置坐标 file.WriteUint16((ushort)cx); file.WriteUint16((ushort)cy); // 计算开始坐标 int offsetX = _range.Width * cx; int offsetY = _range.Height * cy; // 输出数据 int width = _range.Width; int height = _range.Height; for (int y = 0; y <= height; y++) { for (int x = 0; x <= width; x++) { //............................................................ // 计算坐标位置 int positionX = offsetX + x; if (positionX >= _size.Width) { positionX = _size.Width - 1; } int positionY = _size.Height - (offsetY + y) - 1; if (positionY < 0) { positionY = 0; } else if (positionY >= _size.Height) { positionY = _size.Height - 1; } int positionHeight = 2 * (_size.Width * positionY + positionX); float h = _heightData[positionHeight] + _heightData[positionHeight + 1] * 256; // 计算点高度(1, 0) SFloatVector3 tangent = new SFloatVector3(1, 0, 0); if (positionX < _size.Width - 1) { int tangentPosition = 2 * (_size.Width * positionY + (positionX) + 1); float h1 = _heightData[tangentPosition] + _heightData[tangentPosition + 1] * 256; float dx = (h1 - h) / 65535 * _deep; tangent.Set(1, dx, 0); } tangent.Normalize(); // 计算点高度(0, 1) SFloatVector3 binormal = new SFloatVector3(0, 0, 1); if (positionY < _size.Height - 1) { int binormalPosition = 2 * (_size.Width * (positionY + 1) + positionX); float h2 = _heightData[binormalPosition] + _heightData[binormalPosition + 1] * 256; float dy = (h2 - h) / 65535 * _deep; binormal.Set(0, dy, 1); } binormal.Normalize(); // 计算法线 SFloatVector3 normal = new SFloatVector3(); binormal.Cross(tangent, normal); normal.Normalize(); //............................................................ // 输出像素的高度 file.WriteUint8(_heightData[positionHeight]); file.WriteUint8(_heightData[positionHeight + 1]); // 输出像素的颜色 Color color = _colorData.Bitmap.GetPixel(positionX, positionY); file.WriteUint8(color.R); file.WriteUint8(color.G); file.WriteUint8(color.B); // 输出像素的法线 file.WriteUint8((byte)((normal.X + 1) * 0.5 * 255)); file.WriteUint8((byte)((normal.Y + 1) * 0.5 * 255)); file.WriteUint8((byte)((normal.Z + 1) * 0.5 * 255)); // 输出像素的层数据 for (int n = 0; n < _layerCount; n++) { FBitmap layerData = _layers[n].Bitmap; Color layerColor = layerData.Bitmap.GetPixel(positionX, positionY); file.WriteUint8(layerColor.R); } } } // 输出文件 string rangeFile = "tile_" + RInt.Pad(cx, 2) + "_" + RInt.Pad(cy, 2) + ".swf"; file.SaveFile(_exportFilePath + "\\" + rangeFile); }
//============================================================ public void ChangeSize(int width, int height) { SuspendLayout(); // 是否自动缩放 if (_autoScale) { AutoScroll = false; float rx = (float)ClientSize.Width / (float)_clip.ValidRectangle.Width; float ry = (float)ClientSize.Height / (float)_clip.ValidRectangle.Height; _clipScale = Math.Min(Math.Min(rx, ry), 1.0f); width = (int)(_clip.ValidRectangle.Width * _clipScale); height = (int)(_clip.ValidRectangle.Height * _clipScale); } // 重置位置 if ((width <= ClientSize.Width) && (height <= ClientSize.Height)) { AutoScroll = false; pbxViewer.Left = ClientSize.Width / 2 - width / 2; pbxViewer.Top = ClientSize.Height / 2 - height / 2; } else { AutoScroll = true; if (width <= ClientSize.Width) { pbxViewer.Left = ClientSize.Width / 2 - width / 2; } else { pbxViewer.Left = 0; } if ((height <= ClientSize.Height)) { pbxViewer.Top = ClientSize.Height / 2 - height / 2; } else { pbxViewer.Top = 0; } } pbxViewer.Width = width; pbxViewer.Height = height; // 设置图片(仅在图形变大的情况下重新设置) if (null == _bitmap) { _bitmap = new FBitmap(width, height); } else { if ((width > _bitmap.Native.Width) || (height > _bitmap.Native.Height)) { _bitmap.Dispose(); _bitmap = new FBitmap(width, height); } } pbxViewer.Width = width; pbxViewer.Height = height; pbxViewer.Image = _bitmap.Native; ResumeLayout(); }
//============================================================ // <T>释放数据内容。</T> //============================================================ public virtual void Dispose() { _image.Dispose(); _image = null; }