SQLServerにバイナリで保存されている画像をASP.NETで指定したサイズに変更し、画像ファイルとしてエクスポートする
SQLServerにバイナリで保存されている画像をASP.NETで画像ファイルとしてエクスポートする で、SQLServerのテーブル TMDbPosters にバイナリで格納してある映画のオリジナルサイズのポスター画像を、指定するフォルダに画像ファイルとしてエクスポートするサンプルを作りました。
SSDにデータベースを展開しているのですが、ListViewのImageにバイナリで格納している画像を System.Drawing.Bitmap.Save(Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg) で表示すると下図のように画像の表示にラグが発生してしまいます。画像ファイル表示ならラグは発生しないと思うので、すべてをエクスポートしてListViewでのポスター画像はエクスポートした画像ファイルを表示するようにしようと思います。
今回はエクスポートする画像ファイルのサイズ(縦横ピクセル)を任意に指定できるように変更します。画像サイズを変更できるよういした以外は同じです。
縦横小さい方に合わせ縦横比を固定します。
- FILESTREAMIDは非表示にしています。
- 画像ファイルの出力先パスはweb.configで指定します。
Image2FileFolderPrivate Image2FileFolder As String = ConfigurationManager.AppSettings("Image2FileFolder") - オリジナルサイズでエクスポートする場合は BinaryWriter.Write でファイルとしてエクスポートします。
- サイズを指定した場合は System.Drawing.Bitmap.Save でファイルとしてエクスポートします。
画像データのバイナリを格納するテーブル「TMDbPoster」
横幅を150pxにして全画像をエクスポートしてできた画像ファイル
ソース
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>
<!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
コメント
コメントを投稿