C# - Combinando diversas Imagens em um único arquivo


Há algum tempo atrás publiquei um artigo para VB .NET que mostrava como combinar duas imagens , mesclando-as em um único arquivo imagem. (veja as referências).

Pois bem, vamos fazer a mesma coisa usando a linguagem C#.

Na verdade iremos um pouco além pois vamos mostrar como podemos combinar diversas imagens em um único arquivo.

Abra o Visual C# 2010 Express Edition e crie um novo projeto do tipo Windows Forms Application com o nome CombinandoImagens;

A seguir no formulário form1.cs inclua os seguintes controles a partir da ToolBar:

Conforme o leiaute da figura abaixo:

A seguir defina os seguintes namespaces no projeto:

using System.Security;
using System.IO;

No evento Click do botão Selecionar imagens inclua o seguinte código:

 private void btnSelecionarImagens_Click(object sender, EventArgs e)
        {
            //define as propriedades do controle 
            //OpenFileDialog
            this.ofd1.Multiselect = true;
            this.ofd1.Title = "Selecionar Fotos";
            ofd1.InitialDirectory = @"C:\macoratti\Pictures";
            //filtra para exibir somente arquivos de imagens
            ofd1.Filter = "Images (*.BMP;*.JPG;*.GIF,*.PNG,*.TIFF)|*.BMP;*.JPG;*.GIF;*.PNG;*.TIFF|" + "All files (*.*)|*.*";
            ofd1.CheckFileExists = true;
            ofd1.CheckPathExists = true;
            ofd1.FilterIndex = 2;
            ofd1.RestoreDirectory = true;
            ofd1.ReadOnlyChecked = true;
            ofd1.ShowReadOnly = true;
            
            DialogResult dr = this.ofd1.ShowDialog();

            if (dr == System.Windows.Forms.DialogResult.OK)
            {
                // Le os arquivos selecionados 
                foreach (String arquivo in ofd1.FileNames)
                {
                    txtArquivos.Text += arquivo + "#";
                    // cria um PictureBox
                    try
                    {
                        PictureBox pb = new PictureBox();
                        Image Imagem = Image.FromFile(arquivo);
                        pb.SizeMode = PictureBoxSizeMode.StretchImage;
                        //para exibir as imagens em tamanho natural 
                        //descomente as linhas abaixo e comente as duas seguintes
                        //pb.Height = loadedImage.Height;
                        //pb.Width = loadedImage.Width;
                        pb.Height = 100;
                        pb.Width = 100;
                        //atribui a imagem ao PictureBox - pb
                        pb.Image = Imagem;
                        //inclui a imagem no containter flowLayoutPanel
                        flowLayoutPanel1.Controls.Add(pb);

                    }
                    catch (SecurityException ex)
                    {
                        // O usuário  não possui permissão para ler arquivos
                        MessageBox.Show("Erro de segurança Contate o administrador de segurança da rede.\n\n" +
                                        "Mensagem : " + ex.Message + "\n\n" +
                                        "Detalhes (enviar ao suporte):\n\n" + ex.StackTrace);
                    }
                    catch (Exception ex)
                    {
                        // Não pode carregar a imagem (problemas de permissão)
                        MessageBox.Show("Não é possível exibir a imagem : " + arquivo.Substring(arquivo.LastIndexOf('\\'))
                                         + ". Você pode não ter permissão para ler o arquivo , ou " +
                                         " ele pode estar corrompido.\n\nErro reportado : " + ex.Message);
                    }
                }
            }
        }//fim e evento botão

A rotina CombinarImagens() que combinas as imagens selecionada possui o seguinte código:

        public static System.Drawing.Bitmap CombinarImagens(string[] files)
        {
            //lê todas as imagens para a memória
            List<System.Drawing.Bitmap> images = new List<System.Drawing.Bitmap>();
            System.Drawing.Bitmap imagemFinal = null;

            try
            {
                int width = 0;
                int height = 0;

                foreach (string image in files)
                {
                    //cria um bitmap a partir do arquivo e o inclui na lista
                    System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(image);

                    //atualiza o tamanho da imagem bitmap final
                    width += bitmap.Width;
                    height = bitmap.Height > height ? bitmap.Height : height;

                    images.Add(bitmap);
                }

                //cria um bitmap para tratar a imagem combinada
                imagemFinal = new System.Drawing.Bitmap(width, height);

                //Obtem o objeto gráfico da imagem 
                using (System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(imagemFinal))
                {
                    //define a cor de fundo
                    g.Clear(System.Drawing.Color.Black);

                    //percorre imagem por imagem e gera uma unica imagem final
                    int offset = 0;
                    foreach (System.Drawing.Bitmap image in images)
                    {
                        g.DrawImage(image,
                          new System.Drawing.Rectangle(offset, 0, image.Width, image.Height));
                        offset += image.Width;
                    }
                }

                return imagemFinal;
            }
            catch (Exception ex)
            {
                if (imagemFinal != null)
                    imagemFinal.Dispose();

                throw ex;
            }
            finally
            {
                //limpa a memória
                foreach (System.Drawing.Bitmap image in images)
                {
                    image.Dispose();
                }
            }
        }

No evento Click do botão de comando btnCombinarImagens temos o código que obtém os arquivos selecionados e salva as imagens combinadas:

 private void btnCombinarImagens_Click(object sender, EventArgs e)
        {
            System.Drawing.Bitmap imagensCombinadas;
            //pega todos os arquivos da pasta
            //string[] arquivos = Directory.GetFiles(@"C:\Imagens");

            //obtem a posicao da ultima ocorrência do caractere #
            int posicao = txtArquivos.Text.LastIndexOf('#');

            //remove a última ocorrência do caractere #
            string arquivosSelecionados = txtArquivos.Text.Remove(posicao);

            //separa os nomes dos arquivos gerando um array de string
            string[] arquivos = arquivosSelecionados.Split('#');

            //combina as imagens em um única imagem
            imagensCombinadas = CombinarImagens(arquivos);

            //salva a nova imagem
            imagensCombinadas.Save(@"C:\dados\ImagensCombinadas.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
        }

Observe que estamos separando os arquivos usando a função Split().

Executando o projeto e selecionando mais de uma imagem  iremos obter o seguinte resultado:

Abrindo o arquivo de imagens combinadas que foram salvas teremos:

Simples, simples assim...

Pegue o projeto completo aqui: CombinandoImagens.zip

Eu sei é apenas C# e VB .NET, mas eu gosto...

Referências:

José Carlos Macoratti