Программа для слияние двух изображений

Блог 30 октября 2014

Теги: C#, программирование,обучающий портал

Обеспечивает плавный переход. Ниже пример на 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>

Комментарии

Комментариев еще нет.
Добавить комментарий могут только авторизованные пользователи. Авторизоваться
Комментарий

Оценка





Авторизоваться через http://www.pvobr.ru
Логин
Пароль
Регистрация

Авторизоваться через соцсети
Наверх