blog.Ring.idv.tw

Articles

IMG2WebP.net is Announced!

WebP圖檔格式(based on VP8 codec)最初是由Google在2010年9月底所發表的:WebP, a new image format for the Web,它是一種支援無損(lossless)壓縮和有損(lossy)壓縮的圖檔格式,根據Google的官方測試說明.. WebP無損壓縮的圖檔格式和PNG檔相較之下,它能比PNG檔還少26%的檔案大小;若是採用有損壓縮的話也能比JPEG圖檔再少25~34%的檔案大小,話雖如此~ 但是這畢竟是較新的圖檔格式,所以現階段有支援WebP的瀏覽器也比較少~ 除了Google本身的Chrome之外,就只有Opera有支援(CSS gradients, WebP, and Declarative UI),不過如果現在想試用看看的話,除了可以到WebP官網下載安裝之外,還可以透過IMG2WebP.net這個線上轉檔工具,直接拖張圖片進去就可自動轉成WebP圖檔,所以筆者的年假就弄了這個東西來練練功...Orz 希望有朝一日WebP圖檔的涵蓋率能佔有一席之地。

IMG2WebP線上轉檔工具

IMG2WebP.net

相關資源

A Comprehensive Guide to WebP

2013-02-19 15:35:39 | Add Comment

Sprite Animation in CSS3

.2013/01/22 新增CSS Animation + steps()

Sprite是一種經常被用於遊戲開發的技巧,如:Super MarioRockman,另一方面也常被用於網頁優化(Web Optimization)之中,將許多小圖檔組合成一張大圖,以減少這些小圖HTTP的請求次數,不過本文並非針對該議題,而是要探討如何透過CSS Animations結合Sprite來達成動畫效果,藉由Browser原生支援的方式,以減少JavaScript的程式運算來提升效率,下述例子將利用Google衣夾人(Google Street View 心得)來示範:

P.S. 目前W3C CSS Animations規格仍在Working Draft狀態。

JavaScript

var offsetX = [0, 49, 98, 147, 196, 245, 294, 343, 392, 441, 490, 539, 588, 637, 686, 735];
var olen = offsetX.length;
s.style.width = "49px";
s.style.height = "51px";
s.style.backgroundImage = "url(img/panda_001.png)";
s.style.backgroundSize = "1029px 51px";
s.style.backgroundPosition = "0px 0px";
s._ox = 0;
_main.appendChild(s);
(function animate(){
	s.style.backgroundPosition = '-'+offsetX[s._ox++%olen]+"px 0px";
	setTimeout(animate,33);
})();

Demo

這是一般透過JavaScript的方式,若從效率上的觀點來看它並不是最佳的解法。

CSS Animation

CSS

@-webkit-keyframes panda 
{
	0% { background-position: 0px 0px; }
	6.25% { background-position: 0px 0px; }
	6.26% { background-position: -49px 0px; }
	12.5% { background-position: -49px 0px; }
	12.51% { background-position: -98px 0px; }
	18.75% { background-position: -98px 0px; }
	18.76% { background-position: -147px 0px; }
	25% { background-position: -147px 0px; }
	25.01% { background-position: -196px 0px; }
	31.25% { background-position: -196px 0px; }
	31.26% { background-position: -245px 0px; }
	37.5% { background-position: -245px 0px; }
	37.51% { background-position: -294px 0px; }
	43.75% { background-position: -294px 0px; }
	43.76% { background-position: -343px 0px; }
	50% { background-position: -343px 0px; }
	50.01% { background-position: -392px 0px; }
	56.25% { background-position: -392px 0px; }
	56.26% { background-position: -441px 0px; }
	62.5% { background-position: -441px 0px; }
	62.51% { background-position: -490px 0px; }
	68.75% { background-position: -490px 0px; }
	68.76% { background-position: -539px 0px; }
	75% { background-position: -539px 0px; }
	75.01% { background-position: -588px 0px; }
	81.25% { background-position: -588px 0px; }
	81.26% { background-position: -637px 0px; }
	87.5% { background-position: -637px 0px; }
	87.51% { background-position: -686px 0px; }
	93.75% { background-position: -686px 0px; }
	93.76% { background-position: -735px 0px; }
	99.99% { background-position: -735px 0px; }
	100% { background-position: 0px 0px; }
} 

JavaScript

s.style.width = "49px";
s.style.height = "51px";
s.style.backgroundImage = "url(img/panda_001.png)";
s.style.backgroundSize = "1029px 51px";
s.style.backgroundPosition = "0px 0px";
s.style.webkitAnimation = 'panda 500ms linear infinite';

純粹透過CSS Animation的方式看起來有點冗長,不過這並不是啥大問題,因為上述的CSS Animation可以寫個function來產生,但這也不是最好的解決方式,因為上述這種方式會有spurt的問題(Demo),尤其在效率較差的Mobile平台上更顯而易見。

CSS Animation + Transform

CSS

@-webkit-keyframes panda 
{
	0% { background-position: -0px 0px; }
	100% { background-position: -15px 0px; }
} 

JavaScript

s.style.width = "1px";
s.style.height = "1px";
s.style.webkitTransform = "scaleX(49) scaleY(51)";		
s.style.backgroundImage = "url(img/panda_001.png)";
s.style.backgroundSize = "21px 1px";
s.style.webkitAnimation = 'panda 500ms linear infinite';

Demo

透過CSS Animation + Transform似乎是個不錯的方式,但若從Mobile平台來看~ 目前iOS 6.0 Safari、Android Chrome Browser支援度都還不好,僅有最近才剛上架的Chrome beta for Android(2013/01/10)有支援。

CSS Animation + steps()

CSS

@-webkit-keyframes panda 
{
	from { background-position: 0px; }
	to { background-position: -784px; }
} 

JavaScript

s.style.width = "49px";
s.style.height = "51px";
s.style.backgroundImage = "url(img/panda_001.png)";
s.style.webkitAnimation = 'panda 500ms steps(16,end) infinite';

Demo

最後「CSS Animation + steps()」此方式才是目前針對Sprite Animation最佳的解法,尤其是iOS/Android平台均支援此方法。

參考資料

Sprite animation in CSS3

Taking steps() with CSS animations

2013-01-15 02:25:50 | Add Comment

BTrace - A Dynamic Tracing Tool for Java

BTrace 是一套可以讓你動態追踨(trace)運作中程式的工具,它是由當時Sun公司的兩位高級工程師(Staff Engineer)Sundararajan AthijegannathanKannan Balasubramanian,在2007年開始進行的一項計劃,並於2008年在JavaOne的會議上正式對外公開:BTrace: Java™ Platform Observability by Bytecode Instrumentation (pdf),不過隨著Oracle在2010年併購Sun之後,目前只有A. Sundararajan仍然在Oracle公司服務,而B. Kannan則是在VMWare服務。

那究竟BTrace有何過人之處呢?舉個實例來說,以往要評估一個method會耗多少執行時間,可能的寫法如下:

long start = System.nanoTime();
test();
long end = System.nanoTime();
System.out.println(end - start);

但這樣的作法在小程式還可行,倘若要用來追踨一些大型Project原始碼的話就太麻煩了...Orz

雖然還有另一種方法,就是用JDK 5所提供的java.lang.instrument API來達成,透過AOP的方式在class載入之前就注入(inject)一些bytecode,如此便能無須更動原始碼即可完成所需,但這若是面對一個正在「運作中的程式(running program)」仍有些麻煩,除非透過JVM Tool Interface (JVM TI)的技術去達成,不過採用JVM TI還要寫一些native code,這實在還是不夠方便... 而就在2006年底時JDK 6(Mustang)正式推出之後,它為Java帶來了一些新的API,如:Java Attach APIJava Compiler API等。

簡單來說,透過Java Attach API不像JVM TI技術需要寫些native code,它就能藉由VirtualMachine class用純Java的方式去attach to a JVM,如:

VirtualMachine vm = VirtualMachine.attach(processid);
String agent = ...
vm.loadAgent(agent);

也正因為如此,所以BTrace是一個結合Java Attach APIJava Compiler APIJava Instrumentation APIASM (A Java bytecode engineering library)等技術來實現的,而這些關鍵API對應BTrace的原始碼如下:

Java Attach API: net.java.btrace.client.Client.java

Java Compiler API: net.java.btrace.compiler.Compiler.java

Java Instrumentation API: net.java.btrace.agen.Main.java

ASM: net.java.btrace.instr.Instrumentor.java

P.S. The ASM name does not mean anything, it's just a reference to the __asm__ keyword in C. (ASM 4.0 A Java bytecode engineering library)

這裡我們來看一個實際的例子,如下述程式:

Hello.java

import java.util.*;

public class Hello
{
    public Hello(){}
    public void sayHello()throws Exception
    {
        Random random = new Random();
        int r = random.nextInt(1000);
        Thread.sleep(r);
        System.out.println("Hello: "+r);
    }
    public static void main(String args[])
    {
        Hello h = new Hello();
        try
        {
            while(true)
            {
                Thread.sleep(1000l);
                h.sayHello();
            }
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

接下來~ 假設我們想知道上述程式sayHello method耗多少執行時間或stack trace都可藉由BTrace來完成,如下:

HelloTest.java

import static com.sun.btrace.BTraceUtils.*;
import com.sun.btrace.annotations.*;
 
@BTrace public class HelloTest
{
    @OnMethod(clazz="Hello",method="sayHello")
    public static void trace()
    {
        jstack();
    }
    @OnMethod(clazz="Hello",method="sayHello",location=@Location(value=Kind.RETURN))
    public static void func(@Duration long duration)
    {
        println(duration);
    }
}

上述annotations的詳細用法及BTrace的使用限制可參考BTrace User's Guide

執行BTrace

$BTRACE_HOME/bin/btrace [pid] HelloTest.java

P.S. [pid]可透過「jps」指令來取得。

結果

Hello.sayHello(Hello.java)
Hello.main(Hello.java:21)
803517667
Hello.sayHello(Hello.java)
Hello.main(Hello.java:21)
681229152

相關資源

BTrace Developer's Guide

BTrace – a Simple Way to Instrument Running Java Applications

btrace一些你不知道的事

btrace记忆

Java 動態程式碼變更 (一)

2013-01-08 01:56:18 | Add Comment

用CSS3 Transitions來模擬Path app的選單特效

上圖是Path App for iPhone的選單特效,但其實我並不常用Path... 只是某次同事介紹我使用時,我一直覺得它的選單特效很好玩!

心想應該也可以試著用CSS Transitions模擬出來,那何謂CSS Transitions?從規格書上的解釋:

CSS Transitions allows property changes in CSS values to occur smoothly over a specified duration.

也就是說~ 一般我們在設定CSS屬性值之後會立即呈現出效果,而透過CSS Transitions可以讓我們控制該效果要在多久的時間內如何來呈現,所以本文就是用CSS Transitions和一些JavaScript來模擬這個特效,有興趣可以參考下述的程式碼或直接觀看範例:

Demo

Path Menu in CSS3 Transitions

function on(n,angle,delay)
{
	n.style.webkitTransition = "all 150ms linear";
	n.style.webkitTransitionDelay = delay+"ms";
	n.style.webkitTransform = "rotate(-540deg)";
	var sx = radius * Math.cos(angle*(Math.PI/180));
	var sy = radius * Math.sin(angle*(Math.PI/180));
	n.style.left = sx+"px";
	n.style.top = sy+"px";
	var sx2 = sx *0.91;
	var sy2 = sy *0.91;
	sx *= 0.9;
	sy *= 0.9;
	function round2(e)
	{
		e.stopPropagation();
		n.removeEventListener("webkitTransitionEnd",round2,false);	
		n.style.webkitTransition = "all 100ms ease-out";
		n.style.webkitTransform = "rotate(-360deg)";
		n.style.left = sx+"px";
		n.style.top = sy+"px";
		function round3(e)
		{
			e.stopPropagation();
			n.removeEventListener("webkitTransitionEnd",round3,false);	
			n.style.left = sx2+"px";
			n.style.top = sy2+"px";
		}
		setTimeout(function(){
			n.addEventListener("webkitTransitionEnd",round3,false);
		},1);
	}
	n.addEventListener("webkitTransitionEnd",round2,false);
}
function off(n,angle,delay)
{
	n.style.webkitTransition = "all 150ms ease-out";
	n.style.webkitTransform = "rotate(-630deg)";
	var sx = radius * Math.cos(angle*(Math.PI/180));
	var sy = radius * Math.sin(angle*(Math.PI/180));
	n.style.left = sx+"px";
	n.style.top = sy+"px";
	function round2(e)
	{
		e.stopPropagation();
		n.removeEventListener("webkitTransitionEnd",round2,false);	
		n.style.webkitTransition = "all 150ms linear";
		n.style.webkitTransitionDelay = delay+"ms";
		n.style.webkitTransform = "rotate(-900deg)";
		n.style.left = "0px";
		n.style.top = "0px";
	}
	n.addEventListener("webkitTransitionEnd",round2,false);
}

2012-08-27 14:29:03 | Add Comment

如何成為iStockphoto contributor

iStockphoto是一間經營線上微圖庫(microstock photography)的公司,筆者會知道這個網站主要是在去年的時候,那時我正在公司開發一個和寶寶相關的iPhone App案子,由於需要一些嬰兒、寶寶的照片來當作App首頁及Logo,所以才找到iStockphoto這個網站,最後並從該網站上購買了五張照片來作為App使用。(P.S. 如何用10天開發一個遊戲APP,該文作者也是從iStockphoto購買圖庫來作為遊戲App使用)

最初iStockphoto這間公司是由一位加拿大人Bruce Livingstone在2000年5月所創立的,一開始該網站是用來和其它攝影師分享彼此的照片,藉此互相切磋以改善攝影技巧,不過就在2002年時,隨著社群持續地成長,每個月的頻寬費用也愈來愈多,而這也就促使Bruce Livingstone開始實作一種付費機制,讓大家可以在線上以便宜的價格來下載照片,並透過這樣的方式來維持該網站的營運。

不過就在2006年2月時,全球最大的傳統圖像供應公司Getty Images以五千萬美金的價格收購了iStockphoto,隔年2007年~ iStockphoto達到將近7200萬美金的收益,而這其中有將近2100萬美金(29%)用來支付給Contributors。

P.S. 群眾外包(Crowdsourcing)浪潮的興起(一) – 專家的新挑戰 這裡有些iStockphoto的小故事!

前陣子剛好和朋友聊到iStockphoto,他建議我可以將我所拍攝的照片也試著傳上去賣看看~ 所以筆者就花了一點時間來準備這件事,簡單來說,要申請為iStockphoto contributor主要有兩個考試步驟,第一步驟是筆試,你必須閱讀官方網站所提供的訓練手冊(Stock Photography Training Manual),然後進行大約15題的單選題考試,若是沒有通過可以馬上再重新考試,這部份只要花點時間閱讀訓練手冊應該都能通過~ 比較耗時的是所謂的照片審核考試,你必須準備三張照片上傳供iStockphoto審查人員審核,倘若沒通過的話則必須再等待三天之後才能重新再上傳,不過筆者很幸運地在二次就通過,第一次通過了在日本東京所拍攝的上述兩張,至於另一張沒過的原因(去韓國首爾時拍的…牽拖到韓國XD),主要是因為我的相機在高ISO的畫質表現的不是很好,所以被退件! P.S. 其實才ISO 800..我要上全幅!! Orz

所以三天後我上傳了一張在農曆新年期間在鹿港老街拍的舊門,透過紅色的對聯和藍色的傳統舊門而形成的強烈對比,五天後就收到了iStockphoto的審核成功通知!從審核成功的信件內文來看,裡頭提到目前每個禮拜最多只能上傳18張照片,筆者不曉得這是每個人一開始的限制還是有其它的原因。

然而重點來了,那透過這樣的方式可以帶來多少收益呢?根據作者CYC的分享文「Image4Fun 圖片銷售心得交流」來看,可以得知要高獲利其實並不是那麼容易,該作者傳了近兩百張圖在各個圖庫網站,分別為Shutterstock(85%)、Dreamstime(10%)和Istockphoto(5%),並在一年多的時間裡累積了$3,000美金,當然這樣的收益取決於你付出多少時間的回報,若是全職的話可能養不活自己,若是兼職的話也許是一筆不錯的外快,當然不乏也有高手全心投入並達到每個月$1,000美金的收入。

最後如果熱愛攝影的你也想試試能不能靠攝影來賺點小外快,你也可以和筆者一樣試試iStockphoto或是Shutterstock網站~ 下次就等筆者有收到第一筆下載再通知大家了!

P.S. iStockphoto目前也提供Illustration、Flash、Video、Audio和Logo等服務。

參考資源

2011 Microstock Industry Survey – First Look

*2012-3-27 iStockphoto 考試過關 *

公司外包給全世界群眾

2012-08-17 17:39:04 | Comments (4)

Next Posts~:::~Previous Posts
Copyright (C) Ching-Shen Chen. All rights reserved.

::: 搜尋 :::

::: 分類 :::

::: 最新文章 :::

::: 最新回應 :::

::: 訂閱 :::

Atom feed
Atom Comment