Обеспечивает плавный переход. Ниже пример на C#.
Пример работы - слияние 2 демо-изображений
Код программы.
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using
System.Text;
using System.Runtime.InteropServices;
using System.Configuration;
namespace PictUnion
{
class Program
{
static
string file1, file2, save;
static int iOver;
static void Main(string[] args)
{
//считать конфигурацию
Bitmap image_1, image_2;
try
{
file1 = ConfigurationManager.AppSettings["file1"];
file2 = ConfigurationManager.AppSettings["file2"];
save = ConfigurationManager.AppSettings["save"];
iOver
= int.Parse(ConfigurationManager.AppSettings["over"].ToString());
image_1 = new Bitmap(file1);
image_2 = new
Bitmap(file2);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
Console.ReadKey();
return;
}
//проверки
if (image_1.Height != image_2.Height)
{
Console.WriteLine("Нужна одинаковая высота!");
Console.ReadKey();
return;
}
if (image_1.Width < iOver || image_2.Width < iOver)
{
Console.WriteLine("Слишком большой перехлест!");
Console.ReadKey();
return;
}
//слить
try
{
Bitmap
image = new Bitmap(image_1.Width + image_2.Width - iOver, image_1.Height);
image.MakeTransparent(Color.AntiqueWhite);
//
GDI+ still lies to us - the return format is BGR, NOT RGB.
BitmapData bmData_1 = image_1.LockBits(new Rectangle(0, 0, image_1.Width,
image_1.Height),
ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
int offset_1 = 0;
int stride_1 = bmData_1.Stride;
IntPtr Scan_1 = bmData_1.Scan0;
int nOffset_1 = stride_1 - image_1.Width * 4;
BitmapData bmData_2 =
image_2.LockBits(new Rectangle(0, 0, image_2.Width, image_2.Height),
ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
int offset_2 = 0;
int stride_2 = bmData_2.Stride;
IntPtr Scan_2 = bmData_2.Scan0;
int nOffset_2 = stride_2 - image_2.Width *
4;
BitmapData bmData = image.LockBits(new Rectangle(0, 0, image.Width, image.Height),
ImageLockMode.ReadWrite,
PixelFormat.Format32bppArgb);
int offset = 0;
int stride = bmData.Stride;
IntPtr Scan0 = bmData.Scan0;
int nOffset = stride - image.Width * 4;
int bBl = 0, bGr = 0, bRd = 0, bAl = 0;
int bBl_2 = 0, bGr_2 = 0,
bRd_2 = 0, bAl_2 = 0;
for (int y = 0; y < image.Height; y++)
{
for (int x = 0; x <
image.Width; x++)
{
if (x < image_1.Width - iOver)
{ //image_1
bBl = Marshal.ReadByte(Scan_1, offset_1);
bGr = Marshal.ReadByte(Scan_1, offset_1 + 1);
bRd
= Marshal.ReadByte(Scan_1, offset_1 + 2);
bAl = Marshal.ReadByte(Scan_1, offset_1 + 3);
offset_1 +=
4;
Marshal.WriteByte(Scan0, offset, (byte)bBl);
Marshal.WriteByte(Scan0, offset + 1, (byte)bGr);
Marshal.WriteByte(Scan0, offset + 2, (byte)bRd);
Marshal.WriteByte(Scan0, offset + 3, (byte)bAl);
}
else if (x < image_1.Width)
{ //перехлест
bBl =
Marshal.ReadByte(Scan_1, offset_1);
bGr = Marshal.ReadByte(Scan_1, offset_1 + 1);
bRd =
Marshal.ReadByte(Scan_1, offset_1 + 2);
bAl = Marshal.ReadByte(Scan_1, offset_1 + 3);
offset_1 += 4;
bBl_2 = Marshal.ReadByte(Scan_2, offset_2);
bGr_2 = Marshal.ReadByte(Scan_2, offset_2 + 1);
bRd_2 = Marshal.ReadByte(Scan_2, offset_2 + 2);
bAl_2 = Marshal.ReadByte(Scan_2, offset_2 + 3);
offset_2 += 4;
//слить градиентно
int d = x - image_1.Width + iOver;
bBl = (bBl * (iOver - d) + bBl_2 * d) / iOver;
bGr = (bGr * (iOver - d) + bGr_2 * d) / iOver;
bRd = (bRd * (iOver - d) + bRd_2 * d) / iOver;
Marshal.WriteByte(Scan0, offset, (byte)bBl);
Marshal.WriteByte(Scan0, offset + 1, (byte)bGr);
Marshal.WriteByte(Scan0, offset + 2, (byte)bRd);
Marshal.WriteByte(Scan0, offset + 3, (byte)bAl);
}
else
{ //image_2
bBl = Marshal.ReadByte(Scan_2, offset_2);
bGr = Marshal.ReadByte(Scan_2, offset_2 + 1);
bRd = Marshal.ReadByte(Scan_2, offset_2 + 2);
bAl = Marshal.ReadByte(Scan_2, offset_2 + 3);
offset_2
+= 4;
Marshal.WriteByte(Scan0, offset, (byte)bBl);
Marshal.WriteByte(Scan0, offset + 1, (byte)bGr);
Marshal.WriteByte(Scan0, offset + 2, (byte)bRd);
Marshal.WriteByte(Scan0, offset + 3, (byte)bAl);
}
offset += 4;
}
offset += nOffset;
offset_1 +=
nOffset_1;
offset_2 += nOffset_2;
}
image.UnlockBits(bmData);
image_1.UnlockBits(bmData_1);
image_2.UnlockBits(bmData_2);
if( save.IndexOf(".jpg") > 0 )
image.Save(save, System.Drawing.Imaging.ImageFormat.Jpeg);
else image.Save(save, System.Drawing.Imaging.ImageFormat.Png);
image_1.Dispose();
image_2.Dispose();
Console.WriteLine("Успех!");
}
catch
(Exception ex)
{
Console.WriteLine(ex.ToString());
}
Console.ReadKey();
}
}
}
Пояснения к коду программы.
Алгоритм прямолинейный. Считать конфигурацию. Создать объекты Bitmap.
"Пробежать" по байтам и скопировать в результирующий объект. В полосе перехлеста записать взвешенную сумму. Смотри также Создание "прозрачного" png-файла.
Пример конфигурационного файла
<?xml
version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="file1" value="C:
emp\test1.png"/>
<add key="file2" value="C:\temp\test2.png"/>
<add key="save" value="C:
emp\test3.png"/>
<add key="over" value="100"/>
</appSettings>
</configuration>
Комментариев еще нет.