<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	>

<channel>
	<title>Barcode Knowledge and More</title>
	<atom:link href="http://www.barcodeschool.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.barcodeschool.com</link>
	<description>dedicated on barcode</description>
	<pubDate>Sun, 11 Dec 2011 03:04:39 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.7</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Using JanRain OpenID with Zend Framework</title>
		<link>http://www.barcodeschool.com/2011/12/using-janrain-openid-with-zend-framework/</link>
		<comments>http://www.barcodeschool.com/2011/12/using-janrain-openid-with-zend-framework/#comments</comments>
		<pubDate>Sun, 11 Dec 2011 03:04:39 +0000</pubDate>
		<dc:creator>Sherwood Hu</dc:creator>
		
		<category><![CDATA[Programming]]></category>

		<category><![CDATA[OpenID]]></category>

		<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://www.barcodeschool.com/2011/12/using-janrain-openid-with-zend-framework/</guid>
		<description><![CDATA[We are currently working on an OpenID consumer implementation. We looked into the Zend_OpenID - unfortunately it did not work. We are unable to get it work with Google. The remaining choice is the excellent JanRain library. 
OK, the Jan rain library is not PHP 5.3 friendly. There are several warnings if you try included [...]]]></description>
			<content:encoded><![CDATA[<p>We are currently working on an OpenID consumer implementation. We looked into the Zend_OpenID - unfortunately it did not work. We are unable to get it work with Google. The remaining choice is the excellent <a href="http://www.openidenabled.com/php-openid/" target="_blank">JanRain library</a>. </p>
<p>OK, the Jan rain library is not PHP 5.3 friendly. There are several warnings if you try included consumer test. The library also requires several extensions. To start you&#8217;d better read the README first and run the detect.php under its example directory. Fortunately, those warnings are easy to deal with and I won&#8217;t repeat them here.</p>
<p> <code><span style="color: #000000">$path = ini_get(&#8217;include_path&#8217;);      <br />$path = APPLICATION_PATH . &#8216;/../library/openid-php&#8217; . PATH_SEPARATOR . $path;       <br />ini_set(&#8217;include_path&#8217;, $path);       </p>
<p>require_once &quot;Auth/OpenID/Consumer.php&quot;;       <br />require_once &quot;Auth/OpenID/FileStore.php&quot;;       <br />require_once &quot;Auth/OpenID/SReg.php&quot;;       <br />require_once &quot;Auth/OpenID/PAPE.php&quot;;       </p>
<p>class OpenidController extends Zend_Controller_Action       <br />{       <br />&#160; public function init()       <br />&#160; {       <br />&#160;&#160;&#160; $this-&gt;session = new Zend_Session_Namespace(&#8217;openid&#8217;);       <br />&#160;&#160;&#160; $this-&gt;store = $this-&gt;getFileStore();       <br />&#160;&#160;&#160; $this-&gt;consumer = new Auth_OpenID_Consumer($this-&gt;store);       <br />&#160; }       <br />&#160;&#160; <br />&#160;&#160; /** for testing only. This is not necessary as openid_identifier       <br />&#160; *&#160; is captured in the URL. */       <br />&#160; public function indexAction()&#160; <br />&#160; {       <br />&#160; }       <br />&#160;&#160; <br />&#160; public function tryAction()&#160; <br />&#160; {       <br />&#160;&#160;&#160; $this-&gt;openid = $_GET['openid_identifier'];       <br />&#160;&#160;&#160; try {       <br />&#160;&#160;&#160;&#160;&#160; // Make sure the user entered something.       <br />&#160;&#160;&#160;&#160;&#160; if(strlen($this-&gt;openid) == 0) {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; throw new Exception(&#8217;OpenID is empty.&#8217;);       <br />&#160;&#160;&#160;&#160;&#160; }       </p>
<p>&#160;&#160;&#160;&#160;&#160; // Try to start an openid authentication.       <br />&#160;&#160;&#160;&#160;&#160; $auth_request = $this-&gt;consumer-&gt;begin($this-&gt;openid);       </p>
<p>&#160;&#160;&#160;&#160;&#160; if(!$auth_request) {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; throw new Exception(&quot;No Auth Request&quot;);       <br />&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160;&#160;&#160;&#160; <br />&#160;&#160;&#160;&#160;&#160; $sreg_request = Auth_OpenID_SRegRequest::build(       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; // Required       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; array(&#8217;nickname&#8217;),       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; // Optional       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; array(&#8217;fullname&#8217;, &#8216;email&#8217;));       <br />&#160;&#160;&#160;&#160; <br />&#160;&#160;&#160;&#160;&#160; if ($sreg_request) {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; $auth_request-&gt;addExtension($sreg_request);       <br />&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160;&#160;&#160;&#160; </p>
<p>&#160;&#160;&#160;&#160;&#160;&#160; $redirect_url = $auth_request       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; -&gt;RedirectURL($this-&gt;getTrustRoot(),$this-&gt;getReturnTo());       </p>
<p>&#160;&#160;&#160;&#160;&#160; if (Auth_OpenID::isFailure($redirect_url)) {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; throw new Exception(&quot;Could not redirect to server: &quot;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; . $redirect_url-&gt;message);       <br />&#160;&#160;&#160;&#160;&#160; }       </p>
<p>&#160;&#160;&#160; } catch (Exception $e) {       <br />&#160;&#160;&#160;&#160;&#160; $this-&gt;view-&gt;error = $e-&gt;getMessage();       <br />&#160;&#160;&#160;&#160;&#160; $this-&gt;render(&#8217;index&#8217;);       <br />&#160;&#160;&#160;&#160;&#160; return;       <br />&#160;&#160;&#160; }       </p>
<p>&#160;&#160;&#160; $this-&gt;_redirect($redirect_url);       <br />&#160; }       <br />&#160;&#160;&#160;&#160; <br />&#160; private $session;       <br />&#160; private $store;       <br />&#160; private $consumer;       <br />&#160; private $openid;       </p>
<p>&#160; public function getFileStore()&#160; <br />&#160; {       <br />&#160;&#160;&#160; /**       <br />&#160;&#160;&#160;&#160; * This is where the example will store its OpenID information.       <br />&#160;&#160;&#160;&#160; * You should change this path if you want the example store to be       <br />&#160;&#160;&#160;&#160; * created elsewhere.&#160; After you&#8217;re done playing with the example       <br />&#160;&#160;&#160;&#160; * script, you&#8217;ll have to remove this directory manually.       <br />&#160;&#160;&#160;&#160; */       <br />&#160;&#160;&#160; $store_path = null;       <br />&#160;&#160;&#160; if (function_exists(&#8217;sys_get_temp_dir&#8217;)) {       <br />&#160;&#160;&#160;&#160;&#160; $store_path = sys_get_temp_dir();       <br />&#160;&#160;&#160; }       <br />&#160;&#160;&#160; else {       <br />&#160;&#160;&#160;&#160;&#160; if (strpos(PHP_OS, &#8216;WIN&#8217;) === 0) {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; $store_path = $_ENV['TMP'];       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (!isset($store_path)) {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; $dir = &#8216;C:\Windows\Temp&#8217;;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160;&#160;&#160; else {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; $store_path = @$_ENV['TMPDIR'];       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (!isset($store_path)) {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; $store_path = &#8216;/tmp&#8217;;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160; }       <br />&#160;&#160;&#160; $store_path .= DIRECTORY_SEPARATOR . &#8216;_atlantis_openid&#8217;;       <br />&#160;&#160; <br />&#160;&#160;&#160; if (!file_exists($store_path) &amp;&amp;       <br />&#160;&#160;&#160;&#160;&#160; !mkdir($store_path)) {       <br />&#160;&#160;&#160;&#160;&#160; print &quot;Could not create the FileStore directory &#8216;$store_path&#8217;. &quot;.       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; &quot; Please check the effective permissions.&quot;;       <br />&#160;&#160;&#160;&#160;&#160; exit(0);       <br />&#160;&#160;&#160; }       <br />&#160;&#160;&#160; $r = new Auth_OpenID_FileStore($store_path);       </p>
<p>&#160;&#160;&#160; return $r;       <br />&#160; }       <br />&#160;&#160; <br />&#160; /**       <br />&#160;&#160; * When the identity provider is done having their       <br />&#160;&#160; * moment with the user they get returned to this action.       <br />&#160;&#160; * Here we look at the response status codes to decide       <br />&#160;&#160; * to if they were authenticated or not.       <br />&#160;&#160; */       <br />&#160; public function finishAction()&#160; <br />&#160; {       <br />&#160;&#160;&#160;&#160;&#160; $return_to = $this-&gt;getReturnTo();       <br />&#160;&#160;&#160;&#160;&#160; $response = $this-&gt;consumer-&gt;complete($return_to);       <br />&#160;&#160;&#160;&#160;&#160;&#160; <br />&#160;&#160;&#160;&#160;&#160; if($response-&gt;status == Auth_OpenID_CANCEL) {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; $this-&gt;view-&gt;error = &#8216;Verification cancelled.&#8217;;       <br />&#160;&#160;&#160;&#160;&#160; } else if ($response-&gt;status == Auth_OpenID_FAILURE) {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; $this-&gt;view-&gt;error = &quot;OpenID authentication failed: &quot;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; . $response-&gt;message;       <br />&#160;&#160;&#160;&#160;&#160; } else if ($response-&gt;status == Auth_OpenID_SUCCESS) {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; $this-&gt;view-&gt;error =&#160; &quot;Success&quot;;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; $auth = Zend_Auth::getInstance();       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; $adapter = new Application_Model_Account_OpenIDAdapter($response-&gt;identity_url);       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; $result = $auth-&gt;authenticate($adapter);       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; if ($result-&gt;isValid()) {       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; $this-&gt;_redirect(&#8217;/');       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return;       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160;&#160;&#160; }       <br />&#160;&#160;&#160; $this-&gt;_redirect(&#8217;/account/index&#8217;);       <br />&#160; }       </p>
<p>&#160; private function getScheme()&#160; <br />&#160; {       <br />&#160;&#160;&#160; $scheme = &#8216;http&#8217;;       <br />&#160;&#160;&#160; if (isset($_SERVER['HTTPS']) and $_SERVER['HTTPS'] == &#8216;on&#8217;) {       <br />&#160;&#160;&#160;&#160;&#160; $scheme .= &#8217;s&#8217;;       <br />&#160;&#160;&#160; }       <br />&#160;&#160;&#160; return $scheme;       <br />&#160; }       </p>
<p>&#160; private function getReturnTo()&#160; <br />&#160; {       <br />&#160;&#160;&#160; return sprintf(&quot;%s://%s/openid/finish&quot;,       <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; $this-&gt;getScheme(), $_SERVER['SERVER_NAME']);       <br />&#160; }       </p>
<p>&#160; private function getTrustRoot()&#160; <br />&#160; {       <br />&#160;&#160;&#160; return sprintf(&quot;%s://%s/&quot;, $this-&gt;getScheme(),       <br />&#160;&#160;&#160;&#160;&#160; $_SERVER['SERVER_NAME']);       <br />&#160; }&#160;&#160; <br />&#160;&#160; <br />}       </p>
<p></span></code>
<p>The code starts with /openid/try action. It communicates with OpenID provider to obtain a URL that user will be redirected to. It also set the callback to /openid/finish. Note that I created class Application_Model_Account_OpenIDAdapter so that it fits Zend_Auth architecture. In reality, all it does is to write information to user account database and persist it to a storage in choice (such as session or cookie).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.barcodeschool.com/2011/12/using-janrain-openid-with-zend-framework/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Overdesign case in Web UI</title>
		<link>http://www.barcodeschool.com/2011/12/overdesign-case-in-web-ui/</link>
		<comments>http://www.barcodeschool.com/2011/12/overdesign-case-in-web-ui/#comments</comments>
		<pubDate>Sun, 11 Dec 2011 02:03:27 +0000</pubDate>
		<dc:creator>Sherwood Hu</dc:creator>
		
		<category><![CDATA[Programming]]></category>

		<category><![CDATA[Web UI]]></category>

		<guid isPermaLink="false">http://www.barcodeschool.com/?p=291</guid>
		<description><![CDATA[Today I went to a site that displays information on domains. I wanted to look at how we are doing so I entered Morovia in the search box. Quickly surprisingly I received a message
Morovia is an Invalid Extension.
difficult to understand uuuh? Obviously you have to put your full domain name - in this case, morovia.com. [...]]]></description>
			<content:encoded><![CDATA[<p>Today I went to a site that displays information on domains. I wanted to look at how we are doing so I entered Morovia in the search box. Quickly surprisingly I received a message</p>
<blockquote><p>Morovia is an Invalid Extension.</p></blockquote>
<p>difficult to understand uuuh? Obviously you have to put your full domain name - in this case, morovia.com. Otherwise it thinks morovia is the top domain name. But even so, why it is called &#8220;extension&#8221;? File names have extensions; while domain names have <strong>suffixes</strong>. </p>
<p><img src="http://www.barcodeschool.com/wp-content/uploads/2011/12/error-invalid-extension-search-domain.png" alt="error-invalid-extension-search-domain" title="error-invalid-extension-search-domain" width="798" height="287" class="aligncenter size-full wp-image-292" /></p>
]]></content:encoded>
			<wfw:commentRss>http://www.barcodeschool.com/2011/12/overdesign-case-in-web-ui/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Useful QR Code Ideas for Small Business Marketing</title>
		<link>http://www.barcodeschool.com/2011/12/useful-qr-code-ideas-for-small-business-marketing/</link>
		<comments>http://www.barcodeschool.com/2011/12/useful-qr-code-ideas-for-small-business-marketing/#comments</comments>
		<pubDate>Fri, 09 Dec 2011 21:10:54 +0000</pubDate>
		<dc:creator>admin</dc:creator>
		
		<category><![CDATA[Barcode Formats]]></category>

		<category><![CDATA[Marketing]]></category>

		<category><![CDATA[QR Code]]></category>

		<category><![CDATA[Small Business]]></category>

		<guid isPermaLink="false">http://www.barcodeschool.com/?p=285</guid>
		<description><![CDATA[Nowadays smart phones are cheap. Android powered phones are around 100 dollars. It is not surprising that majority people now have smart phones - those with touch screen and have far more power than their predecessors. This phenomenon brings business opportunities that you as a business owner want to tap.
So what is QR Code?
A QR [...]]]></description>
			<content:encoded><![CDATA[<p>Nowadays smart phones are cheap. Android powered phones are around 100 dollars. It is not surprising that majority people now have smart phones - those with touch screen and have far more power than their predecessors. This phenomenon brings business opportunities that you as a business owner want to tap.</p>
<p><div id="attachment_289" class="wp-caption alignnone" style="width: 158px"><img src="http://www.barcodeschool.com/wp-content/uploads/2011/12/qrcode-mecard-format.png" alt="QR Code Image" title="qrcode-mecard-format" width="148" height="148" class="size-full wp-image-289" /><p class="wp-caption-text">QR Code Image</p></div><br />
So what is QR Code?</p>
<p>A QR Code is a 2D barcode that can be scanned by smart phone&#8217;s camera. It is capable of encoding large amount of text; however most QR codes encode a few dozen characters. QR Code becomes increasingly popular because smart phones now have decoder programs that read the barcode and act on the content it reads.</p>
<p>So what is the big deal for that? It turns out that QR Code offers a convenient way to encode key information - such as your web site address, email and so on. A smart phone owner can capture the info to his phone by just scanning the QR Code.</p>
<p>You certainly want your web site gets more visits - but how? If you run a restaurant, you can print a QR Code at the bottom of receipt, or in news paper&#8230; people who are interest just scan the QR code and visit your web site.</p>
<p>Some more ideas:</p>
<p>1. <strong>QR Code on Business Card</strong>. There is a popular format called MECARD, which allows contact info to be encoded into a QR Code. A smart phone user scans the barcode and put your contact into his address book. Hey if you are in  real estate agent, insurance broker or industry that you&#8217;d like everyone to remember you,  QR Code is a must.</p>
<p>2. <strong>Product Label</strong>. If you are a manufacturer it is time to add a QR Code with your web site encoded on the product label. Customers who bought your stuff may scan the barcode and visit your web site. Even more, you can print something like - scan this QR code to get a 10% off coupon.</p>
<p>3. <strong>Promotions, Discounts and Coupons.</strong> The idea here is to get the user to visit your web site and receive the discount. If you just print a coupon barcode on the newspaper your web site won&#8217;t get visited.  It is also easier to track users through your web site.</p>
<p>4. <strong>E-commerce</strong>.  QR Code encodes a URL with extra parameters - and users can only see them when they scan the barcode. So you can easily offer different discounts to different audience.</p>
<p>QR code can encode many information: such as web site URL, E-mail address and contact info. This <a href="http://www.morovia.com/fonts/qrcode/common-usage-qrcode.html" target="_blank">Morovia page </a>lists the common usage in mobile industry. Even better, there is an <a href="http://www.morovia.com/free-online-barcode-generator/qrcode-maker.php">online QR code generator</a> that create QR codes for free.</p>
<p>If you are looking a solution to add QR Code to Word documents, we&#8217;d like to recommend Morovia&#8217;s excellent product <a href="http://www.morovia.com/fonts/qrcode/">QR Code Fonts &amp; Encoder 5</a>.  With this <a href="http://mdn.morovia.com/manuals/qrcode-font-encoder/chapter-word-add-in.php">word addin</a>, creating a QRcode just takes two steps - highlight and convert; all can be done in 1 minute.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.barcodeschool.com/2011/12/useful-qr-code-ideas-for-small-business-marketing/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Creating Barcodes in Memory with PHP</title>
		<link>http://www.barcodeschool.com/2011/08/creating-barcodes-in-memory-with-php/</link>
		<comments>http://www.barcodeschool.com/2011/08/creating-barcodes-in-memory-with-php/#comments</comments>
		<pubDate>Tue, 30 Aug 2011 02:23:12 +0000</pubDate>
		<dc:creator>Sherwood Hu</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[Barcode ActiveX]]></category>

		<category><![CDATA[PHP]]></category>

		<category><![CDATA[PHP Barcode]]></category>

		<guid isPermaLink="false">http://www.barcodeschool.com/?p=272</guid>
		<description><![CDATA[Barcode image generation in memory using Barcode ActiveX, in PHP5.]]></description>
			<content:encoded><![CDATA[<p>Morovia <a href="http://mdn.morovia.com/kb/Tutorial-Barcode-ActiveX-Generate-Barcodes-PHP-Web-Applications-10148.html">KB 10148</a> talks about how to use Barcode ActiveX to generate barcode images in PHP 5. Barcode ActiveX 3 has a long history in Morovia, as it was conceived in year 2003 and our first ActiveX control product.</p>
<p>In this article, barcode is generated first in a front end script and the image is saved to a disk file. In the backend script the image is loaded and sent to the browser. Sometimes an in-memory solution is preferred, as programers will not have to deal with file permission, clean up and possible privacy issues.</p>
<p>The classic ASP example, which is included in the installer package, is an in-memory solution. It utilizes ADODB.Stream object. It exports barcode images to ADODB.Stream object, then calls Response.BinaryWrite to write all the bytes out. While it looks simple, the ADODB.Stream object&#8217;s Read method does not give back a sequence of bytes as defined in PHP. It is actually a COM SafeArray packaged in VARIANT type.</p>
<p><code>try {<br />
$objBarcode = new COM("Morovia.BarcodeActiveX");<br />
$objBarcode-&gt;RasterImageResolution = 96;								//Set the resolution to 96 dpi (screen)<br />
$objBarcode-&gt;NarrowBarWidth        = 15;                               //Default NarrowBarWidth 15 mils<br />
$objBarcode-&gt;BorderStyle = 0;											//No border<br />
$objBarcode-&gt;ShowComment = false;										//No comment<br />
$objBarcode-&gt;ShowHRText = false;										//No human readable text<br />
// By default the Barcode ActiveX creates margins around the symbol. The margins are around 100 mils<br />
// You can increase or decrease the margins by setting 4 SymbolMargin properties like<br />
$objBarcode-&gt;SymbolMarginTop = 100;</code></p>
<p><code>// Retrieve input parameters through the URL query string<br />
$objBarcode-&gt;Rotation   = $_GET["rotation"];<br />
$objBarcode-&gt;ShowHRText = (strlen($_GET["showhrtext"])==0 || $_GET['showhrtext']==0) ? 0 : 1;<br />
$objBarcode-&gt;Symbology = $_GET["symbology"];<br />
$objBarcode-&gt;NarrowBarWidth = $_GET['narrowbarwidth'];</code></p>
<p><code>$objBarcode-&gt;BarHeight            = $_GET['barheight'];<br />
$objBarcode-&gt;Message              = $_GET['message'];</p>
<p>$objBarcode-&gt;Font-&gt;Name = &#8220;MRV OCRB I&#8221;;<br />
$objBarcode-&gt;Font-&gt;Bold = false;<br />
$objBarcode-&gt;ShowComment = false;</p>
<p>// The Stream object is available in MDAC 2.5 and above versions. You can download the most<br />
// recent MDAC at http://www.microsoft.com/data/mdac/<br />
$objStream = new COM(&#8221;ADODB.Stream&#8221;);<br />
$objStream-&gt;Open();<br />
$objStream-&gt;Type = adTypeBinary;</p>
<p>// Export the Image to Stream object.<br />
// After transfer completes, the Position must set to 0 before Calling Response.BinaryWrite<br />
// otherwise an &#8220;unknown type&#8221; is reported.<br />
$objBarcode-&gt;ExportImage($objStream, imgTypePNG);</p>
<p>// BinaryWrite the image data to the client browser, in PHP use echo<br />
$objStream-&gt;Position = 0;</p>
<p>// until we figured out how to convert a byte array in COM to PHP,<br />
// we have to save it to a file first, then read it back to PHP.<br />
header(&#8217;Content-Type: image/png&#8217;);<br />
$buffer = $objStream-&gt;Read();</p>
<p>// Note: this does not work!<br />
echo($buffer);</p>
<p></code></p>
<p><code> $objStream  = null;<br />
$objBarcode = null;<br />
} catch(Exception $ex) {<br />
header('Content-Type: text/plain');<br />
echo($ex-&gt;getMessage());<br />
}</code></p>
<p>It turns out that the solution is pretty simple - although PHP does not provide direct way to convert a COM safe array to string, it provides a way to iterate the content. Thus, we can write:</p>
<p><code><br />
foreach ($buffer as $byte) echo chr($byte);<br />
</code></p>
<p>In the place of echo($buffer) statement. It worked.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.barcodeschool.com/2011/08/creating-barcodes-in-memory-with-php/feed/</wfw:commentRss>
		</item>
		<item>
		<title>IDispatch::Invoke Arguments are passed in reverse order</title>
		<link>http://www.barcodeschool.com/2011/03/idispatchinvoke-arguments-are-passed-in-reverse-order/</link>
		<comments>http://www.barcodeschool.com/2011/03/idispatchinvoke-arguments-are-passed-in-reverse-order/#comments</comments>
		<pubDate>Tue, 29 Mar 2011 18:54:44 +0000</pubDate>
		<dc:creator>Sherwood Hu</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.barcodeschool.com/2011/03/idispatchinvoke-arguments-are-passed-in-reverse-order/</guid>
		<description><![CDATA[Today I am testing the IDispatch of a COM object. The method has the following fingerprint:
[id(6)] HRESULT DataMatrixEncodeSet(   &#160;&#160;&#160;&#160;&#160;&#160;&#160; [in] BSTR strDateToEncode,    &#160;&#160;&#160;&#160;&#160;&#160;&#160; [in] LONG sizeID,     &#160;&#160;&#160;&#160;&#160;&#160;&#160; [out,retval] LONG* chunks);    
I was quite surprise that I got an “type mistach” error from Invoke [...]]]></description>
			<content:encoded><![CDATA[<p>Today I am testing the IDispatch of a COM object. The method has the following fingerprint:</p>
<p>[id(6)] HRESULT DataMatrixEncodeSet(   <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; [in] BSTR strDateToEncode,    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; [in] LONG sizeID,     <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; [out,retval] LONG* chunks);    </p>
<p>I was quite surprise that I got an “type mistach” error from Invoke function. My code is as below:</p>
<p>args[0].vt = VT_BSTR;   <br />args[0].bstrVal = SysAllocString(L&quot;this is data to encodeencodeencodeencodeencode&quot;);    <br />args[1].vt = VT_I4;    <br />args[1].lVal = 0;</p>
<p>dp.cArgs&#160; = 2;&#160;&#160;&#160; <br />dp.rgvarg = args;&#160;&#160;&#160; <br />dp.cNamedArgs = 0;&#160;&#160;&#160; <br />dp.rgdispidNamedArgs = NULL; </p>
<p>VARIANT vaRet;   <br />VariantClear(&amp;vaRet);    <br />EXCEPINFO&#160; exInfo;    <br />unsigned int uErr;    <br />hr = disp-&gt;Invoke(dispID[0], IID_NULL, LCID_NEUTRAL,    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; DISPATCH_METHOD, &amp;dp, &amp;vaRet, &amp;exInfo, &amp;uErr);    <br />BOOST_CHECK(SUCCEEDED(hr));    </p>
<p>After some search, I finally found the cause: the arguments packed in DISPPARAMS must be in reverse order. In other words, the args[] array must be reversed. After I changed that, the error disappeared.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.barcodeschool.com/2011/03/idispatchinvoke-arguments-are-passed-in-reverse-order/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Bulk generate barcode images using Barcode ActiveX and Perl</title>
		<link>http://www.barcodeschool.com/2011/02/bulk-generate-barcode-images-using-barcode-activex-and-perl/</link>
		<comments>http://www.barcodeschool.com/2011/02/bulk-generate-barcode-images-using-barcode-activex-and-perl/#comments</comments>
		<pubDate>Tue, 01 Mar 2011 04:23:43 +0000</pubDate>
		<dc:creator>Sherwood Hu</dc:creator>
		
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.barcodeschool.com/?p=266</guid>
		<description><![CDATA[How to bulk generate upc-a images]]></description>
			<content:encoded><![CDATA[<p>With <a href="http://www.morovia.com/activex/barcode-activex.asp">Morovia Barcode ActiveX 3</a>, it is easy to bulk generate barcode images. The following 10 lines of perl code just demonstrate how easy it is.</p>
<p>use Win32::OLE;<br />
my $object = Win32::OLE-&gt;new(&#8217;Morovia.BarcodeActivex&#8217;, &#8221;);<br />
$object-&gt;{&#8221;Symbology&#8221;} = 8; #UPC-A symbology<br />
$object-&gt;{&#8221;ShowComment&#8221;} = 0;<br />
$object-&gt;{&#8221;BarHeight&#8221;}=1000;</p>
<p>for(my $number=0; $number&lt;=999; $number++)<br />
{<br />
my $text_number = sprintf(&#8221;%03d&#8221;, $number);<br />
$object-&gt;{&#8221;message&#8221;} = &#8220;81058201&#8243; . $text_number;</p>
<p>print(&#8221;exporting image $text_number.\n&#8221;);</p>
<p>$object-&gt;ExportImage($object-&gt;{&#8221;message&#8221;} . &#8220;.jpg&#8221;, 1);<br />
}</p>
<p>my $result = `zip all-images.zip *.jpg`;</p>
<p>The code above generates UPC-A barcode images for numbers 81058201xxx where xxx is from 000 to 999. At the end, the code calls zip command to zip all the images files into zip.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.barcodeschool.com/2011/02/bulk-generate-barcode-images-using-barcode-activex-and-perl/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Display Developer Tab in Word 2007/2010</title>
		<link>http://www.barcodeschool.com/2011/01/display-developer-tab-in-word-20072010/</link>
		<comments>http://www.barcodeschool.com/2011/01/display-developer-tab-in-word-20072010/#comments</comments>
		<pubDate>Tue, 25 Jan 2011 14:49:48 +0000</pubDate>
		<dc:creator>admin</dc:creator>
		
		<category><![CDATA[Barcode Formats]]></category>

		<category><![CDATA[Barcode ActiveX]]></category>

		<category><![CDATA[Developer Tab]]></category>

		<category><![CDATA[Word 2007]]></category>

		<guid isPermaLink="false">http://www.barcodeschool.com/?p=263</guid>
		<description><![CDATA[Developer tab is by default disabled in Word 2007. How to display it to enable advanced functionality.]]></description>
			<content:encoded><![CDATA[<p>In default installation the <strong>Developer</strong> tab is disabled. This tab is required to access programmability, such as macro and ActiveX control. If you need to insert <a title="Morovia Barcode ActiveX" href="http://www.morovia.com/activex/barcode-activex.asp" target="_blank">Barcode ActiveX</a> into a word document, you need to enable this tab first.</p>
<p>Follow the steps below to enable the <strong>Developer</strong> tab:</p>
<ol>
<li>Click the Microsoft Office button.</li>
<li>Choose Word options.</li>
<li>Select Popular (at the top left).</li>
<li>Check <strong>Show Developer tab in the Ribbon</strong>.</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://www.barcodeschool.com/2011/01/display-developer-tab-in-word-20072010/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Programmatically Collect and Analyze VSTS Code Coverage Data</title>
		<link>http://www.barcodeschool.com/2010/12/programmatically-collect-and-analyze-vsts-code-coverage-data/</link>
		<comments>http://www.barcodeschool.com/2010/12/programmatically-collect-and-analyze-vsts-code-coverage-data/#comments</comments>
		<pubDate>Tue, 28 Dec 2010 18:01:00 +0000</pubDate>
		<dc:creator>Sherwood Hu</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.barcodeschool.com/2010/12/programmatically-collect-and-analyze-vsts-code-coverage-data/</guid>
		<description><![CDATA[Visual Studio 2005 and later versions have code coverage feature built-in – only available in team edition. However a standalone profile is available to download from Microsoft site. Code coverage is a great help for programmer’s confidence on the code. It is not possible to test all possible execution path- however, if a test executes [...]]]></description>
			<content:encoded><![CDATA[<p>Visual Studio 2005 and later versions have code coverage feature built-in – only available in team edition. However a standalone profile is available to download from Microsoft site. Code coverage is a great help for programmer’s confidence on the code. It is not possible to test all possible execution path- however, if a test executes 90% code lines, the chance of bugs becomes quite small.</p>
<p>Our project utilizes a different process, which can’t be managed entirely with GUI. To begin with, we manage our unit tests with <strong>boost.test</strong>, with each test file built into an executable file. In large projects we have hundreds of test files, and managing them through GUI interface is quite formidable. </p>
<p>Another issue is the frustration with displaying metrics. The interface provided is quite clunky, and you have to navigate thousands of functions and class methods in order to find coverage for the method you are focusing. The color display in the editor has a lot for improvement. </p>
<p>I recently investigated possibilities to collect and analyze code coverage data programmatically. It was a success. I noticed that the documentation on this aspect is quite weak, so I’d like to share some points with readers. </p>
<h2>Collecting Data</h2>
<p>In order for the code coverage to be collected, the executable must be instrumented. Some web pages I found like <a href="http://blogs.msdn.com/b/cellfish/archive/2008/11/16/native-c-code-coverage-reports-using-visual-studio-2008-team-system.aspx">this</a> state that link flag –PROFILE is required, while others not mentioning this requirement. In our build system, this link flag triggers the instrumentation. The build system we are using is boost.build, we changed the file msvc.jam slightly to launch instrumentation process once &lt;linkflags&gt;-PROFILE is passed.</p>
<p>Visual Studio documentation calls those related tools “Performance Tools” and they are located at <tt>C:\Program Files\Microsoft Visual Studio [Version]\Team Tools\Performance Tools</tt> directory. It is recommended to add this path into PATH variable in vcvars.bat so that you gain the access to the command after entering command prompt. </p>
<p>To instrument the executable, run the command:</p>
<p>vsinstr.exe &lt;YOUR_EXE&gt; /COVERAGE</p>
<p>As I stated, this process is added into our build system automatically – if &lt;linkflags&gt;-PROFILE is found, the executable will be instrumented.</p>
<p>Now the second step is to collect data. To collect data you first start vsperfmon process. Because you can run multiple executables in one session, this step is now carried out manually:</p>
<p>start VSPerfMon /COVERAGE /OUTPUT:&lt;REPORT_FILE_NAME&gt;</p>
<p>Here we use start&#160; command to open a separate console, because execution will block the current console. </p>
<p>Now run the tests. Code coverage data will be collected.</p>
<p>After we have done testing, shut down the vsperfmon process:</p>
<p>vsperfcmd –shutdown</p>
<p>After this command is carried out, the coverage data is stored in the file we specified. The coverage file is in a proprietary format with no documentation about its structure. Fortunately, MS allows us to export using Visual Studio or calling code analysis API.</p>
<h2>Converting to XML</h2>
<p>You can drop the coverage file newly created into Visual Studio. You can not do much with its interface, as you have to navigate many functions to locate the ones you wanted to view. Furthermore, it does not code coverage ratio on source file basis, but rather on method basis.</p>
<p>You can export the XML file from Visual Studio, or use the code I provided below to export programmatically.&#160; Oddly the two give different results – the one exported from Visual Studio is encoded in UTF-16 and with no line endings – I spent a quite a bit time to convert it into a UTF-8 with line endings so that my favorite editor can open it. It looks to me that Visual Studio uses a different method to export, and it might be written in native C++.</p>
<p>The programmatic way that Microsoft wants us to use is through assembly. There are several MSDN blogs on this topic; unfortunately the one I found contain two errors: it failed to point out that symbol path must be set, and the WriteXML call was wrong. I posted my code below:</p>
<p>using System;   <br />using System.Collections.Generic;    <br />using System.Text;    <br />using Microsoft.VisualStudio.CodeCoverage;</p>
<p>namespace coverdump   <br />{    <br />&#160;&#160;&#160; class Program    <br />&#160;&#160;&#160; {    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; static void Main(string[] args)    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; {    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (args.Length != 3)    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Console.WriteLine(&quot;Usage: coverdump coverage xml symbolpath&quot;);    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return;    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; String coveragepath = args[2];   <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; CoverageInfoManager.SymPath = coveragepath;    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; CoverageInfoManager.ExePath = coveragepath;</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; // Create a coverage info object from the file   <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; CoverageInfo ci = CoverageInfoManager.CreateInfoFromFile(args[0]);</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; // Ask for the DataSet.&#160; The parameter must be null   <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; CoverageDS data = ci.BuildDataSet(null);</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; // Write to XML   <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; data.WriteXml(args[1]);    <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; }    <br />&#160;&#160;&#160; }    <br />}</p>
<p>I had to overcome some issues not mentioned elsewhere. The first issue is references. You must add reference to two files: Microsoft.VisualStudio.Coverage.Analysis.dll and Microsoft.DbgHelp.manifest. Both are located under C:\Program Files\Microsoft Visual Studio [Version]\Common7\IDE\PrivateAssemblies. When I first ran the code, it complained that the assembly does not match the one requested, and I found that the file Microsoft.DbgHelp.manifest does not match dbghelp.dll. I do not know if the initially not match, or just because a subsequent update. Anyway I have to update the version number as well as remove publicKey attribute in order for the program to run properly. </p>
<p>The third argument is the symbol path and executable path. You can specify multiple paths separated by semicolon. If you work with Visual Studio 2010, the interface changed a little bit as the property SymPath and ExePath are now string arrays. </p>
<p>It is a little bit odd to ask for symbol path, considering that the fact that Visual Studio does not ask for it when loading a coverage file. In other words, the coverage file must contain the path to EXE (and PDB file name can be found in EXE for debug build). </p>
<h2>Analyzing Data</h2>
<p>PHP is my favorite script language, and I use it to analyze the data. As the first step, my goal is display the code coverage ratio for each source file specified at command line, also produce a code diff that our programmers can view subsequently. This is much better than what we did previously – programmers have to navigate thousands of methods before they can locate useful information. From project management perspective, now we are able to view code coverage ratio on source file basis.</p>
<p>The resulted XML file can be very big – or even huge. The first one I got was 200MBytes out of a mere 15M coverage file. If you load all the file into memory the process can take quite a while. In light of this issue, I choose XMLReader class to read the file – XMLReader reads XML file as a stream. I read all &lt;Method&gt; elements as well as all &lt;SourceFiles&gt; elements. </p>
<p>In order for programmers to view the difference, my script creates another file based on line coverage data. If the code is not covered, it writes a blank line into the file. After all lines are written, the script calls diff –u 100 to produce a diff file between the original and the new source file. The option –u 100 tells the diff to display 100 lines context, which basically produces a diff file containing all original source lines. </p>
<p>In the future we might expand the script to do more reporting. XSLT is an interesting option here. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.barcodeschool.com/2010/12/programmatically-collect-and-analyze-vsts-code-coverage-data/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Pitfalls of applying const in C++</title>
		<link>http://www.barcodeschool.com/2010/12/pitfalls-of-applying-const-in-c/</link>
		<comments>http://www.barcodeschool.com/2010/12/pitfalls-of-applying-const-in-c/#comments</comments>
		<pubDate>Thu, 02 Dec 2010 16:31:08 +0000</pubDate>
		<dc:creator>Sherwood Hu</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[C++ Programming]]></category>

		<guid isPermaLink="false">http://www.barcodeschool.com/2010/12/pitfalls-of-applying-const-in-c/</guid>
		<description><![CDATA[One annoyance aspect as a programmer is having to to know the sublets of the language. Many features are great on paper, however, you run into trouble immediately if you do not understand the possible issue associated.
Many C++ programmers are now familiar with keyboard const. They want to apply the keyword anywhere if they see [...]]]></description>
			<content:encoded><![CDATA[<p>One annoyance aspect as a programmer is having to to know the sublets of the language. Many features are great on paper, however, you run into trouble immediately if you do not understand the possible issue associated.</p>
<p>Many C++ programmers are now familiar with keyboard <strong>const</strong>. They want to apply the keyword anywhere if they see fit. They argue that const keyword adds a lot more constraints that help discover bugs by compilers, and itself also help compiler to optimize the code for better performance.</p>
<p>Let’s start with a simple example:<br />
<code>class IRule<br />
{<br />
public:<br />
   virtual const char* getName() const = 0;<br />
};</code><br />
The above is an abstract class, which defines the methods that all derived classes must implement. The method returns a const pointer, which means that the caller can’t change the content that the pointer points to. The const at the end indicates that the implement should not change the object state, a.k.a. const this pointer.</p>
<p>All went well and you wrote a dozen derived classes that inherits IRule. A couple of months later you have to implement another one, and this time, the situation is a little bit different. You have to obtain the name from a remote server, and for performance reason, you can only do so at the first time it called. You write this:<br />
<code>class myRemoteRule : public IRule<br />
{<br />
public:<br />
  myRemoteRule(const char* serverA);<br />
  virtual const char* Name(void) const;<br />
private:<br />
  std::string strName;<br />
  std::string serverAddr;<br />
};</code><br />
<code><br />
const char* myRemoteRule::Name(void) const<br />
{<br />
  if (strName.empty()) {<br />
    strName = getNameFromRemote(serverAddr);<br />
  }<br />
  return strName.c_str();<br />
}</code><br />
Cool. How the above code does not compile. The compiler complains that you can’t declare the method as const as the data member strName, is modified in it.   Now bad. Either you have to find a workaround, or just go change all declaration of this method, which can take a while. Luckily, C++ allows us to cast the const off using const_cast, so the following code compiles:<br />
<code>const char* myRemoteRule::Name(void) const<br />
{<br />
  if (strName.empty()) {<br />
    const_cast&lt;myRemoteRule*&gt;(this)-&gt;strName = getNameFromRemote(serverAddr);<br />
  }<br />
  return strName.c_str();<br />
}</code><br />
Let’s look at the real case – the example above is just too trivial. In reality, a class may have several dozen methods and data members. It is difficult to predict whether we may run into such situation when we wrote the interface prototype. We may well end up with writing a lot of const_cast in the place, further glutting the code.</p>
<p>The morale of the story is that in real world programming is not easy. Simply applying const on a seemingly const construct may be an over constraint and hurts the coding.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.barcodeschool.com/2010/12/pitfalls-of-applying-const-in-c/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Publishers, Fix the MetaData of PDF file</title>
		<link>http://www.barcodeschool.com/2010/09/publishers-fix-the-metadata-in-the-pdf-file/</link>
		<comments>http://www.barcodeschool.com/2010/09/publishers-fix-the-metadata-in-the-pdf-file/#comments</comments>
		<pubDate>Wed, 15 Sep 2010 18:19:50 +0000</pubDate>
		<dc:creator>Sherwood Hu</dc:creator>
		
		<category><![CDATA[PDF Software]]></category>

		<category><![CDATA[PDF metadata]]></category>

		<category><![CDATA[pdfleo]]></category>

		<category><![CDATA[Publisher]]></category>

		<category><![CDATA[Title]]></category>

		<guid isPermaLink="false">http://www.barcodeschool.com/?p=222</guid>
		<description><![CDATA[I recently bought a Nook. Originally I did not expect much, and consider only to read ebooks in .epub format. To my surprise, it also reads PDF. It displays PDF in a different way than what people imagine - it retrieves the text and graph, and reflows the paragraphs. I am impressed. It has some [...]]]></description>
			<content:encoded><![CDATA[<p>I recently bought a Nook. Originally I did not expect much, and consider only to read ebooks in .epub format. To my surprise, it also reads PDF. It displays PDF in a different way than what people imagine - it retrieves the text and graph, and reflows the paragraphs. I am impressed. It has some flaws, especially in dealing with tables,  and program code, but good enough for me to read PDFs with heavy text.</p>
<p>After I loaded several PDF files into Nook, I found that some books are shown &#8220;Unknown Author&#8221; and strange titles in &#8220;My Documents&#8221; directory, which lists all ebooks. The title and author information are taken from the PDF metadata, and obviously the software some publishers used did not set them properly.</p>
<p><div id="attachment_243" class="wp-caption aligncenter" style="width: 410px"><img class="size-full wp-image-243" title="Nook Unknown Author" src="http://www.barcodeschool.com/wp-content/uploads/2010/09/nook-unknown-author.jpg" alt="Nook Unknown Author" width="400"  /><p class="wp-caption-text">Nook Document List</p></div></p>
<p>For example, the book &#8220;the Facebook Era&#8221; written by Clara Shih, shows <em>013715318X.pdf</em> as title and <em>Unknown Author</em> as Author.</p>
<p>With the help of <a href="http://rockpdf.com">PDFLeo</a>, released by <a href="http://rockpdf.com">rockpdf.com</a>, I am able to determine the cause: incorrect metadata. The following is the output:</p>
<p><code>J:\My Documents&gt;pdfleo -i facebook.pdf<br />
Morovia (R) pdfleo Server 32-bit Version 1.0 (build 4162)<br />
File: facebook.pdf<br />
Title: 013715318X.pdf<br />
Author:<br />
Subject:<br />
Keywords:<br />
Created: 03/24/2009 03:49:24 PM<br />
Modified: 02/02/2010 08:20:45 PM<br />
Application: Acrobat: pictwpstops filter 1.0<br />
PDF Producer: PDFKit.NET 2.0.28.0<br />
PDF Version: 1.6 (Acrobat 7.x)<br />
Number of Pages: 254<br />
Tagged PDF: No<br />
Linearized: No<br />
Page Size: 6.01x9.25 in<br />
....</code></p>
<p>The software used the book&#8217;s ISBN as title, and set empty string to Author (If the field does not exist in the file, <strong>PDFLeo</strong>l displays <strong>N/A</strong>). It is more obvious when you look inside the file:<img class="size-full wp-image-225" title="incorrect-metadata-fields-pdf" src="http://www.barcodeschool.com/wp-content/uploads/2010/09/incorrect-metadata-fields-pdf.png" alt="Incorrect MetaData Fields" width="837" height="113" /></p>
<p>Metadata fields can also be viewed in Adobe Reader:</p>
<p><img class="aligncenter size-full wp-image-226" src="http://www.barcodeschool.com/wp-content/uploads/2010/09/incorrect-metadata-reader.png" alt="" width="612" height="644" /></p>
<p>After pinpointing the problem, now it comes to fix. We need to set metadata to the PDF file so that the title and author display correctly in Nook (or Kindle, SONY reader etc.). Fortunately, PDFLeo is capable of modifying metdata with <em>&#8211;info-dict</em> switch.</p>
<p><code><br />
J:\My Documents&gt;pdfleo --info-dict="Title=The Facebook Era;Author=Clara Shih" facebook.pdf facebook.new.pdf<br />
</code><br />
Now the new file has the metadata corrected, which can be verified by loading the file in Adobe Reader:</p>
<p><img class="aligncenter size-full wp-image-229" title="correct-metadata-pdf1" src="http://www.barcodeschool.com/wp-content/uploads/2010/09/correct-metadata-pdf1.png" alt="correct-metadata-pdf1" width="612" height="644" /></p>
<p>After overwriting the existing file, Nook shows the title and author correctly.</p>
<p>Although I can fix one by one, I certainly hope that publishers can get the things correct at the first step.  Here is my call - publishers, check your metadata before shipping the PDF version! You can use the PDFLeo tool for that purpose.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.barcodeschool.com/2010/09/publishers-fix-the-metadata-in-the-pdf-file/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>

