I. Mở đầu

Trong bài viết này, mình sẽ hướng dẫn các bạn đọc dữ liệu EXIF của hình ảnh bằng ngôn ngữ lập trình C#. Nhưng trước tiên, mình sẽ trình bày cho các bạn biết về EXIF, nếu như các bạn đã biết thì có thể bỏ qua phần này.

EXIF là gì? EXIF (Exchangeable Image File Format) hay có tên tiếng Việt là “Định dạng tập tin ảnh có thể chuyển đổi”, đây là một tiêu chuẩn để xác định thông tin liên quan đến một bức ảnh được tạo bởi một thiết bị ghi hình cụ thể như: các thông số phơi sáng, tiêu cự, cân bằng trắng, ngày giờ chụp bức hình đó, thông tin GPS và nhiều thông tin khác nữa.

Để biết rõ hơn về EXIF, các bạn có thể xem tại đây: https://en.wikipedia.org/wiki/Exif.

II. Viết chương trình

1. Chuẩn bị

Để bắt đầu viết chương trình, mình sẽ tạo 1 project trên Visual Studio 2019 với loại project là Windows Form App (.NET Framework).

Về phiên bản .NET Framework và Visual Studio thì các bạn có thể chọn bất kỳ phiên bản nào mà bạn thích cũng được, không nhất định là phải giống với mình.

2. Tạo Form và xây dựng giao diện

Mình sẽ tạo 1 form và nó có giao diện như bên dưới:

Giao diện của chương trình.

Form có thuộc tính (Name) (tên biến) là frmMain, thuộc tính Text là “Đọc dữ liệu EXIF”.

Giao diện của mình gồm có những toolbox như sau:

  • 1 Button: Thuộc tính (Name) (tên biến) là btnImageSelection, thuộc tính Text là “Chọn hình ảnh”.
  • 1 PictureBox: Thuộc tính (Name) (tên biến) là pbImage.
  • 1 RichTextBox: Thuộc tính (Name) (tên biến) là richTextBox.
  • 1 OpenFileDialog: Thuộc tính (Name) (tên biến) là openFileDialog.

3. Thêm thư viện MetadataExtractor từ Nuget

Sau khi mình xây dựng xong phần giao diện, mình sẽ tiến hành cài đặt MetadataExtractor từ Nuget thông qua Nuget Package Manager.

Cài đặt MetadataExtractor từ Nuget.

Các bạn vào Nuget Package Manager, trong tab Browse gõ từ khóa “MetadataExtractor“, sau đó chọn phiên bản phù hợp (tương thích với phiên bản .NET Framework mà bạn đang dùng) và nhấn Install.

4. Thêm các namespace (không gian tên) cần thiết

Trước khi trình bày nội dung của các phần tiếp theo, mình sẽ tiến hành bổ sung các namespace (không gian tên) cần thiết vào phần code xử lý như sau:

using MetadataExtractor; // để sử dụng ImageMetadataReader.
using System;
using System.Collections.Generic;
using System.Drawing; // để sử dụng đối tượng Image.
using System.IO; // để sử dụng đối tượng StreamReader.
using System.Text;
using System.Windows.Forms;

5. Tạo sự kiện cho button chọn hình ảnh (btnImageSelection)

Ở bước này, mình sẽ tạo 1 sự kiện click cho button chọn hình ảnh (btnImageSelection). Sau khi tạo xong, mình sẽ viết code xử lý như sau:

– Thực hiện mở OpenFileDialog:

private void btnImageSelection_Click(object sender, EventArgs e)
{
  if (openFileDialog.ShowDialog() == DialogResult.OK)
  {
    
  }
}

– Tạo một đối tượng StreamReader đọc dữ liệu từ file mà mình đã mở từ OpenFileDialog:

private void btnImageSelection_Click(object sender, EventArgs e)
{
  if (openFileDialog.ShowDialog() == DialogResult.OK)
  {
    StreamReader streamReader = new StreamReader(openFileDialog.FileName);
  }
}

– Hiển thị hình ảnh lên Form:

private void btnImageSelection_Click(object sender, EventArgs e)
{
  if (openFileDialog.ShowDialog() == DialogResult.OK)
  {
    StreamReader streamReader = new StreamReader(openFileDialog.FileName);
    try
    {
      // Từ đối tượng StreamReader chuyển thành Image.
      Image image = Image.FromStream(streamReader.BaseStream);
      
      // Gán hình ảnh cho PictureBox (pbImage) để hiện thị lên Form.
      pbImage.Image = image;
    }
    catch (Exception ex)
    {
      MessageBox.Show($"Exception: {ex.Message}");
    }
    finally
    {
      streamReader.Dispose();
    }
  }
}

– Tiến hành đọc dữ liệu EXIF bằng MetadataExtractor và hiển thị dữ liệu lên Form:

private void btnImageSelection_Click(object sender, EventArgs e)
{
  if (openFileDialog.ShowDialog() == DialogResult.OK)
  {
    StreamReader streamReader = new StreamReader(openFileDialog.FileName);
    try
    {
      Image image = Image.FromStream(streamReader.BaseStream);
      pbImage.Image = image;

      #region "MetadataExtractor"
      
      //********************************************************
      IReadOnlyList<MetadataExtractor.Directory> directories = ImageMetadataReader.ReadMetadata(openFileDialog.FileName);

      StringBuilder stringBuilder = new StringBuilder();
      foreach (MetadataExtractor.Directory directory in directories)
        foreach (MetadataExtractor.Tag tag in directory.Tags)
          stringBuilder.Append($"{directory.Name} - {tag.Name} = {tag.Description}\n");
	  //********************************************************
      
      #endregion
      
      // Hiển thị dữ liệu lên Form thông qua RichTextBox
      richTextBox.Text = stringBuilder.ToString();
    }
    catch (Exception ex)
    {
      MessageBox.Show($"Exception: {ex.Message}");
    }
    finally
    {
      streamReader.Dispose();
    }
  }
}

6. Bổ sung lọc tập tin cho OpenFileDialog

Chương trình mình viết cơ bản đã có thể chạy được, tuy nhiên khi mở OpenFileDialog thì nó sẽ hiển thị nhiều loại tập tin khác nhau không cần thiết. Chính vì thế, mình sẽ tiến hành tạo bộ lọc để OpenFileDialog chỉ hiển thị các tập tin hình ảnh.

Cách lọc các tập tin hình ảnh như sau:

openFileDialog.Filter = "Image Files|*.jpg;*.jpeg;*.png;*.gif;*.tif;...";

Mình sẽ thêm đoạn code này vào phương thức khởi tạo (trong phần code xử lý):

public frmMain()
{
  InitializeComponent();
  openFileDialog.Filter = "Image Files|*.jpg;*.jpeg;*.png;*.gif;*.tif;...";
}

7. Hoàn thiện chương trình

Phần code xử lý:

using MetadataExtractor;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Text;
using System.Windows.Forms;

namespace EXIF
{
    public partial class frmMain : Form
    {
        public frmMain()
        {
            InitializeComponent();
            openFileDialog.Filter = "Image Files|*.jpg;*.jpeg;*.png;*.gif;*.tif;...";
        }

        private void btnImageSelection_Click(object sender, EventArgs e)
        {
            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                StreamReader streamReader = new StreamReader(openFileDialog.FileName);
                try
                {
                    Image image = Image.FromStream(streamReader.BaseStream);
                    pbImage.Image = image;

                    IReadOnlyList<MetadataExtractor.Directory> directories = ImageMetadataReader.ReadMetadata(openFileDialog.FileName);

                    StringBuilder stringBuilder = new StringBuilder();
                    foreach (MetadataExtractor.Directory directory in directories)
                        foreach (MetadataExtractor.Tag tag in directory.Tags)
                            stringBuilder.Append($"{directory.Name} - {tag.Name} = {tag.Description}\n");

                    richTextBox.Text = stringBuilder.ToString();
                }
                catch (Exception ex)
                {
                    MessageBox.Show($"Exception: {ex.Message}");
                }
                finally
                {
                    streamReader.Dispose();
                }
            }
        }
    }
}

Phần code giao diện:

namespace EXIF
{
    partial class frmMain
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.pbImage = new System.Windows.Forms.PictureBox();
            this.btnImageSelection = new System.Windows.Forms.Button();
            this.openFileDialog = new System.Windows.Forms.OpenFileDialog();
            this.richTextBox = new System.Windows.Forms.RichTextBox();
            ((System.ComponentModel.ISupportInitialize)(this.pbImage)).BeginInit();
            this.SuspendLayout();
            // 
            // pbImage
            // 
            this.pbImage.BackColor = System.Drawing.SystemColors.AppWorkspace;
            this.pbImage.Location = new System.Drawing.Point(12, 66);
            this.pbImage.Name = "pbImage";
            this.pbImage.Size = new System.Drawing.Size(488, 407);
            this.pbImage.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
            this.pbImage.TabIndex = 0;
            this.pbImage.TabStop = false;
            // 
            // btnImageSelection
            // 
            this.btnImageSelection.BackColor = System.Drawing.SystemColors.ActiveCaption;
            this.btnImageSelection.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.btnImageSelection.Location = new System.Drawing.Point(12, 12);
            this.btnImageSelection.Name = "btnImageSelection";
            this.btnImageSelection.Size = new System.Drawing.Size(488, 34);
            this.btnImageSelection.TabIndex = 1;
            this.btnImageSelection.Text = "Chọn hình ảnh";
            this.btnImageSelection.UseVisualStyleBackColor = false;
            this.btnImageSelection.Click += new System.EventHandler(this.btnImageSelection_Click);
            // 
            // richTextBox
            // 
            this.richTextBox.Location = new System.Drawing.Point(506, 12);
            this.richTextBox.Name = "richTextBox";
            this.richTextBox.Size = new System.Drawing.Size(451, 461);
            this.richTextBox.TabIndex = 2;
            this.richTextBox.Text = "";
            // 
            // frmMain
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(969, 497);
            this.Controls.Add(this.richTextBox);
            this.Controls.Add(this.btnImageSelection);
            this.Controls.Add(this.pbImage);
            this.Name = "frmMain";
            this.Text = "Đọc dữ liệu EXIF";
            ((System.ComponentModel.ISupportInitialize)(this.pbImage)).EndInit();
            this.ResumeLayout(false);

        }

        #endregion

        private System.Windows.Forms.PictureBox pbImage;
        private System.Windows.Forms.Button btnImageSelection;
        private System.Windows.Forms.OpenFileDialog openFileDialog;
        private System.Windows.Forms.RichTextBox richTextBox;
    }
}

III. Chạy chương trình

Đây là chương trình của mình sau khi xây dựng xong:

Các bạn có thể xem chi tiết hơn trong video này:

IV. Source code

Tải xuống tại đây:

VI. Lời kết

Như vậy, thông qua bài viết này, mình đã chia sẻ cho các bạn cách để có thể đọc được dữ liệu EXIF của hình ảnh trong ngôn ngữ lập trình C# với sự hỗ trợ của MetadataExtractor, rất đơn giản phải không nào? Nếu các bạn thấy bài viết này hay, đừng ngần ngại, hãy chia sẻ cho nhiều người biết tới hơn nhé. Cuối cùng, cảm ơn các bạn đã đọc bài viết, nếu các bạn có vấn đề cần giải đáp, hãy để lại bình luận cho mình nhé!

Được phân loại: