//============================================================ // <T>检测指定位图是否含有某个通道数据。<T> // // @param bitmap 位图 // @param rectangle 矩形范围 // @param channels 通道 // @param value 通道 //============================================================ public static bool HasChannel(Bitmap bitmap, SIntRectangle rectangle, int channel, int value = 255) { // 取得图片的宽度 int width = rectangle.Width; int height = rectangle.Height; int size = width * 4; // 内存锁定 BitmapData data = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); long dataPtr = data.Scan0.ToInt64(); // 存储数组 byte[] buffer = new byte[size]; for (int row = 0; row < height; row++) { // 读取源信息 Marshal.Copy(new IntPtr(dataPtr), buffer, 0, size); for (int n = 0; n < size; n += 4) { if (buffer[n + channel] != value) { bitmap.UnlockBits(data); return(true); } } dataPtr += data.Stride; } bitmap.UnlockBits(data); return(false); }
//============================================================ // <T>指定复制位图的指定通道到目标位图。<T> // // @param source 来源位图 // @param sourceRectangle 来源矩形 // @param target 目标位图 // @param targetPosition 目标位置 //============================================================ public static void Copy(Bitmap source, SIntRectangle sourceRectangle, Bitmap target, SIntPoint2 targetPosition) { int lineSize = sourceRectangle.Width; int height = sourceRectangle.Height; int[] buffer = new int[lineSize]; // 获得来源内存 BitmapData sourceData = source.LockBits(new Rectangle(sourceRectangle.Left, sourceRectangle.Top, sourceRectangle.Width, sourceRectangle.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); long sourcePtr = sourceData.Scan0.ToInt64(); // 获得目标内存 BitmapData targetData = target.LockBits(new Rectangle(targetPosition.X, targetPosition.Y, sourceRectangle.Width, sourceRectangle.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); long targetPtr = targetData.Scan0.ToInt64(); // 复制数据 for (int row = 0; row < height; row++) { // 读取源信息 Marshal.Copy(new IntPtr(sourcePtr), buffer, 0, lineSize); sourcePtr += sourceData.Stride; // 读取目标源信息 Marshal.Copy(buffer, 0, new IntPtr(targetPtr), lineSize); targetPtr += targetData.Stride; } // 释放资源 source.UnlockBits(sourceData); target.UnlockBits(targetData); }
//============================================================ // <T>序列化位图数据。</T> // // @params output 输出流 // @params colorCount 调色板颜色数量 // @params pixelCount 分块的像素个数 //============================================================ public bool SerializeIndexed3d(IOutput output, SIntRectangle rect, int colorCount) { // 写入设置 output.WriteUint8(_optionAlpha ? (byte)1 : (byte)0); // 写入属性 output.WriteUint16((ushort)Width); output.WriteUint16((ushort)Height); output.WriteUint16((ushort)rect.Left); output.WriteUint16((ushort)rect.Top); output.WriteUint16((ushort)rect.Width); output.WriteUint16((ushort)rect.Height); // 若不支持半透明,去掉一个颜色,添加一个透明色 if (!_optionAlpha) { colorCount--; } // 写入头信息 FPictureQuantizer pictureQuantizer = null; IColorQuantizer colorQuantizer = null; if (_optionAlpha) { pictureQuantizer = new FPictureQuantizer(EColorQuantizer.Octree); colorQuantizer = pictureQuantizer.LoadQuantizerColors(_native, rect, FPictureQuantizer.EQuantizedMode.Rgb); } else { pictureQuantizer = new FPictureQuantizer(EColorQuantizer.Octree16); colorQuantizer = pictureQuantizer.LoadQuantizerColors(_native, rect, FPictureQuantizer.EQuantizedMode.Color); } SerializeUnpackBlock3d(output, colorQuantizer, rect, colorCount); return(true); }
//============================================================ // <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(); }
//============================================================ // <T>测试有效范围区域。</T> // // @param alpha 透明度 // @return 有效范围区域 //============================================================ public SIntRectangle TestValidRectangle(int alpha) { SIntRectangle rect = new SIntRectangle(); TestValidRectangle(rect, alpha); return(rect); }
//============================================================ // <T>指定复制位图的指定通道到目标位图。<T> // // @param source 来源位图 // @param target 目标位图 // @param rectangle 矩形范围 // @param channels 通道集合 //============================================================ public static void CopyChannels(Bitmap source, Bitmap target, SIntRectangle rectangle, int channels) { // 获得通道 bool channelsA = (EBitmapChannels.A == (channels & EBitmapChannels.A)); bool channelsR = (EBitmapChannels.R == (channels & EBitmapChannels.R)); bool channelsG = (EBitmapChannels.G == (channels & EBitmapChannels.G)); bool channelsB = (EBitmapChannels.B == (channels & EBitmapChannels.B)); // 取得图片的宽度 int width = rectangle.Width; int height = rectangle.Height; int size = width << 2; // 获得来源内存 BitmapData sourceData = source.LockBits(new Rectangle(rectangle.Left, rectangle.Top, width, height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); long sourcePtr = sourceData.Scan0.ToInt64(); byte[] sourceBuffer = new byte[size]; // 获得目标内存 BitmapData targetData = target.LockBits(new Rectangle(rectangle.Left, rectangle.Top, width, height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); long targetPtr = targetData.Scan0.ToInt64(); byte[] targetBuffer = new byte[size]; // 复制数据 for (int row = 0; row < height; row++) { // 读取源信息 Marshal.Copy(new IntPtr(sourcePtr), sourceBuffer, 0, size); sourcePtr += sourceData.Stride; // 读取目标源信息 Marshal.Copy(new IntPtr(targetPtr), targetBuffer, 0, size); // 复制通道数据 for (int n = 0; n < size; n += 4) { if (channelsB) { targetBuffer[n + 0] = sourceBuffer[n + 0]; } if (channelsG) { targetBuffer[n + 1] = sourceBuffer[n + 1]; } if (channelsR) { targetBuffer[n + 2] = sourceBuffer[n + 2]; } if (channelsA) { targetBuffer[n + 3] = sourceBuffer[n + 3]; } } Marshal.Copy(targetBuffer, 0, new IntPtr(targetPtr), size); targetPtr += targetData.Stride; } // 释放资源 source.UnlockBits(sourceData); target.UnlockBits(targetData); }
//============================================================ // <T>更新属性。</T> //============================================================ public void Update() { // 测试有效区域 SIntRectangle rect = new SIntRectangle(); RBitmap.TestValidRectangle(_bitmap, rect, _validAlpha); // 设置属性 _size.Set(_bitmap.Width, _bitmap.Height); _validLocation.Set(rect.Left, rect.Top); _validSize.Set(rect.Width, rect.Height); }
//============================================================ // <T>构造位图。</T> // // @param bitmap 位图 //============================================================ public FRsBitmap(Bitmap bitmap, SIntRectangle rectangle) { // 设置有效区域 _validLocation.X = rectangle.Left; _validLocation.Y = rectangle.Top; _validSize.Width = rectangle.Width; _validSize.Height = rectangle.Height; // 设置属性 _bitmap = bitmap; // 更新属性 Update(); }
/// ============================================================ /// <summary>加载图形的优化器颜色。</summary> /// <param name="bitmap">图形对象</param> /// <param name="modeCd">颜色模式</param> /// <returns>颜色优化器</returns> /// ============================================================ public IColorQuantizer LoadQuantizerColors(Bitmap bitmap, SIntRectangle rect, EQuantizedMode modeCd) { // 检查参数错误 if (null == bitmap) { throw new ArgumentNullException("Cannot quantize a null bitmap."); } // 锁定原图像,获得所有颜色 int width = rect.Width; int height = rect.Height; Rectangle bounds = new Rectangle(rect.Left, rect.Top, width, height); BitmapData data = bitmap.LockBits(bounds, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); try { // 读取所有颜色 int[] buffer = new int[width]; long offset = data.Scan0.ToInt64(); for (int row = 0; row < height; row++) { // 复制一行颜色到缓冲中 Marshal.Copy(new IntPtr(offset), buffer, 0, width); // 增加到优化器中 for (int n = 0; n < width; n++) { uint color = (uint)buffer[n]; switch (modeCd) { case EQuantizedMode.Color: break; case EQuantizedMode.Rgb: color |= 0xFF000000; break; case EQuantizedMode.Alpha: color &= 0xFF000000; break; default: throw new FFatalException("Unknown type"); } _quantizer.AddColor(Color.FromArgb((int)color)); } // 修正行边界 offset += data.Stride; } } finally { // 释放图像对象 bitmap.UnlockBits(data); } return(_quantizer); }
//============================================================ // <T>打开资源。</T> //============================================================ public void Open() { if (!_opened) { // 打开所有帧 foreach (FRsResourceFrame frame in _frames) { frame.Open(); } // 获得最小左 上点和最大右下点 int left = int.MaxValue; int top = int.MaxValue; int right = 0; int bottom = 0; foreach (FRsResourceFrame frame in _frames) { SIntRectangle rect = frame.ValidRectangle; if (!rect.IsEmpty) { if (rect.Left < left) { left = rect.Left; } if (rect.Top < top) { top = rect.Top; } if (rect.Right > right) { right = rect.Right; } if (rect.Bottom > bottom) { bottom = rect.Bottom; } } } _validRectangle.Set(left, top, right - left, bottom - top); // 获得剪辑重心 _validBarycenter.X = _frames[0].Bitmap.Width / 2 - left; _validBarycenter.Y = _frames[0].Bitmap.Height / 2 - top; _opened = true; } }
//============================================================ // <T>自动调整处理。</T> //============================================================ public virtual void OnAdjust() { // 计算背景图片关联的大小 //if(_groundResource.HasBitmap()) { // _size.Set(_groundResource.Size.Width, _groundResource.Size.Height); // _size.Width += _groundResource.Location.X; // _size.Height += _groundResource.Location.Y; //} // 计算容器大小 SIntRectangle rectangle = CalculateRange(); if (rectangle.Width > ControlResource.Size.Width) { ControlResource.Size.Width = rectangle.Width; } if (rectangle.Height > ControlResource.Size.Height) { ControlResource.Size.Height = rectangle.Height; } }
//============================================================ // <T>绘制资源。</T> // // @param resource 资源 // @param rectangle 范围 //============================================================ public void DrawResource(FUiPicture resource, SIntRectangle rectangle) { if (resource.HasBitmap()) { // 获得坐标 float scale = _context.Scale; int x = resource.Location.X; int y = resource.Location.Y; // 绘制资源 FDxContext2d context = _context.Context; if (resource.AlignCd == ERcPictureAlign.Square) { context.DrawBitmapPadding(resource.bitmap, rectangle, x, y, ControlResource.Size.Width, ControlResource.Size.Height, resource.Padding, scale); } else { SIntSize2 size = resource.bitmap.Size; context.DrawBitmap(resource.bitmap, rectangle, x, y, size.Width, size.Height, scale); } } }
//============================================================ // <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> // // @params output 输出流 // @params colorCount 调色板颜色数量 // @params pixelCount 分块的像素个数 //============================================================ public bool Compress(IOutput output, int compressCd, SIntRectangle rect, int colorCount) { // 保存数据 using (FByteStream stream = new FByteStream()) { Serialize(stream, rect, colorCount); // 压缩数据 byte[] data = null; if (compressCd == ERsCompress.NoneValue) { data = stream.ToArray(); } else if (compressCd == ERsCompress.DeflateValue) { //using(FRsCompressFile compress = new FRsCompressFile(ERsCompress.Deflate, stream, RResourceManager.CompressBlockSplit)) { using (FCompressFile compress = new FCompressFile(stream)) { data = compress.Compress(); } if (data.Length > stream.Length) { compressCd = ERsCompress.NoneValue; data = stream.ToArray(); } } else if (compressCd == ERsCompress.LzmaValue) { using (FLzmaFile compress = new FLzmaFile(stream)) { data = compress.CompressNative(); } if (data.Length > stream.Length) { compressCd = ERsCompress.NoneValue; data = stream.ToArray(); } } output.WriteInt32(compressCd); output.WriteInt32(data.Length); output.WriteBytes(data, 0, data.Length); } return(true); }
//============================================================ // <T>清除位图为指定颜色。<T> // // @param bitmap 位图 // @param rectangle 矩形范围 // @param value 颜色 //============================================================ public static void Clear(Bitmap bitmap, SIntRectangle rectangle, int value = -1) { // 取得图片的宽度 int width = rectangle.Width; int height = rectangle.Height; // 内存锁定 BitmapData data = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); long dataPtr = data.Scan0.ToInt64(); // 存储数组 int[] buffer = new int[width]; for (int n = 0; n < width; n++) { buffer[n] = value; } for (int row = 0; row < height; row++) { // 读取源信息 Marshal.Copy(buffer, 0, new IntPtr(dataPtr), width); dataPtr += data.Stride; } bitmap.UnlockBits(data); }
//============================================================ // <T>获得图片一部分字节。<T> // // @param bitmap 位图 // @param rectangle 矩形范围 // @param value 颜色 //============================================================ public static byte[] ToBytes(Bitmap bitmap, SIntRectangle rectangle = null) { // 取得矩形范围 Rectangle rect; if (null != rectangle) { rect = new Rectangle(rectangle.Left, rectangle.Top, rectangle.Width, rectangle.Height); } else { rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height); } int width = rect.Width; int height = rect.Height; int size = width * height * 4; byte[] data = new byte[size]; // 内存锁定 BitmapData bitmapData = bitmap.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); long dataPtr = bitmapData.Scan0.ToInt64(); // 存储数组 int stride = width * 4; byte[] buffer = new byte[stride]; for (int row = 0; row < height; row++) { // 读取源信息 Marshal.Copy(new IntPtr(dataPtr), buffer, 0, stride); Array.Copy(buffer, 0, data, width * row * 4, stride); dataPtr += bitmapData.Stride; } bitmap.UnlockBits(bitmapData); // 返回数据 return(data); }
//============================================================ // <T>序列化位图数据。</T> // // @params output 输出流 // @params colorCount 调色板颜色数量 // @params pixelCount 分块的像素个数 //============================================================ public bool Serialize(IOutput output, SIntRectangle rect, int colorCount) { // 写入设置 output.WriteBool(_optionAlpha); // 写入属性 output.WriteUint16((ushort)_size.Width); output.WriteUint16((ushort)_size.Height); output.WriteUint16((ushort)rect.Left); output.WriteUint16((ushort)rect.Top); output.WriteUint16((ushort)rect.Width); output.WriteUint16((ushort)rect.Height); // 若不支持半透明,去掉一个颜色,添加一个透明色 //if (!_optionAlpha) { // colorCount--; //} // 写入头信息 FPictureQuantizer pictureQuantizer = null; IColorQuantizer colorQuantizer = null; if (_optionAlpha) { pictureQuantizer = new FPictureQuantizer(EColorQuantizer.Octree); colorQuantizer = pictureQuantizer.LoadQuantizerColors(_bitmap, rect, FPictureQuantizer.EQuantizedMode.Rgb); } else { pictureQuantizer = new FPictureQuantizer(EColorQuantizer.Octree16); colorQuantizer = pictureQuantizer.LoadQuantizerColors(_bitmap, rect, FPictureQuantizer.EQuantizedMode.Color); } using (FByteStream stream = new FByteStream()) { SerializeUnpack(stream, colorQuantizer, rect, colorCount); output.WriteInt32(stream.Length); output.WriteBytes(stream.Memory, 0, stream.Length); } return(true); }
//============================================================ // <T>绘制边界位图。</T> // // @param bitmap 位图 // @param bitmapRectangle 位图范围 // @param x 横坐标 // @param y 纵坐标 // @param width 宽度 // @param height 高度 // @param padding 空格 //============================================================ public void DrawBitmapPadding(FDxBitmap bitmap, SIntRectangle bitmapRectangle, int x, int y, int width, int height, SIntPadding padding, float scale = 1.0f) { // 计算缩放 int paddingLeft = padding.Left; int paddingTop = padding.Top; int paddingRight = padding.Right; int paddingBottom = padding.Bottom; width -= x; height -= y; if (scale != 1.0f) { x = (int)(x * scale); y = (int)(y * scale); width = (int)(width * scale); height = (int)(height * scale); paddingLeft = (int)(paddingLeft * scale); paddingTop = (int)(paddingTop * scale); paddingRight = (int)(paddingRight * scale); paddingBottom = (int)(paddingBottom * scale); } // 绘制对象 int[] sxs = null; int[] sys = null; if (bitmapRectangle != null) { sxs = new int[4] { bitmapRectangle.Left, bitmapRectangle.Left + paddingLeft, bitmapRectangle.Right - paddingRight, bitmapRectangle.Right }; sys = new int[4] { bitmapRectangle.Top, bitmapRectangle.Top + paddingTop, bitmapRectangle.Bottom - paddingBottom, bitmapRectangle.Bottom }; } else { sxs = new int[4] { 0, paddingLeft, bitmap.Size.Width - paddingRight, bitmap.Size.Width }; sys = new int[4] { 0, paddingTop, bitmap.Size.Height - paddingBottom, bitmap.Size.Height }; } int[] dxs = new int[4] { 0, paddingLeft, width - paddingRight, width }; int[] dys = new int[4] { 0, paddingTop, height - paddingBottom, height }; for (int ny = 0; ny < 3; ny++) { for (int nx = 0; nx < 3; nx++) { int n = 3 * ny + nx; // 计算来源信息 int sx = sxs[nx]; int sw = sxs[nx + 1] - sx; if (sw <= 0) { continue; } int sy = sys[ny]; int sh = sys[ny + 1] - sy; if (sh <= 0) { continue; } // 计算目标信息 int dx = dxs[nx]; int dw = dxs[nx + 1] - dx; if (dw <= 0) { continue; } int dy = dys[ny]; int dh = dys[ny + 1] - dy; if (dh <= 0) { continue; } // 绘制图片 _target.DrawBitmap(bitmap.Native, new Rectangle(x + dx, y + dy, dw, dh), 1.0f, InterpolationMode.Linear, new Rectangle(sx, sy, sw, sh)); } } }
//============================================================ // <T>绘制位图。</T> // // @param bitmap 位图 // @param bitmapRectangle 位图范围 // @param x 横坐标 // @param y 纵坐标 // @param width 横坐标 // @param height 纵坐标 // @param scale 缩放 //============================================================ public void DrawBitmap(FDxBitmap bitmap, SIntRectangle bitmapRectangle, int x, int y, int width, int height, float scale = 1.0f) { _target.DrawBitmap(bitmap.Native, new Rectangle((int)(x * scale), (int)(y * scale), (int)(width * scale), (int)(height * scale)), 1.0f, InterpolationMode.NearestNeighbor, new Rectangle(bitmapRectangle.Left, bitmapRectangle.Top, bitmapRectangle.Width, bitmapRectangle.Height)); }
//============================================================ // <T>绘制边框。</T> // // @param border 边框描述 //============================================================ public void DrawBorder(SIntRectangle rectangle, FRcBorder border) { }
//============================================================ // <T>序列化位图的一个区块。</T> // // @params output 输出流 // @params colorQuantizer 颜色优化器 // @params rect 序列化的矩形区域 // @params colorCount 颜色数量 //============================================================ protected bool SerializeBlock(IOutput output, IColorQuantizer colorQuantizer, SIntRectangle rect, int colorCount) { int blockWidth = rect.Width; int blockHeight = rect.Height; output.WriteUint16((ushort)blockWidth); output.WriteUint16((ushort)blockHeight); // 构造调色板 Color[] palette = null; if (_optionAlpha) { palette = colorQuantizer.MakePalette(colorCount).ToArray(); if (0 == palette.Length) { RMoCore.TrackConsole.Write(this, "SerializeBlock", "Palette color is empty."); return(false); } } else { List <Color> colorList = colorQuantizer.MakePalette(colorCount); if (0 == colorList.Count) { RMoCore.TrackConsole.Write(this, "SerializeBlock", "Palette color is empty."); return(false); } colorList.Add(Color.Transparent); palette = colorList.ToArray(); } // 输出调色板 int paletteCount = palette.Length; output.WriteUint16((ushort)paletteCount); foreach (Color color in palette) { if (_optionAlpha) { output.WriteInt32(color.ToArgb() & 0x00FFFFFF); } else { output.WriteInt32(color.ToArgb()); } } // _logger.Debug(this, "SerializeIndexed", "block_size={0}x{1}, color={2}, alpha={3}", blockWidth, blockHeight, paletteCount, _optionAlpha); // 输出颜色数组 int x = rect.Left; int y = rect.Top; // 透明色索引 int transparentIndex = palette.Length - 1; int size = blockWidth * blockHeight; // 写入数组 int postion = 0; byte[] bytes = null; if (_optionAlpha) { // 写入索引颜色和透明度 bytes = new byte[size * 2]; for (int h = 0; h < blockHeight; h++) { for (int w = 0; w < blockWidth; w++) { Color color = _native.GetPixel(x + w, y + h); int index = colorQuantizer.FindPaletteIndex(Color.FromArgb(255, color)); bytes[postion++] = (byte)index; bytes[postion++] = color.A; } } } else { // 写入带透明的索引颜色 bytes = new byte[size]; for (int h = 0; h < blockHeight; h++) { for (int w = 0; w < blockWidth; w++) { Color color = _native.GetPixel(x + w, y + h); int index = colorQuantizer.FindPaletteIndex(color); bytes[postion++] = (byte)index; } } } output.WriteBytes(bytes, 0, postion); return(true); }
//============================================================ // <T>序列化位图数据。</T> // // @params output 输出流 // @params colorCount 调色板颜色数量 // @params pixelCount 分块的像素个数 //============================================================ public bool SerializeUnpackIndexed(IOutput output, int colorCount, int pixelCount) { // 若不支持半透明,去掉一个颜色,添加一个透明色 SIntRectangle rect = new SIntRectangle(); rect.Left = 0; rect.Top = 0; rect.Width = _native.Width; rect.Height = _native.Height; // 计算分割信息 int width = rect.Width; int height = rect.Height; int totalPixel = width * height; int splitWidth = width; int splitCount = totalPixel / pixelCount; int splitHeight = height; if (0 == splitCount) { splitHeight = height; splitCount = 1; } else { splitHeight = height / splitCount; splitCount = height / splitHeight; if (0 != (height % splitHeight)) { splitCount++; } } // 写入头信息 ushort option = 0; if (_optionAlpha) { option |= (ushort)EBitmapOption.Alpha; } output.WriteUint16(option); output.WriteUint16((ushort)width); output.WriteUint16((ushort)height); output.WriteUint16((ushort)splitCount); // 要序列化的源矩形区域 SIntRectangle subrect = new SIntRectangle(); subrect.Left = rect.Left; subrect.Top = rect.Top; subrect.Width = splitWidth; subrect.Height = splitHeight; // 源矩形数据 FByteStream bs = new FByteStream(); for (int n = 0; n < splitCount; n++) { bs.Clear(); subrect.Bottom = Math.Min(subrect.Top + splitHeight, rect.Top + height); // 创建图片优化器 FPictureQuantizer pictureQuantizer = null; IColorQuantizer colorQuantizer = null; if (_optionAlpha) { pictureQuantizer = new FPictureQuantizer(EColorQuantizer.Octree); colorQuantizer = pictureQuantizer.LoadQuantizerColors(_native, subrect, FPictureQuantizer.EQuantizedMode.Rgb); } else { pictureQuantizer = new FPictureQuantizer(EColorQuantizer.Octree16); colorQuantizer = pictureQuantizer.LoadQuantizerColors(_native, subrect, FPictureQuantizer.EQuantizedMode.Color); } // 存储图片优化数据 if (SerializeUnpackBlock(bs, colorQuantizer, subrect, colorCount)) { output.WriteUint32((uint)bs.Length); output.WriteBytes(bs.Memory, 0, bs.Length); // _logger.Debug(this, "SerializeIndexed", "index={0}/{1}, rect={2}, size={3}", n, splitCount, rect.ToString(), bs.Length); subrect.Top += splitHeight; } else { RMoCore.TrackConsole.Write(this, "SerializeIndexed", "Picture is all transparent."); return(false); } } return(true); }
//============================================================ // <T>序列化位图的一个区块。</T> // // @params output 输出流 // @params colorQuantizer 颜色优化器 // @params rect 序列化的矩形区域 // @params colorCount 颜色数量 //============================================================ protected bool SerializeUnpackBlock(IOutput output, IColorQuantizer colorQuantizer, SIntRectangle rect, int colorCount) { int blockWidth = rect.Width; int blockHeight = rect.Height; output.WriteUint16((ushort)blockWidth); output.WriteUint16((ushort)blockHeight); // 构造调色板 Color[] palette = null; if (_optionAlpha) { palette = colorQuantizer.MakePalette(colorCount).ToArray(); if (0 == palette.Length) { RMoCore.TrackConsole.Write(this, "SerializeBlock", "Palette color is empty."); return(false); } } else { List <Color> colorList = colorQuantizer.MakePalette(colorCount); if (0 == colorList.Count) { RMoCore.TrackConsole.Write(this, "SerializeBlock", "Palette color is empty."); return(false); } colorList.Add(Color.Transparent); palette = colorList.ToArray(); } // 输出颜色数组 int x = rect.Left; int y = rect.Top; // 写入数组 if (_optionAlpha) { // 写入索引颜色和透明度 for (int h = 0; h < blockHeight; h++) { for (int w = 0; w < blockWidth; w++) { Color color = _native.GetPixel(x + w, y + h); int index = colorQuantizer.FindPaletteIndex(Color.FromArgb(255, color)); Color c = Color.FromArgb(color.A, palette[index]); output.WriteInt32(c.ToArgb()); } } } else { // 写入带透明的索引颜色 for (int h = 0; h < blockHeight; h++) { for (int w = 0; w < blockWidth; w++) { Color color = _native.GetPixel(x + w, y + h); int index = colorQuantizer.FindPaletteIndex(color); output.WriteInt32(palette[index].ToArgb()); } } } return(true); }
//============================================================ // <T>测试有效范围区域。</T> // // @param bitmap 位图 // @param rect 有效范围区域 // @param alpha 透明度 //============================================================ public static bool TestValidRectangle(Bitmap bitmap, SIntRectangle rect, int alpha = 0) { // 获得初始位置 int width = bitmap.Width; int height = bitmap.Height; int left = width; int right = 0; int top = height; int bottom = 0; // 获得内存位置 BitmapData data = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); IntPtr pointer = new IntPtr(data.Scan0.ToInt64()); // 处理所有行 int[] buffer = new int[width]; for (int y = 0; y < height; y++) { Marshal.Copy(pointer, buffer, 0, width); for (int x = 0; x < width; x++) { Color color = Color.FromArgb(buffer[x]); if (color.A > alpha) { // 确定左边界 if (x < left) { left = x; } // 确定右边界 if (x > right) { right = x; } // 确定上边界 if (y < top) { top = y; } // 确定下边界 if (y > bottom) { bottom = y; } } } pointer += data.Stride; } bitmap.UnlockBits(data); // 设置返回内容 rect.Left = left; rect.Top = top; if ((right < left) || (bottom < top)) { rect.Width = 0; rect.Height = 0; return(false); } rect.Width = right - left + 1; rect.Height = bottom - top + 1; return(true); }
//============================================================ public void SetRect(string key, SIntRectangle rect) { FXmlNode config = _config.Sync(key); rect.SaveConfig(config); }
//============================================================ // <T>打开资源。</T> //============================================================ public override void Open() { if (!_opened) { base.Open(); foreach (FRsResourceClip clip in _clips) { if (null != clip) { if (0 != clip.FrameCount) { clip.Open(); } } } // 中心点 SIntPoint2 center = new SIntPoint2(); foreach (FRsResourceClip clip in _clips) { if (null != clip) { center.X = clip.Frames[0].Size.Width / 2; center.Y = clip.Frames[0].Size.Height / 2; break; } } // 计算边界 int left = int.MaxValue; int top = int.MaxValue; int right = 0; int bottom = 0; foreach (FRsResourceClip clip in _clips) { if (null != clip && !clip.ValidRectangle.IsEmpty) { // 未反转过的边界 SIntRectangle rect = clip.ValidRectangle; if (rect.Left < left) { left = rect.Left; } if (rect.Top < top) { top = rect.Top; } if (rect.Right > right) { right = rect.Right; } if (rect.Bottom > bottom) { bottom = rect.Bottom; } } } int reverseLeft = center.X * 2 - right; int reverseRight = center.X * 2 - left; if (reverseLeft < left) { left = reverseLeft; } if (reverseRight > right) { right = reverseRight; } _size.Width = right - left; _size.Height = bottom - top; foreach (FRsResourceClip clip in _clips) { if (null != clip) { _validBarycenter.X = center.X - left; _validBarycenter.Y = center.Y - top; break; } } } _opened = true; }
//============================================================ // <T>序列化位图的一个区块。</T> // // @params output 输出流 // @params colorQuantizer 颜色优化器 // @params rect 序列化的矩形区域 // @params colorCount 颜色数量 //============================================================ protected bool SerializeBlock(IOutput output, IColorQuantizer colorQuantizer, SIntRectangle rect, int colorCount) { FByteStream stream = new FByteStream(); int blockWidth = rect.Width; int blockHeight = rect.Height; // 写入设置 stream.WriteBool(_optionAlpha); stream.WriteUint16((ushort)blockWidth); stream.WriteUint16((ushort)blockHeight); // 构造调色板 Color[] palette = null; if (_optionAlpha) { palette = colorQuantizer.MakePalette(colorCount).ToArray(); if (0 == palette.Length) { RMoCore.TrackConsole.Write(this, "SerializeBlock", "Palette color is empty."); return(false); } } else { List <Color> colorList = colorQuantizer.MakePalette(colorCount); if (0 == colorList.Count) { RMoCore.TrackConsole.Write(this, "SerializeBlock", "Palette color is empty."); return(false); } colorList.Add(Color.FromArgb(0, 0, 0, 0)); palette = colorList.ToArray(); } // 输出调色板 int paletteCount = palette.Length; stream.WriteUint16((ushort)paletteCount); //if(RResourceManager.IsColoPremultiplied) { // foreach (Color color in palette) { // if (_optionAlpha) { // stream.WriteInt32(color.ToArgb() & 0x00FFFFFF); // } else { // byte a = color.A; // byte r = (byte)(((float)color.R * (float)a) / 255.0f); // byte g = (byte)(((float)color.G * (float)a) / 255.0f); // byte b = (byte)(((float)color.B * (float)a) / 255.0f); // stream.WriteInt32(Color.FromArgb(a, r, g, b).ToArgb()); // } // } //} else if(RResourceManager.IsColoSkipProcess) { // int skipAlpha = RResourceManager.ColoSkipAlpha; // foreach(Color color in palette) { // if(_optionAlpha) { // stream.WriteInt32(color.ToArgb() & 0x00FFFFFF); // } else { // if(color.A < skipAlpha) { // stream.WriteInt32(0); // } else { // stream.WriteInt32(color.ToArgb()); // } // } // } //} else { // foreach(Color color in palette) { // if(_optionAlpha) { // stream.WriteInt32(color.ToArgb() & 0x00FFFFFF); // } else { // stream.WriteInt32(color.ToArgb()); // } // } //} // _logger.Debug(this, "SerializeIndexed", "block_size={0}x{1}, color={2}, alpha={3}", blockWidth, blockHeight, paletteCount, _optionAlpha); // 输出颜色数组 int x = rect.Left; int y = rect.Top; // 透明色索引 int transparentIndex = palette.Length - 1; int size = blockWidth * blockHeight; // 写入数组 int postion = 0; byte[] bytes = null; if (_optionAlpha) { // 写入索引颜色和透明度 bytes = new byte[size * 2]; for (int h = 0; h < blockHeight; h++) { for (int w = 0; w < blockWidth; w++) { Color color = _bitmap.GetPixel(x + w, y + h); int index = colorQuantizer.FindPaletteIndex(Color.FromArgb(255, color)); bytes[postion++] = (byte)index; bytes[postion++] = color.A; } } } else { // 写入带透明的索引颜色 bytes = new byte[size]; for (int h = 0; h < blockHeight; h++) { for (int w = 0; w < blockWidth; w++) { Color color = _bitmap.GetPixel(x + w, y + h); int index = colorQuantizer.FindPaletteIndex(color); bytes[postion++] = (byte)index; } } } stream.WriteBytes(bytes, 0, postion); // 写入数据 output.WriteInt32(stream.Length); output.WriteBytes(stream.Memory, 0, stream.Length); return(true); }
//============================================================ // <T>绘制文本。</T> // // @param text 文本 // @param format 字体格式 // @param color 颜色 // @param rectangle 范围 //============================================================ public void DrawText(string text, FDxTextFormat format, int color, SIntRectangle rectangle) { FDxSolidBrush brush = BuildSoldBrush(color); _target.DrawText(text, format.Native, new Rectangle(rectangle.Left, rectangle.Top, rectangle.Width, rectangle.Height), brush.Native); }
//============================================================ // <T>绘制文本。</T> // // @param text 文本 // @param format 字体格式 // @param brush 刷子 // @param rectangle 范围 //============================================================ public void DrawText(string text, FDxTextFormat format, FDxBrush brush, SIntRectangle rectangle) { _target.DrawText(text, format.Native, new Rectangle(rectangle.Left, rectangle.Top, rectangle.Width, rectangle.Height), brush.Native); }
//============================================================ // <T>序列化位图数据。</T> // // @params output 输出流 // @params colorCount 调色板颜色数量 // @params pixelCount 分块的像素个数 //============================================================ public bool Serialize(IOutput output, int colorCount, int pixelCount) { // 计算分割信息 int width = _validSize.Width; int height = _validSize.Height; int totalPixel = width * height; int splitWidth = width; int splitCount = totalPixel / pixelCount; int splitHeight = height; if (0 == splitCount) { splitHeight = height; splitCount = 1; } else { splitHeight = height / splitCount; splitCount = height / splitHeight; if (0 != (height % splitHeight)) { splitCount++; } } // 写入头信息 output.WriteBool(_optionAlpha); output.WriteUint16((ushort)_size.Width); output.WriteUint16((ushort)_size.Height); output.WriteUint16((ushort)_validLocation.X); output.WriteUint16((ushort)_validLocation.Y); output.WriteUint16((ushort)_validSize.Width); output.WriteUint16((ushort)_validSize.Height); output.WriteUint16((ushort)splitCount); // 若不支持半透明,去掉一个颜色,添加一个透明色 //if (!_optionAlpha) { // colorCount--; //} // 要序列化的源矩形区域 SIntRectangle subrect = new SIntRectangle(); subrect.Left = _validLocation.X; subrect.Top = _validLocation.Y; subrect.Width = splitWidth; subrect.Height = splitHeight; // 源矩形数据 FByteStream data = new FByteStream(); for (int n = 0; n < splitCount; n++) { subrect.Bottom = Math.Min(subrect.Top + splitHeight, _validLocation.Y + height); // 创建图片优化器 FPictureQuantizer pictureQuantizer = null; IColorQuantizer colorQuantizer = null; if (_optionAlpha) { pictureQuantizer = new FPictureQuantizer(EColorQuantizer.Octree); colorQuantizer = pictureQuantizer.LoadQuantizerColors(_bitmap, subrect, FPictureQuantizer.EQuantizedMode.Rgb); } else { pictureQuantizer = new FPictureQuantizer(EColorQuantizer.Octree16); colorQuantizer = pictureQuantizer.LoadQuantizerColors(_bitmap, subrect, FPictureQuantizer.EQuantizedMode.Color); } // 存储图片优化数据 if (SerializeBlock(data, colorQuantizer, subrect, colorCount)) { // _logger.Debug(this, "SerializeIndexed", "index={0}/{1}, rect={2}, size={3}", n, splitCount, rect.ToString(), bs.Length); subrect.Top += splitHeight; } else { RMoCore.TrackConsole.Write(this, "Serialize", "Picture is all transparent."); return(false); } } output.WriteInt32(data.Length); output.WriteBytes(data.Memory, 0, data.Length); return(true); }