SQLServerにバイナリで保存されている画像をASP.NETで指定したサイズに変更し、画像ファイルとしてエクスポートする

SQLServerにバイナリで保存されている画像をASP.NETで画像ファイルとしてエクスポートする で、SQLServerのテーブル TMDbPosters にバイナリで格納してある映画のオリジナルサイズのポスター画像を、指定するフォルダに画像ファイルとしてエクスポートするサンプルを作りました。

SSDにデータベースを展開しているのですが、ListViewのImageにバイナリで格納している画像を System.Drawing.Bitmap.Save(Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg) で表示すると下図のように画像の表示にラグが発生してしまいます。画像ファイル表示ならラグは発生しないと思うので、すべてをエクスポートしてListViewでのポスター画像はエクスポートした画像ファイルを表示するようにしようと思います。

07

今回はエクスポートする画像ファイルのサイズ(縦横ピクセル)を任意に指定できるように変更します。画像サイズを変更できるよういした以外は同じです。

縦横小さい方に合わせ縦横比を固定します。

  • FILESTREAMIDは非表示にしています。
  • 画像ファイルの出力先パスはweb.configで指定します。
    Image2FileFolder
    Private Image2FileFolder As String = ConfigurationManager.AppSettings("Image2FileFolder")
  • オリジナルサイズでエクスポートする場合は BinaryWriter.Write でファイルとしてエクスポートします。
  • サイズを指定した場合は System.Drawing.Bitmap.Save でファイルとしてエクスポートします。

 

横幅150px
03
横幅300px
04
横幅600px
05

画像データのバイナリを格納するテーブル「TMDbPoster」
画像バイナリ格納テーブル

エクスポート終了
08

横幅を150pxにして全画像をエクスポートしてできた画像ファイル
06

 

ソース

 

0102

ASPX

Binary2FileResize.aspx

<%@ Page Language="VB" AutoEventWireup="false" CodeFile="Binary2FileResize.aspx.vb" Inherits="ListViewPoster" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        W:<asp:TextBox ID="TextBoxW" runat="server" Columns="4">150</asp:TextBox>
        H:<asp:TextBox ID="TextBoxH" runat="server" Columns="4">300</asp:TextBox>
        <asp:Button ID="ButtonDisplay" runat="server" Text="Display" />
        <asp:Button ID="ButtonExport" runat="server" Text="Export" />
        <asp:Button ID="ButtonExportAll" runat="server" Text="ExportAll" />
        <asp:CheckBox ID="CheckBoxCreate" runat="server" Text="" />
        <asp:CheckBox ID="CheckBoxORG" runat="server" Text="" />
        <asp:Label ID="LabelResult" runat="server"></asp:Label>
        <br />
    
        <asp:ListView ID="ListViewPosters" runat="server" DataKeyNames="ID" DataSourceID="SqlDataSource1" GroupItemCount="10">
            <AlternatingItemTemplate>
                <td runat="server" style="vertical-align: top">ID:
                    <asp:Label ID="IDLabel" runat="server" Text='<%# Eval("ID") %>' />
                    <br />STREAMID:
                    <asp:Label ID="STREAMIDLabel" runat="server" Text='<%# Eval("STREAMID") %>' Visible="False" />
                    <br />TMDbID:
                    <asp:Label ID="TMDbIDLabel" runat="server" Text='<%# Eval("TMDbID") %>' />
                    <br />aspect_ratio:
                    <asp:Label ID="aspect_ratioLabel" runat="server" Text='<%# Eval("aspect_ratio") %>' />
                    <br />file_path:
                    <asp:Label ID="file_pathLabel" runat="server" Text='<%# Eval("file_path") %>' Visible="False" />
                    <br />height:
                    <asp:Label ID="heightLabel" runat="server" Text='<%# Eval("height") %>' />
                    <br />width:
                    <asp:Label ID="widthLabel" runat="server" Text='<%# Eval("width") %>' />
                    <br />
                    <asp:Image ID="Image2" runat="server" ImageUrl='<%# "imagePoster.aspx?ID=" + Convert.ToString(DataBinder.Eval(Container.DataItem, "ID")) + "&w=" + Convert.ToString(DataBinder.Eval(Container.DataItem, "w")) + "&h=" + Convert.ToString(DataBinder.Eval(Container.DataItem, "h")) %>' />
                    <br />
                    <asp:Label ID="LabelStatus" runat="server"></asp:Label>
                </td>
            </AlternatingItemTemplate>
            <EmptyDataTemplate>
                <table runat="server" style="">
                    <tr>
                        <td></td>
                    </tr>
                </table>
            </EmptyDataTemplate>
            <EmptyItemTemplate>
<td runat="server" />
            </EmptyItemTemplate>
            <GroupTemplate>
                <tr id="itemPlaceholderContainer" runat="server">
                    <td id="itemPlaceholder" runat="server"></td>
                </tr>
            </GroupTemplate>
            <ItemTemplate>
                <td runat="server" style="vertical-align: top">ID:
                    <asp:Label ID="IDLabel" runat="server" Text='<%# Eval("ID") %>' />
                    <br />STREAMID:
                    <asp:Label ID="STREAMIDLabel" runat="server" Text='<%# Eval("STREAMID") %>' Visible="False" />
                    <br />TMDbID:
                    <asp:Label ID="TMDbIDLabel" runat="server" Text='<%# Eval("TMDbID") %>' />
                    <br />aspect_ratio:
                    <asp:Label ID="aspect_ratioLabel" runat="server" Text='<%# Eval("aspect_ratio") %>' />
                    <br />file_path:
                    <asp:Label ID="file_pathLabel" runat="server" Text='<%# Eval("file_path") %>' Visible="False" />
                    <br />height:
                    <asp:Label ID="heightLabel" runat="server" Text='<%# Eval("height") %>' />
                    <br />width:
                    <asp:Label ID="widthLabel" runat="server" Text='<%# Eval("width") %>' />
                    <br />
                    <asp:Image ID="Image1" runat="server" ImageUrl='<%# "imagePoster.aspx?ID=" + Convert.ToString(DataBinder.Eval(Container.DataItem, "ID")) + "&w=" + Convert.ToString(DataBinder.Eval(Container.DataItem, "w")) + "&h=" + Convert.ToString(DataBinder.Eval(Container.DataItem, "h")) %>' />
                    <br />
                    <asp:Label ID="LabelStatus" runat="server"></asp:Label>
                    <br /></td>
            </ItemTemplate>
            <LayoutTemplate>
                <table runat="server">
                    <tr runat="server">
                        <td runat="server">
                            <table id="groupPlaceholderContainer" runat="server" border="0" style="">
                                <tr id="groupPlaceholder" runat="server">
                                </tr>
                            </table>
                        </td>
                    </tr>
                    <tr runat="server">
                        <td runat="server" style="">
                            <asp:DataPager ID="DataPager1" runat="server" PageSize="20">
                                <Fields>
                                    <asp:NextPreviousPagerField ButtonType="Button" ShowFirstPageButton="True" ShowLastPageButton="True" />
                                    <asp:NumericPagerField ButtonCount="50" />
                                </Fields>
                            </asp:DataPager>
                        </td>
                    </tr>
                </table>
            </LayoutTemplate>
        </asp:ListView>
        <asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:TESTConnectionString %>" SelectCommand="SELECT [ID], [STREAMID], [TMDbID], [aspect_ratio], [file_path], [height], [width], [iso_639_1], [vote_average], [vote_count],@w as w,@h as h FROM [TMDbPoster]">
            <SelectParameters>
                <asp:ControlParameter ControlID="TextBoxW" Name="w" PropertyName="Text" />
                <asp:ControlParameter ControlID="TextBoxH" Name="h" PropertyName="Text" />
            </SelectParameters>
        </asp:SqlDataSource>
    
        <asp:SqlDataSource ID="SqlDataSource2" runat="server" ConnectionString="<%$ ConnectionStrings:TESTConnectionString %>" SelectCommand="SELECT [ID], [file_path] FROM [TMDbPoster]"></asp:SqlDataSource>
    
    </div>
    </form>
</body>
</html>

VB

Binary2FileResize.aspx

Imports System.Data
Imports System.Data.SqlClient
Imports System.IO
Imports System.Drawing

Partial Class ListViewPoster
    Inherits System.Web.UI.Page
    Private DVPosters As Data.DataView
    Private Image2FileFolder As String = ConfigurationManager.AppSettings("Image2FileFolder")
    Private BooleanNoError As Boolean = True

    Protected Sub ButtonExport_Click(sender As Object, e As EventArgs) Handles ButtonExport.Click

        For Each item In ListViewPosters.Items
            Dim objID As Object = item.FindControl("IDLabel")
            Dim objFileName As Object = item.FindControl("file_pathLabel")
            Dim objStatus As Object = item.FindControl("LabelStatus")
            If Not objID Is Nothing And Not objFileName Is Nothing And Not objStatus Is Nothing Then
                Using con As New SqlConnection(SqlDataSource1.ConnectionString.ToString())
                    con.Open()
                    Dim strSQL As String = "SELECT Image FROM TMDbPoster WHERE ID = " + objID.text
                    Using sqlCmd As New SqlCommand(strSQL, con)
                        Using sdr As SqlDataReader = sqlCmd.ExecuteReader
                            Do While sdr.Read
                                Dim strFileNmae As String = Mid(objFileName.text, 2, Len(objFileName.text) - 1)
                                Dim strPath As String = Image2FileFolder + "\" + strFileNmae
                                If CheckBoxORG.Checked Then
                                    Try
                                        Dim mode As FileMode
                                        If CheckBoxCreate.Checked Then
                                            mode = FileMode.Create
                                        Else
                                            mode = FileMode.CreateNew
                                        End If
                                        Dim fs As New FileStream(strPath, mode)
                                        Dim bw As New BinaryWriter(fs)
                                        bw.Write(CType(sdr.Item(0), Byte()))
                                        objStatus.text = "Write Success"
                                        objStatus.forecolor = Drawing.Color.Blue
                                    Catch ex As Exception
                                        objStatus.text = "Write Error" + "<br>" + ex.Message
                                        objStatus.forecolor = Drawing.Color.Red
                                    End Try
                                Else
                                    Dim oW As Integer = TextBoxW.Text
                                    Dim oH As Integer = TextBoxH.Text
                                    Dim bmp As System.Drawing.Bitmap = System.Drawing.Bitmap.FromStream(New System.IO.MemoryStream(DirectCast(sdr.Item(0), Byte())))
                                    If bmp.Width > oW Or bmp.Height > oH Then
                                        Dim s As Double = Math.Min(oW / bmp.Width, oH / bmp.Height)
                                        Dim sW As Integer = CInt(s * bmp.Width)
                                        Dim sH As Integer = CInt(s * bmp.Height)
                                        Dim newBmp As New System.Drawing.Bitmap(bmp, sW, sH)
                                        Using g As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(newBmp)
                                            g.DrawImage(bmp, 0, 0, sW, sH)
                                        End Using
                                        Try
                                            newBmp.Save(strPath)
                                            objStatus.text = "Write Success"
                                            objStatus.forecolor = Drawing.Color.Blue
                                        Catch ex As Exception
                                            objStatus.text = "Write Error" + "<br>" + ex.Message
                                            objStatus.forecolor = Drawing.Color.Red
                                        End Try
                                    Else
                                        Try
                                            Dim mode As FileMode
                                            If CheckBoxCreate.Checked Then
                                                mode = FileMode.Create
                                            Else
                                                mode = FileMode.CreateNew
                                            End If
                                            Dim fs As New FileStream(strPath, mode)
                                            Dim bw As New BinaryWriter(fs)
                                            bw.Write(CType(sdr.Item(0), Byte()))
                                            objStatus.text = "Write Success"
                                            objStatus.forecolor = Drawing.Color.Blue
                                        Catch ex As Exception
                                            objStatus.text = "Write Error" + "<br>" + ex.Message
                                            objStatus.forecolor = Drawing.Color.Red
                                        End Try
                                    End If
                                End If
                            Loop
                        End Using
                    End Using
                    con.Close()
                End Using
            End If
        Next

    End Sub

    Protected Sub ButtonExportAll_Click(sender As Object, e As EventArgs) Handles ButtonExportAll.Click

        DVPosters = SqlDataSource2.Select(DataSourceSelectArguments.Empty)
        For Each row In DVPosters
            Using con As New SqlConnection(SqlDataSource1.ConnectionString.ToString())
                con.Open()
                Dim strSQL As String = "SELECT Image FROM TMDbPoster WHERE ID = " + row(0).ToString
                Using sqlCmd As New SqlCommand(strSQL, con)
                    Using sdr As SqlDataReader = sqlCmd.ExecuteReader
                        Do While sdr.Read
                            Dim strFileNmae As String = Mid(row(1), 2, Len(row(1)) - 1)
                            Dim strPath As String = Image2FileFolder + "\" + strFileNmae
                            If CheckBoxORG.Checked Then
                                Try
                                    Dim mode As FileMode
                                    If CheckBoxCreate.Checked Then
                                        mode = FileMode.Create
                                    Else
                                        mode = FileMode.CreateNew
                                    End If
                                    Dim fs As New FileStream(strPath, mode)
                                    Dim bw As New BinaryWriter(fs)
                                    bw.Write(CType(sdr.Item(0), Byte()))
                                Catch ex As Exception
                                    LabelResult.Text = "Write Error" + "<br>" + ex.Message
                                    LabelResult.ForeColor = Drawing.Color.Red
                                    BooleanNoError = False
                                End Try
                            Else
                                Dim oW As Integer = TextBoxW.Text
                                Dim oH As Integer = TextBoxH.Text
                                Dim bmp As System.Drawing.Bitmap = System.Drawing.Bitmap.FromStream(New System.IO.MemoryStream(DirectCast(sdr.Item(0), Byte())))
                                If bmp.Width > oW Or bmp.Height > oH Then
                                    Dim s As Double = Math.Min(oW / bmp.Width, oH / bmp.Height)
                                    Dim sW As Integer = CInt(s * bmp.Width)
                                    Dim sH As Integer = CInt(s * bmp.Height)
                                    Dim newBmp As New System.Drawing.Bitmap(bmp, sW, sH)
                                    Using g As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(newBmp)
                                        g.DrawImage(bmp, 0, 0, sW, sH)
                                    End Using
                                    Try
                                        newBmp.Save(strPath)
                                    Catch ex As Exception
                                        LabelResult.Text = "Write Error" + "<br>" + ex.Message
                                        LabelResult.ForeColor = Drawing.Color.Red
                                        BooleanNoError = False
                                    End Try
                                Else
                                    Try
                                        Dim mode As FileMode
                                        If CheckBoxCreate.Checked Then
                                            mode = FileMode.Create
                                        Else
                                            mode = FileMode.CreateNew
                                        End If
                                        Dim fs As New FileStream(strPath, mode)
                                        Dim bw As New BinaryWriter(fs)
                                        bw.Write(CType(sdr.Item(0), Byte()))
                                    Catch ex As Exception
                                        LabelResult.Text = "Write Error" + "<br>" + ex.Message
                                        LabelResult.ForeColor = Drawing.Color.Red
                                        BooleanNoError = False
                                    End Try
                                End If
                            End If
                        Loop
                    End Using
                End Using
                con.Close()
                If BooleanNoError Then
                    LabelResult.Text = "All Binary Image Write Success"
                    LabelResult.ForeColor = Drawing.Color.Blue
                End If
            End Using
        Next

    End Sub
End Class

 

ASPX

imagePoster.aspx
<%@ Page Language="VB" AutoEventWireup="false" CodeFile="imagePoster.aspx.vb" Inherits="imagePoster" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
    
        <asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:TESTConnectionString %>" SelectCommand="SELECT [Image] FROM [TMDbPoster] WHERE ([ID] = @ID)">
            <SelectParameters>
                <asp:QueryStringParameter Name="ID" QueryStringField="ID" Type="Int32" />
            </SelectParameters>
        </asp:SqlDataSource>
    
    </div>
    </form>
</body>
</html>

VB

imagePoster.aspx.vb

Partial Class imagePoster
    Inherits System.Web.UI.Page

    Protected Sub Page_PreLoad(sender As Object, e As EventArgs) Handles Me.PreLoad

        Dim dv As Data.DataView = SqlDataSource1.Select(DataSourceSelectArguments.Empty)
        If Not dv Is Nothing Then
            If dv.Table.Rows.Count > 0 Then
                If Not IsDBNull(dv.Table.Rows(0)(0)) Then
                    Dim oW As Integer = Page.Request.QueryString.Get("w")
                    Dim oH As Integer = Page.Request.QueryString.Get("h")
                    Dim bmp As System.Drawing.Bitmap = System.Drawing.Bitmap.FromStream(New System.IO.MemoryStream(DirectCast(dv.Table.Rows(0)(0), Byte())))
                    If bmp.Width > oW Or bmp.Height > oH Then
                        Dim s As Double = Math.Min(oW / bmp.Width, oH / bmp.Height)
                        Dim sW As Integer = CInt(s * bmp.Width)
                        Dim sH As Integer = CInt(s * bmp.Height)
                        Dim outBmp As System.Drawing.Bitmap = New System.Drawing.Bitmap(sW, sH)
                        Using g As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(outBmp)
                            g.DrawImage(bmp, 0, 0, sW, sH)
                        End Using
                        outBmp.Save(Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg)
                    Else
                        Response.BinaryWrite(DirectCast(dv.Table.Rows(0)(0), Byte()))
                    End If
                    Response.End()
                End If
            End If
        End If

    End Sub
End Class

コメント

このブログの人気の投稿

ダブルクォーテーションで括られたCSVカ​ンマ区切りテキストファイルを SQL Server で Bulk Insert する方法

PowerShellでTSV/CSVの列を絞り込んで抽出し、(先頭/行末)からN行出力する

IKEAの鏡を壁に取り付ける