1. [RUN! PC] 2008 九月號

    image

    感謝編輯賞光,第三篇順利刊出 :D

     

    執行緒這種東西,實在不是什麼主流的文章,不過雜誌社願意刊到第三篇,真是感謝... 前兩篇分別介紹了同步機制跟旗標,這次用執行緒集區作總結,提供了綜合的應用,也對效能的影響作整理,讓讀者具體的瞭解使用前後的效能差異。

     

    這次文章內提到了 ThreadPool 的應用,不過因為內容及篇幅的關係,沒有挖到 ThreadPool 本身怎麼設計。對這部份有興趣的讀者可以參考我寫的這三篇:

    ThreadPool 實作 #1. 基本概念

    ThreadPool 實作 #2. 程式碼 (C#)

    ThreadPool 實作 #3. AutoResetEvent / ManualResetEvent

     

    雖然好像沒有人因為看到雜誌才連到這裡來,不過還是要囉唆一下,看到文章有任何意見都可以在這裡留言給我。文章內提到的 SAMPLE CODE 可以在這裡下載! 這次的範例程式是 Console application,不提供直接在網頁上執行,下載回去試試吧!

    2008/09/03 RUN! PC 專欄文章 .NET RUN! PC 作品集 多執行緒 技術隨筆

  2. 好酷的漆彈陣列...

     

     

    雖然我很少貼這些五四三的 (明明 543 這 tags 點下去有一堆..) ,不過無意間在癮科技逛到這段實在是太酷了... 流言終結者這節目的 Adam & Jamie用漆彈示範來比喻 CPU / GPU 繪圖的差別... 不管它的比喻精不精確或妥不妥當啦,那一瞬間噴出蒙那麗莎實在是太酷了... :D

    2008/09/02 有的沒的

  3. 請正確的引用文章內容!

    在開始講 "為什麼" 之前,先講一下該如何正確的引用我的文章。

    1. 明確的提供本站及該文的網址。例如:

      ........ 網路上有個叫安德魯的寫過一篇文章: "任意放大/縮小網頁的內容" ...........


    2. 若要轉貼,請以不超過 1/3 內容為原則 (程式碼及檔案下載不算),同時也要包含第一點的資訊。引用的部份請在格式上跟你的原文有所區隔,用斜體或是改顏色都可以。例如:

      ........ 網路上有個叫安德魯的寫過一篇文章: "任意放大/縮小網頁的內容" ,他提到一個用法:
      把“放網頁大 200%”的功能直接加在我的最愛

      只要把這個 link 加到書籤, 就大功告成了!

      javascript:document.body.style.zoom="150%";void(0);

      之後看到任何網頁, 覺的看不過癮想放大看, 再點一下這個 Bookmark 就好了.
      覺的固定 150% 不好用, 那可以把 link 改成這樣:

      javascript:document.body.style.zoom=prompt('縮放比例 (%):','100%');void(0);

    3. 如果要轉貼的部份超過 1/3,或是會牽扯到商業行為,請務必取得我的同意
      聯絡方式很簡單,在這裡留言我會看的到。

      如果你要透過 RSS 自動轉貼,我也很歡迎! 不過一樣要符合前面兩點要求,請勿轉貼超過 1/3 的內容。如果你的 RSS 轉貼系統只能轉貼整篇,很抱歉,只好請你停止 RSS 轉貼。

      另外,所謂的商業行為,不只是拿去投稿出書賺稿費之類的,如果你轉載的網頁有刊登廣告,就已經算是商業行為了。

     

     

    --------------------------------------------------------------------------------------------------------------------------------

    引用說明結束。以下為本文內容,純發洩用。

     

    為什麼突然要貼這篇? 該說是 "一回生二回熟" 嘛? 沒錯,每次一時興起,到 GOOGLE 找一下我自己的資訊,總是會發現有人沒經過我同意轉貼我的文章...。轉貼對我實質上的影響並不大,畢竟我寫東西是興趣,不是拿還養家糊口的,所以被轉貼除了心理不大爽之外,其它都還好。不過這樣會大大的降低我寫東西的意願。

    舉例來說,最不滿的就是像上次在對岸的入口網站碰到的案例,原文照貼,沒註明出處,留 comment 提醒還被砍掉!? 回報站方也是一副不理不睬的樣子... 這種沒什麼好說的了,直接用我的方式表達我的不滿。

    碰過另一個例子,也是很令人厭惡,就是到處轉貼文章,不管有沒有註明出處。落落長的一整篇文章就被 COPY / PASTE 過去,最後加個小小的 "出處" 就算免責了? 如果他的網頁還放了廣告,那就等於是不當的取得利益。講的難聽一點,這跟盜版沒兩樣,不都是用別人的作品去賺取利益? 最後是通知 BLOGGER,站方停權結束這件事。

     

    看過 Jedi 的文章,我很認同他在這篇 [引用不能祇是引用] 文章裡的看法。很多人好像以為只要加了 trackback 就是盡到道義上的責任了? Trackback 太方便了,之前用的 CS 甚至方便到連 trackback 的 URL 都不需要點,一切全都無腦化自動的進行。方便到好像原本該尊重作者的動作都不用作了,直接貼了就好。所以我的網站刻意不放 trackback,因為我不喜歡這樣的結果。

    我自己認為尊重作者的引用方式,要有兩個前題。一個是清楚的讓你的讀者知道,這段引用的內容出自那個人的那一篇文章。另外就是轉貼的部份。如果你不能只提供 LINK,而需要轉貼它人的內容到你的文章內,請把握好 "片段" 的原則。轉貼幾句話是合理的,轉貼一整篇就是白目了。這跟書本只影印一部份 (好像是 1/3 以內?) 是合法的,整本影印就侵害到原作者版權了。網路上的內容,複製更容易了,也讓人更容易忽略掉這些問題。

     

    所謂 "不教而殺謂之虐",就藉著這個機會說明一下,怎樣作我才不會認為我的權益被侵害。我很歡迎同好轉貼我的文章,不過我既然是我自己的文章,我會保有這幾項權益:

    1. 個人形象
      我會發佈的東西都是在 internet 上代表我這個人。要幫我散佈可以,不過請務必讓讀者知道我的網址及該篇文章的網址。
    2. 讀者 feedback
      收到有人看了我的文章有 feedback, 對我是一大鼓勵。如果你引用的方式違背了第一點,就有可能讓想給我 feedback 的讀者找不到管道。
    3. 點閱率 / 廣告
      很實際的一點,如果你不當的引用會影響我的點閱率 (如同那些全文照貼的),不論你有沒有註明出處,在這個層面上就已經侵犯到我的權益了。雖然我不靠廣告過日子,不過我把它當作打電動的經驗值看待,看著點閱次數增加也是一種成就感。
    4. 原作者要知道作品如何被利用
      如果你有不得以的理由 (比如要發布在內部,不能連到 internet, 或是發部在平面媒體、報章雜誌) 必需原文照貼,沒有辦法滿足上面三點...,或是你要拿去賣錢等等之類的商業應用,請務必取得我本人的同意。

     

    這篇不是合約,也不是在訂什麼法律條文...。我只是想表達出我對於 "轉貼" 及 "引用" 的看法而以。其實任何方式的引用我都歡迎,只要不違背上面四點原則為前題就好。只是一直碰到類似的事件,我不想成為處理盜文事件的老手啊啊啊...。希望打了這篇,可以讓那些沒有惡意的轉貼行為,不會被我誤認為又是盜文事件。

    2008/09/01 有的沒的 火大

  4. 升級到 BlogEngine.NET 1.4.5.0 了

    哈,升級還蠻簡單的,一下子就搞定了... 特此留念 :D

     

    枉我還大陣仗的對付它,VSS (Visual Source Safe), VSS (Volume Shadow copy Service) 都搬出來用了,結果只是目錄搬一搬就好... 咳咳。

    除了 Bot Checker 沒有搬過來之外,其它應該都搞定了吧? 如果有發現我的網站有那裡沒弄好,記得留言跟我講一下 :D

    2008/08/29 BlogEngine.NET 有的沒的

  5. Canon G9 害我沒睡好... 相片自動轉正的問題

    抱怨一下,因為在看照片時發現,有些直的拍的照片看起來是正確的 (會自己轉 90 度),有些卻不是... 得歪著頭看,所以就很好奇到底是怎麼回事...。

     

    image

    這幾張是正確的 (右上 & 左下,會自動轉 90 度)

     

    image

    這幾張是錯的 (應該自動轉 90 度才對)

     

    image

    第二張是錯的 (應該要轉 180 度才對)

     

    越想越不對,我記得除了我那台古董 CANON G2 之外,後來 CANON 的相機都有加上偵測轉向的機制啊? 不外乎是水銀開關或是類似的東西,總之相機能夠得知目前是不是轉直的拍,同時能把這資訊寫到 EXIF 內的 ORIENTATION 欄位去...

    但是為什麼拍出來的相片有的可以自動轉,有的不行? 花了點時間歸納一下,發現 G9 拍出來的 "有機會" 是正常的,而家裡大人的 IXUS55 則都不會自動轉,真是怪了... 在相機上看都會自動轉正啊...

    因為我的照片都是自己用 WPF 寫程式縮圖處理的,我開始懷疑是不是我的歸檔程式的問題。G9 拍的 .CR2 檔,透過 RAW CODEC 轉成 JPEG 會自動轉正,G9 / IXUS55 拍的 JPG 檔則不會...

     

     

    image

    嗯,開始無聊了,拿起相機拍了四種角度,然後用 DEBUGGER 去看 EXIF 的 ORIENTATION 值為啥... .CR2 要用 "/ifd/{ushort=274}" 來查,會得到一個 UInt16 的值,如果是 .JPG 則要改成 "/app1/{ushort=0}/{ushort=274}" ...

    得到的值還真怪。.CR2 / .JPG 都一樣。依照上圖的順序,得到的值分別是 0x01, 0x08, 0x01, 0x06。查了查文件,除了轉 180 度那個的值不大對之外,另外三個都正常。不過 Canon Codec 在 decode 時會自動幫我做 RotateTransform,我得在處理 .JPG 時自己補上這個動作。除了轉 180" 之外其它都正常了。

     

    就是那張 180 度的不正確,害我氣的牙癢癢的... 決定跟它拼了... 改了改程式,把所有 EXIF 都印出來,用肉眼一個一個比... 本來想說是不是有別的 FLAG 可以判定出來正反? 結果看到眼睛脫窗了也沒找到,我連 EXIF 裡的 BLOB (Binary data) 都一個一個印出來看 @_@,GOOGLE 也找不到啥有用的資訊...

    最後氣到,拿起相機重拍一次,這次直接在相機上看,按下 DISPLAY 看看有無其它資訊... COW,終於發現... 相機自己也認不出轉 180 度的狀況? 嘖嘖... 搞了半天 CANON 只有偵測左轉及右轉 90 度的情況,轉 180 度就不理它了.. 哈哈!

    不過有誰會轉 180 度拍照? 當然有...

    1. 用右手拿相機自拍,按不到快門... 只好轉 180 度,用底下的姆指來按
    2. 小孩拿著自己亂拍
    3. 想不出來了...

    總算水落石出,犧牲了幾個小時的睡覺時間,咳咳... 不過既然本版都是討論 .NET 程式設計的,最後就貼點 CODE 充個數... 也算沒偏離主題了 :D 不過我想應該沒人像我一樣無聊在搞這些吧?

     

    取得 ORIENTATION 的值,並且判定要往那個方向旋轉[copy code]
                            BitmapMetadata metadata = null;                        Rotation rotate = Rotation.Rotate0;                        // ...	                        ushort value = (ushort)metadata.GetQuery("/app1/{ushort=0}/{ushort=274}");                        if (value == 6)                        {                            rotate = Rotation.Rotate90;                        }                        else if (value == 8)                        {                            rotate = Rotation.Rotate270;                        }                        else if (value == 3)                        {                            rotate = Rotation.Rotate180;                        }
    
       1:  BitmapMetadata metadata = null;
    
       2:  Rotation rotate = Rotation.Rotate0;
    
       3:  // ...  
    
       4:  ushort value = (ushort)metadata.GetQuery("/app1/{ushort=0}/{ushort=274}");
    
       5:  if (value == 6)
    
       6:  {
    
       7:      rotate = Rotation.Rotate90;
    
       8:  }
    
       9:  else if (value == 8)
    
      10:  {
    
      11:      rotate = Rotation.Rotate270;
    
      12:  }
    
      13:  else if (value == 3)
    
      14:  {
    
      15:      rotate = Rotation.Rotate180;
    
      16:  }
    

     

     

     

    利用 TransformGroup, 一次套用 ScaleTransform (縮放) + RotateTransform (旋轉) 兩種轉換特效[copy code]
                JpegBitmapEncoder target = new JpegBitmapEncoder();            TransformGroup tfs = new TransformGroup();            tfs.Children.Add(new ScaleTransform(0.1, 0.1));            switch (rotate)            {                case Rotation.Rotate90:                    tfs.Children.Add(new RotateTransform(90));                    break;                case Rotation.Rotate180:                    tfs.Children.Add(new RotateTransform(180));                    break;                case Rotation.Rotate270:                    tfs.Children.Add(new RotateTransform(270));                    break;            }            target.Frames.Add(BitmapFrame.Create(                    new TransformedBitmap(sourceFrame, tfs),                    null,                    null,                    null));            target.QualityLevel = quality;            //            // save to temp file            //            string temp = Path.Combine(Path.GetDirectoryName(trgFile), string.Format("{0:N}.tmp", Guid.NewGuid()));            FileStream trgs = File.OpenWrite(temp);            target.Save(trgs);            trgs.Close();
    
       1:  JpegBitmapEncoder target = new JpegBitmapEncoder();
    
       2:  TransformGroup tfs = new TransformGroup();
    
       3:  tfs.Children.Add(new ScaleTransform(0.1, 0.1));
    
       4:  switch (rotate)
    
       5:  {
    
       6:      case Rotation.Rotate90:
    
       7:          tfs.Children.Add(new RotateTransform(90));
    
       8:          break;
    
       9:      case Rotation.Rotate180:
    
      10:          tfs.Children.Add(new RotateTransform(180));
    
      11:          break;
    
      12:      case Rotation.Rotate270:
    
      13:          tfs.Children.Add(new RotateTransform(270));
    
      14:          break;
    
      15:  }
    
      16:  target.Frames.Add(BitmapFrame.Create(
    
      17:          new TransformedBitmap(sourceFrame, tfs),
    
      18:          null,
    
      19:          null,
    
      20:          null));
    
      21:  target.QualityLevel = quality;
    
      22:  //
    
      23:  // save to temp file
    
      24:  //
    
      25:  string temp = Path.Combine(Path.GetDirectoryName(trgFile), string.Format("{0:N}.tmp", Guid.NewGuid()));
    
      26:  FileStream trgs = File.OpenWrite(temp);
    
      27:  target.Save(trgs);
    
      28:  trgs.Close();
    

    2008/08/28 .NET Tips WPF 技術隨筆 有的沒的