Hromadné vkládání vodoznaku do obrázků

Josef Vondráček       22. 5. 2007       WinForms, Grafika       8982 zobrazení

Tento článek obsahuje návod na vytvoření aplikace pro hromadné vkládání vodoznaku do obrázků. Lze se na něm přiučit práci s GDI+.

Mnozí jste se již jistě setkali s e-shopem, ve kterém byly obrázky označeny vodoznakem. V dnešní době se tato technika stáva trendem pro zabezpečování autorských práv na fotky. Nebudeme si nic nalhávat a uznáme, že výroba opravdu profesionálních fotografií není příliš levnou záležitostí. Naučíme se tedy, jak vytvořit jednoduchou utilitku, pomocí které budeme schopni naše fotky hromadně upravit.

Nejprve si vytvoříme novou aplikaci, na jejíž hlavním okně sestavíme následující komponentové rozhraní:

Program bude fungovat tak, že si nejprve otevřeme obrázky, které chceme upravit. Jejich celkový seznam bude zobrazen v ListBoxu. Následně potřebujeme načíst soubor obrázku vodoznaku. Tudíž ho vykreslíme na všechny načtené obrázky v ListBoxu. Samozřejmě potřebujeme vědět, kam vodoznak vykreslit. Pro tento účel použijeme výběrovou nabídku níže. Aby jsme lépe specifikovali umístění pro hromadnou operaci se soubory, které mohou mít různé velikosti, určujeme vždy relativní pozici od určitého rohu. Přepsání původních souborů se stává též velmi užitečnou pomůckou.

Aby jsme docílili efektu vodoznaku, používáme vykreslení jednoho obrázku přez druhý, za použití transparence. Za předpokladu, že chceme docílit lepšího vzhledu, tedy textu s průhledným okolím, tak použijeme soubor s podporou průhlednosti, například *.png nebo *.gif.

Ukázka výsledného obrázku za použití souboru PNG:

 

Pokud budeme po přidání vodoznaku soubory umisťovat na web, využijeme kompresi do formátu JPEG.

Tak a teď už se pusťme do vlastního psaní programu.  Nejdříve vytvoříme několik proměnných, které slouží jako centrální úložistě nastavení pro kompresi obrázků:

    Public JPGEncoder As Drawing.Imaging.Encoder                             'informace o kodeku
    Public JPGCodecInformations As Drawing.Imaging.ImageCodecInfo            'seznam parametrů pro uložení (počet parametrů je 1) 
    Public JPGEncoderParameters As New Drawing.Imaging.EncoderParameters(1)  'pole pro uložení parametru o kompresi
    Public CompressionQuality As Integer = 80                                'úroveň kvality komprese

Dále sestavíme několik procedur, které pak můžeme používat i v rozsáhlejších projektech. Budou nám sloužit jako centrální úpravny pro obrázky.

Správa komprese obrázků:

    ''' <summary>Nastaví kompresi kodeku JPEG.</summary>
    Public Sub SetJPGCompression()
        JPGEncoderParameters.Param(0) = New Drawing.Imaging.EncoderParameter(Imaging.Encoder.Quality, CLng(CompressionQuality))
        JPGCodecInformations = GetEncoderInfo("image/jpeg")
    End Sub

    ''' <summary>Získání informací o kodeku JPEG.</summary>
    Private Function GetEncoderInfo(ByVal mimeType As String) As ImageCodecInfo
        Dim i As Integer
        Dim encoders As ImageCodecInfo()
        encoders = ImageCodecInfo.GetImageEncoders()
        For i = 0 To encoders.Length
            If encoders(i).MimeType = mimeType Then
                Return encoders(i)
            End If
        Next
        Return Nothing
    End Function

Načtení obrázku ze souboru:

Nezbytně též potřebujeme vytvořit funkci, která načte ze souboru obrázek tak, aby nebyl soubor nijak svázán s výslednou proměnnou. Tato technika využívá načtení ze souboru do proměnné Image, pak vytvoření proměnné Bitmap se stejnou velikostí jako načtený Image. Následně vytvoříme objekt Graphics, který propojíme s proměnnou Bitmap a pak zde vykreslíme načtený obrázek. Nakonec uvolníme proměnnou Image.

    ''' <summary>
    ''' Vrátí načtený obrázkový soubor do Image.
    ''' </summary>
    ''' <param name="FileName">Název souboru.</param>
    Public Function LoadImage(ByVal FileName As String) As Image
        Try
            Dim i As Image = Image.FromFile(FileName)
            Dim img As Bitmap = New Bitmap(i.Width, i.Height)
            Dim g As Drawing.Graphics = Drawing.Graphics.FromImage(img)
            g.DrawImage(i, 0, 0, i.Width, i.Height)
            i.Dispose()
            Return img
        Catch ex As Exception
            MsgBox("Nastala chyba při načítání obrázku." & vbCrLf & "(" & ex.Message & ")", MsgBoxStyle.Critical, "Chyba")
            Return Nothing
        End Try
    End Function

Vytvoření souboru s vodoznakem:

    ''' <summary>
    ''' Vložení vodoznaku do obrázku.
    ''' </summary>
    ''' <param name="InputFileName">Vstupní soubor.</param>
    ''' <param name="OutputFileName">Výstupní soubor.</param>
    ''' <param name="ImgPos">Umístění vodoznaku v obrázku.</param>
    ''' <param name="Opacity">Průhlednost.</param>
    Private Sub CreateImageFile(ByVal InputFileName As String, ByVal OutputFileName As String, ByVal ImgPos As Point, ByVal Opacity As Integer)
        Try
            Dim img As Image = LoadImage(InputFileName)
            Dim vod As Image = LoadImage(VFileName)

            Dim g As Graphics = Graphics.FromImage(img)

            Dim ptsArray As Single()() = {New Single() {1, 0, 0, 0, 0}, _
                                          New Single() {0, 1, 0, 0, 0}, _
                                          New Single() {0, 0, 1, 0, 0}, _
                                          New Single() {0, 0, 0, Math.Round(Opacity / 100, 2), 0}, _
                                          New Single() {0, 0, 0, 0, 1}}
            ' vytvoření matice barev objektu
            Dim clrMatrix As New ColorMatrix(ptsArray)
            ' vytvoření atributů obrázku
            Dim imgAttributes As New ImageAttributes
            ' nastavení matice barev
            imgAttributes.SetColorMatrix(clrMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap)
            ' vykreslení vodoznaku
            g.DrawImage(vod, New Rectangle(ImgPos, vod.Size), 0, 0, vod.Width, vod.Height, GraphicsUnit.Pixel, imgAttributes)

            ' uložení obrázku
            img.Save(OutputFileName, Me.JPGCodecInformations, Me.JPGEncoderParameters)
        Catch ex As Exception
            MsgBox("Nastala chyba při úpravách pro vložení nového obrázku!" & vbCrLf & "(" & ex.Message & ")", MsgBoxStyle.Critical, "Chyba")
        End Try
    End Sub

Teď, když už máme hotové jádro naší aplikace, můžeme se pustit do nastavení ovládacích prvků, tedy tlačítek.

Tlačítko "Přidat obrázky, které se mají upravit":

    Private Sub PridatObrazkyProUpravu_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PřidatObrázkyProÚpravu.Click
        If Soubory.ShowDialog = Windows.Forms.DialogResult.OK Then
            For Each f As String In Soubory.FileNames
                ListBox1.Items.Add(f)
            Next
        End If
    End Sub

Tlačítko "Smazat seznam":

    Private Sub SmazatSeznamObrazku_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SmazatSeznamObrázků.Click
        ListBox1.Items.Clear()
    End Sub

Tlačítko "Nahrát soubor vodoznaku":

    Private Sub NahratSouborVodoznaku_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles NahrátSouborVodoznaku.Click
        Vodoznak.FileName = VFileName
        If Vodoznak.ShowDialog = Windows.Forms.DialogResult.OK Then
            VFileName = Vodoznak.FileName
        End If
    End Sub

Tlačítko "Spracuj soubory!":

    Private Sub SpracujSoubory_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SpracujSoubory.Click
        Dim f As String                           'proměnná pro úchovu vždy jednoho názvu souboru z ListBoxu
        Dim imgPos As New Point(0, 0)             'umístění vykreslovaného vodoznaku
        Dim Opc As Integer = Opacityx.Value       'úroveň průhlednosti
        Dim img As Image                          'obrázek, na který vykreslujeme vodoznak
        Dim imgVod As Image                       'vodoznak
        CompressionQuality = Comp.Value           'úroveň komprese výsledného obrázku

        SetJPGCompression()                       'nastavení kodeku JPEG na určenou úroveň komprese

        If VFileName.Length > 0 Then
            If IO.File.Exists(VFileName) Then
                imgVod = LoadImage(VFileName)
                If ListBox1.Items.Count > 0 Then
                    For i As Integer = 0 To ListBox1.Items.Count - 1
                        If IO.File.Exists(ListBox1.Items.Item(i)) Then
                            f = ListBox1.Items.Item(i)

                            img = LoadImage(f)

                            'nastavení pozice pro vykreslení vodoznaku
                            If TopLeft.Checked Then
                                imgPos.X = TopLeftX.Value
                                imgPos.Y = TopLeftY.Value
                            End If
                            If TopRight.Checked Then
                                imgPos.X = img.Width - TopRightX.Value - imgVod.Width
                                imgPos.Y = TopRightY.Value
                            End If
                            If BottomLeft.Checked Then
                                imgPos.X = BottomLeftX.Value
                                imgPos.Y = img.Height - BottomLeftY.Value - imgVod.Height
                            End If
                            If BottomRight.Checked Then
                                imgPos.X = img.Width - BottomRightX.Value - imgVod.Width
                                imgPos.Y = img.Height - BottomRightY.Value - imgVod.Height
                            End If

                            'vykreslení vodoznaku, uložení souboru
                            If RewriteOriginal.Checked Then
                                CreateImageFile(f, f, imgPos, Opc)
                            Else
                                CreateImageFile(f, f.Substring(0, f.LastIndexOf("\") + 1) & CStr(i) & ".jpg", imgPos, Opc)
                            End If
                        Else
                            MsgBox("Soubor " & ListBox1.Items.Item(i) & " neexistuje!", MsgBoxStyle.Critical, "Chyba")
                        End If
                    Next
                    MsgBox("Spracování proběhlo úspěšně!", MsgBoxStyle.Information, "Informace")
                Else
                    MsgBox("Nejsou vybrány soubory pro spracování!", MsgBoxStyle.Exclamation, "Upozornění")
                End If
            Else
                MsgBox("Soubor vodoznaku neexistuje!", MsgBoxStyle.Critical, "Chyba")
            End If
        Else
            MsgBox("Nebyl vybrán soubor s vodoznakem!", MsgBoxStyle.Exclamation, "Upozornění")
        End If
    End Sub

Váš program jest vytvořen, nezbývá než popřát štěstí při jeho používání. Zdrojový kód příkladu si můžete stáhnout

.

 

hodnocení článku

0       Hodnotit mohou jen registrované uživatelé.

 

Mohlo by vás také zajímat

Programujeme hry - díl 1.: Hungry Snake 1

Pokud jste již programátoři, kteří umí základy Visual Basic .NET, a máte rádi hry, můžete si nějaké vytvořit sami. Jako inspirace by mohl sloužit tento seriál, kde si řekneme, jak vykreslovat grafiku v rozhraní GDI+ a čemu se raději vyhnout.

XNA 2.0 ve VB.NET - díl 4.: Textury a světla v XNA

V tomto díle přidáme na náš terén textury a naučíme se pracovat se světly. Při tom si vysvětlíme, co jsou to normály a jak je jednoduše (i když ne přesně) spočítat, aby nám světlo odvětlovalo plochy správně.

Tuning, aneb optimalizace kódu

Tipy a triky pro optimalizaci kódu tak, aby běžel co nejefektivněji.

 

 

Nový příspěvek

 

Diskuse: Hromadné vkládání vodoznaku do obrázků

Prosím nebylo by možné tento program zde dát již hotový? Neovládám programování a hodně by mi tento program pomohl. děkuji

nahlásit spamnahlásit spam -1 / 1 odpovědětodpovědět

Stáhni si zdrojové kódy,ne?Nahoře klikni na odkaz "Zde".

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Diskuse: Hromadné vkládání vodoznaku do obrázků

Píše se Zpracuj, Pepíku ;)

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Stane se ne.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Diskuse: Hromadné vkládání vodoznaku do obrázků

Ahoj, dobrý příklad. Díky za něj.

Hubert

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.

Nyní zakládáte pod článkem nové diskusní vlákno.
Pokud chcete reagovat na jiný příspěvek, klikněte na tlačítko "Odpovědět" u některého diskusního příspěvku.

Nyní odpovídáte na příspěvek pod článkem. Nebo chcete raději založit nové vlákno?

 

  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:  
Heslo:  

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback