nihilogic: Compression using Canvas and PNG-embedded data 面白い人もいるもんだな~。 JavaScriptファイルをPNGファイルにしちゃって、CanvasのgetImageDataを使って再度JavaScriptに復元。 画像ファイルはあまりにも砂嵐。スクリプトの文字コードをそのままRGBにセットして、画像を生成してるからね。なので、8ビット(0~255)グレースケールの画像になるし、1文字が1ピクセル。そりゃ砂嵐だぜ。 CanvasはIEじゃ使えないからFirefoxとOpera、あと最新のWebkitでしか、この方法は使えませんよ、って言う事なんですね。 スゴイな。こんな発想なかった。GZipでいいじゃね~か、と思う自分がちょっと恥ずかしいっす。 スクリプトから画像生成するのはPHPのコードになってたけど、そのままだと試しにくいので、C#で書きなおしてみた(そのままデス)。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
namespace MakeJSPng.Controllers
{
public class HomeController : Controller
{
public void Index()
{
string js = this.ReadFromRequest("JSSource") + "";
int hash = Math.Abs(js.GetHashCode());
string fileName = string.Format("{0}.png", hash);
string filePath = Request.MapPath("~/PNGs/") + fileName;
if (js.Length > 0)
{
ViewData["JSSource"] = js;
byte[] bytes = Encoding.UTF8.GetBytes(js);
int width = (int)Math.Ceiling(Math.Sqrt((double)bytes.Length));
int height = width;
using (Bitmap bmp = new Bitmap(width, height, PixelFormat.Format24bppRgb))
{
int pos = 0;
for (int y = 0; y < height && pos < bytes.Length; y++)
{
for (int x = 0; x < width && pos < bytes.Length; x++)
{
int val = (int)bytes[pos++];
bmp.SetPixel(x, y, Color.FromArgb(0, val, val, val));
}
}
bmp.Save(filePath, ImageFormat.Png);
}
}
ViewData["PngPath"] = "/PNGs/" + fileName;
RenderView("Index");
}
public void About()
{
RenderView("About");
}
}
}
ASP.NET MVC Preview2で動くよ。 Home/Index.aspxは↓。
<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" AutoEventWireup="true" CodeBehind="Index.aspx.cs" Inherits="MakeJSPng.Views.Home.Index" %> <%@ Import Namespace="MakeJSPng.Controllers" %> <asp:Content ID="indexContent" ContentPlaceHolderID="MainContentPlaceHolder" runat="server"> <script type="text/javascript" src="/Content/pngdata.js"></script> <% using (Html.Form<HomeController>(c=>c.Index())) { %> <p>スクリプト</p> <%=Html.TextArea("JSSource", ViewData["JSSource"]) %> <p> <%=Html.SubmitButton("Make", "生成") %> </p> <p>画像</p> <img src="<%= ViewData["PngPath"] %>" id="png" /> <p>復元</p> <%=Html.TextArea("PNGSource", "") %> <% } %> <script type="text/javascript"> var path = '<%= ViewData["PngPath"] %>'; loadPNGData(path, function decodeCallback(data){ var element = document.getElementById("PNGSource"); element.value = data; }); </script> </asp:Content>
でも、IEじゃ動かないよ! 試しに、prototype.1.6.0.2.jsを圧縮した画像↓。
砂嵐。 本家はこれが30KBなんだけど、こっちは50KBなんでじゃ~!!画像サイズ少し違うし。PHPでのデフォルトエンコードがUTF8じゃないのかもしれないしね。 本家は8bppだけど、こっちは24bppなのが原因?それじゃしょうがないよね! ところでPHPのコードは良くわかんない(GDが良くわかんない?)けど、TrueColorを保存して自動で8ビットになるんでしょうか? ちょっとした息抜きってことで。