plupload v.1.4.3.2 to fix html5 chrome upload issue

This commit is contained in:
Espen Antonsen 2011-08-05 14:40:12 +08:00
parent d8390da109
commit d0fa8d2c81
127 changed files with 344 additions and 19643 deletions

View file

@ -1,3 +1,27 @@
Version 1.4.3.2 (2011-04-13)
Fixed bug in HTML5 runtime, when was reduced by a factor of 100 after every upload.
Version 1.4.3.1 (2011-04-12)
Fixed build script, mistakenly populating jquery.plupload.queue directory from jquery.ui.plupload sources.
Fixed script urls in all examples, build script now will alter them automatically from dev to release when needed.
Fixed isEmptyObj undefined error in HTML4 runtime.
Fixed bug in UI Widget preventing UploadComplete from triggering.
Version 1.4.3 (2011-04-11)
Added Latvian language pack and updated French.
Fixed bug in Flash runtime when JPEG header was not investigated deep enough to reach SOFn marker in large images.
Fixed bug, when PNGs were cropped to width in Flash runtimes, rather then resized.
Fixed Flash to allow multiple uploading of the same file, with different settings.
Fixed Flash runtime to clean anonymous listeners properly.
Fixed HTML5 runtime to resolve to mimeType in case-insensitive way.
Fixed HTML5/Flash/SilverLight/Gears runtimes for inconsistency in naming of chunks feature, comparing to other runtimes.
Fixed HTML4/HTML5 runtimes for input[type=file] to outsize contaner effectively enough to fill the whole click area.
Fixed all runtimes to preserve position (relative/absolute) rule on containers that already have it.
Fixed SilverLight runtime to support large files (over 2GB).
Restructured the examples, src and build scripts to make it more clear that jQuery is optional.
Added support for *.* filter.
Added support for preserving ICC and IPTC headers when resizing JPEGs.
Added Image.onerror/onabort handlers to HTML5 in order to gracefully bypass faulty images.
Added ability to drop image size (by lowering quality), while preserving original dimension (HTML5/Flash/Gears).
Ported EXIF, ICC, IPTC preservation code to Flash runtime.
Version 1.4.2 (2011-02-20) Version 1.4.2 (2011-02-20)
Added Brazilian Portuguese, German, Russian and Spanish translations. Added Brazilian Portuguese, German, Russian and Spanish translations.
Added support for file_data_name option to SilverLight runtime. Added support for file_data_name option to SilverLight runtime.

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

View file

@ -2,28 +2,55 @@
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr"> <html xmlns="http://www.w3.org/1999/xhtml" dir="ltr">
<head> <head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/> <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<link rel="stylesheet" href="css/plupload.queue.css" type="text/css" media="screen" />
<title>Plupload - Queue widget example</title> <title>Plupload - Queue widget example</title>
<style type="text/css"> <style type="text/css">
body {background: #9A7C5F;} body {
font-family:Verdana, Geneva, sans-serif;
font-size:13px;
color:#333;
background:url(bg.jpg);
}
</style> </style>
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load("jquery", "1.3");
</script>
<script type="text/javascript" src="../js/gears_init.js"></script>
<script type="text/javascript" src="http://bp.yahooapis.com/2.4.21/browserplus-min.js"></script> <script type="text/javascript" src="http://bp.yahooapis.com/2.4.21/browserplus-min.js"></script>
<!-- Load source versions of the plupload script files -->
<script type="text/javascript" src="../src/javascript/plupload.js"></script> <script type="text/javascript" src="../js/plupload.js"></script>
<script type="text/javascript" src="../src/javascript/plupload.gears.js"></script> <script type="text/javascript" src="../js/plupload.gears.js"></script>
<script type="text/javascript" src="../src/javascript/plupload.silverlight.js"></script> <script type="text/javascript" src="../js/plupload.silverlight.js"></script>
<script type="text/javascript" src="../src/javascript/plupload.flash.js"></script> <script type="text/javascript" src="../js/plupload.flash.js"></script>
<script type="text/javascript" src="../src/javascript/plupload.browserplus.js"></script> <script type="text/javascript" src="../js/plupload.browserplus.js"></script>
<script type="text/javascript" src="../src/javascript/plupload.html5.js"></script> <script type="text/javascript" src="../js/plupload.html4.js"></script>
<script type="text/javascript" src="../src/javascript/jquery.plupload.queue.js"></script> <script type="text/javascript" src="../js/plupload.html5.js"></script>
<script>
<!-- <script type="text/javascript" src="http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js"></script> -->
</head>
<body>
<form id="submit-form" method="post" action="dump.php">
<h1>Custom example</h1>
<p>Shows you how to use the core plupload API.</p>
<div>
<div id="filelist">No runtime found.</div>
<br />
<a id="pickfiles" href="javascript:;">[Select files]</a>
<a id="uploadfiles" href="javascript:;">[Upload files]</a>
</div>
<input type="submit" />
</form>
<script type="text/javascript">
// Custom example logic // Custom example logic
$(function() { function $(id) {
return document.getElementById(id);
}
var uploader = new plupload.Uploader({ var uploader = new plupload.Uploader({
runtimes : 'gears,html5,flash,silverlight,browserplus', runtimes : 'gears,html5,flash,silverlight,browserplus',
browse_button : 'pickfiles', browse_button : 'pickfiles',
@ -39,53 +66,29 @@ $(function() {
}); });
uploader.bind('Init', function(up, params) { uploader.bind('Init', function(up, params) {
$('#filelist').html("<div>Current runtime: " + params.runtime + "</div>"); $('filelist').innerHTML = "<div>Current runtime: " + params.runtime + "</div>";
}); });
uploader.bind('FilesAdded', function(up, files) { uploader.bind('FilesAdded', function(up, files) {
$.each(files, function(i, file) { for (var i in files) {
$('#filelist').append( $('filelist').innerHTML += '<div id="' + files[i].id + '">' + files[i].name + ' (' + plupload.formatSize(files[i].size) + ') <b></b></div>';
'<div id="' + file.id + '">' + }
file.name + ' (' + plupload.formatSize(file.size) + ') <b></b>' +
'</div>');
});
}); });
uploader.bind('UploadFile', function(up, file) { uploader.bind('UploadFile', function(up, file) {
$('<input type="hidden" name="file-' + file.id + '" value="' + file.name + '" />') $('submit-form').innerHTML += '<input type="hidden" name="file-' + file.id + '" value="' + file.name + '" />';
.appendTo('#submit-form');
}); });
uploader.bind('UploadProgress', function(up, file) { uploader.bind('UploadProgress', function(up, file) {
$('#' + file.id + " b").html(file.percent + "%"); $(file.id).getElementsByTagName('b')[0].innerHTML = '<span>' + file.percent + "%</span>";
}); });
$('#uploadfiles').click(function(e) { $('uploadfiles').onclick = function() {
uploader.start(); uploader.start();
e.preventDefault(); return false;
}); };
uploader.init(); uploader.init();
});
</script> </script>
<!-- <script type="text/javascript" src="http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js"></script> -->
</head>
<body>
<form id="submit-form" method="post" action="dump.php">
<h1>Custom example</h1>
<p>Shows you how to use the core plupload API.</p>
<div>
<div id="filelist">No runtime found.</div>
<br />
<a id="pickfiles" href="#">[Select files]</a>
<a id="uploadfiles" href="#">[Upload files]</a>
</div>
<input type="submit" />
</form>
</body> </body>
</html> </html>

View file

@ -5,7 +5,12 @@
<link rel="stylesheet" href="css/plupload.css" type="text/css" media="screen" /> <link rel="stylesheet" href="css/plupload.css" type="text/css" media="screen" />
<title>Plupload - Form dump</title> <title>Plupload - Form dump</title>
<style type="text/css"> <style type="text/css">
body {background: #9A7C5F;} body {
font-family:Verdana, Geneva, sans-serif;
font-size:13px;
color:#333;
background:url(bg.jpg);
}
</style> </style>
</head> </head>
<body> <body>

View file

@ -2,20 +2,45 @@
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr"> <html xmlns="http://www.w3.org/1999/xhtml" dir="ltr">
<head> <head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/> <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<link rel="stylesheet" href="css/plupload.queue.css" type="text/css" media="screen" /> <link rel="stylesheet" href="../../js/jquery.plupload.queue/css/jquery.plupload.queue.css" type="text/css" media="screen" />
<title>Plupload - Events example</title> <title>Plupload - Events example</title>
<style type="text/css"> <style type="text/css">
body {background: #9A7C5F;} body {
font-family:Verdana, Geneva, sans-serif;
font-size:13px;
color:#333;
background:url(../bg.jpg);
}
</style> </style>
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript"> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>
google.load("jquery", "1.3");
</script>
<script type="text/javascript" src="../js/gears_init.js"></script>
<script type="text/javascript" src="http://bp.yahooapis.com/2.4.21/browserplus-min.js"></script> <script type="text/javascript" src="http://bp.yahooapis.com/2.4.21/browserplus-min.js"></script>
<script type="text/javascript" src="../js/plupload.full.min.js"></script>
<script type="text/javascript" src="../js/jquery.plupload.queue.min.js"></script> <script type="text/javascript" src="../../js/plupload.js"></script>
<script> <script type="text/javascript" src="../../js/plupload.gears.js"></script>
<script type="text/javascript" src="../../js/plupload.silverlight.js"></script>
<script type="text/javascript" src="../../js/plupload.flash.js"></script>
<script type="text/javascript" src="../../js/plupload.browserplus.js"></script>
<script type="text/javascript" src="../../js/plupload.html4.js"></script>
<script type="text/javascript" src="../../js/plupload.html5.js"></script>
<script type="text/javascript" src="../../js/jquery.plupload.queue/jquery.plupload.queue.js"></script>
</head>
<body>
<form method="post" action="dump.php">
<h1>Events example</h1>
<p>Shows how to bind and use all available events.</p>
<h3>Log messages</h3>
<textarea id="log" style="width: 100%; height: 150px; font-size: 11px" spellcheck="false" wrap="off"></textarea>
<h3>Queue widget</h3>
<div id="uploader" style="width: 450px; height: 330px;">You browser doesn't support upload.</div>
<a id="clear" href="#">Clear queue</a>
</form>
<script type="text/javascript">
$(function() { $(function() {
function log() { function log() {
var str = ""; var str = "";
@ -64,7 +89,7 @@ $(function() {
$("#uploader").pluploadQueue({ $("#uploader").pluploadQueue({
// General settings // General settings
runtimes: 'html5,gears,browserplus,silverlight,flash,html4', runtimes: 'html5,gears,browserplus,silverlight,flash,html4',
url: 'upload.php', url: '../upload.php',
max_file_size: '10mb', max_file_size: '10mb',
chunk_size: '1mb', chunk_size: '1mb',
unique_names: true, unique_names: true,
@ -79,8 +104,8 @@ $(function() {
], ],
// Flash/Silverlight paths // Flash/Silverlight paths
flash_swf_url: '../js/plupload.flash.swf', flash_swf_url: '../../js/plupload.flash.swf',
silverlight_xap_url: '../js/plupload.silverlight.xap', silverlight_xap_url: '../../js/plupload.silverlight.xap',
// PreInit events, bound before any internal events // PreInit events, bound before any internal events
preinit: { preinit: {
@ -167,21 +192,5 @@ $(function() {
}); });
}); });
</script> </script>
</head>
<body>
<form method="post" action="dump.php">
<h1>Events example</h1>
<p>Shows how to bind and use all available events.</p>
<h3>Log messages</h3>
<textarea id="log" style="width: 100%; height: 150px; font-size: 11px" spellcheck="false" wrap="off"></textarea>
<h3>Queue widget</h3>
<div id="uploader" style="width: 450px; height: 330px;">You browser doesn't support upload.</div>
<a id="clear" href="#">Clear queue</a>
</form>
</body> </body>
</html> </html>

View file

@ -3,28 +3,50 @@
<head> <head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/> <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<title>Plupload - Queue widget example</title> <title>Plupload - Queue widget example</title>
<!-- Load Queue widget CSS and jQuery --> <style type="text/css">
body {
font-family:Verdana, Geneva, sans-serif;
font-size:13px;
color:#333;
background:url(../bg.jpg);
}
</style>
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.9/themes/base/jquery-ui.css" type="text/css" /> <link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.9/themes/base/jquery-ui.css" type="text/css" />
<link rel="stylesheet" href="css/jquery.ui.plupload.css" type="text/css" /> <link rel="stylesheet" href="../../js/jquery.ui.plupload/css/jquery.ui.plupload.css" type="text/css" />
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js" type="text/javascript"></script> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.9/jquery-ui.min.js" type="text/javascript"></script> <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.9/jquery-ui.min.js"></script>
<!-- Thirdparty intialization scripts, needed for the Google Gears and BrowserPlus runtimes -->
<script type="text/javascript" src="../js/gears_init.js"></script>
<script type="text/javascript" src="http://bp.yahooapis.com/2.4.21/browserplus-min.js"></script> <script type="text/javascript" src="http://bp.yahooapis.com/2.4.21/browserplus-min.js"></script>
<script type="text/javascript" src="../js/plupload.full.min.js"></script> <script type="text/javascript" src="../../js/plupload.js"></script>
<script type="text/javascript" src="../js/jquery.ui.plupload.min.js"></script> <script type="text/javascript" src="../../js/plupload.gears.js"></script>
<!--<script type="text/javascript" src="http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js"></script>--> <script type="text/javascript" src="../../js/plupload.silverlight.js"></script>
<script type="text/javascript" src="../../js/plupload.flash.js"></script>
<script type="text/javascript" src="../../js/plupload.browserplus.js"></script>
<script type="text/javascript" src="../../js/plupload.html4.js"></script>
<script type="text/javascript" src="../../js/plupload.html5.js"></script>
<script type="text/javascript" src="../../js/jquery.ui.plupload/jquery.ui.plupload.js"></script>
<!--<script type="text/javascript" src="http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js"></script>-->
</head>
<body>
<h1>jQuery UI Widget</h1>
<p>You can see this example with different themes on the <a href="http://plupload.com/example_jquery_ui.php">www.plupload.com</a> website.</p>
<form method="post" action="dump.php">
<div id="uploader">
<p>You browser doesn't have Flash, Silverlight, Gears, BrowserPlus or HTML5 support.</p>
</div>
</form>
<script type="text/javascript"> <script type="text/javascript">
// Convert divs to queue widgets when the DOM is ready // Convert divs to queue widgets when the DOM is ready
$(function() { $(function() {
$("#uploader").plupload({ $("#uploader").plupload({
// General settings // General settings
runtimes : 'flash,html5,browserplus,silverlight,gears,html4', runtimes : 'flash,html5,browserplus,silverlight,gears,html4',
url : 'upload.php', url : '../upload.php',
max_file_size : '1000mb', max_file_size : '1000mb',
max_file_count: 20, // user can add no more then 20 files at a time max_file_count: 20, // user can add no more then 20 files at a time
chunk_size : '1mb', chunk_size : '1mb',
@ -47,10 +69,10 @@ $(function() {
], ],
// Flash settings // Flash settings
flash_swf_url : '../js/plupload.flash.swf', flash_swf_url : '../../js/plupload.flash.swf',
// Silverlight settings // Silverlight settings
silverlight_xap_url : '../js/plupload.silverlight.xap' silverlight_xap_url : '../../js/plupload.silverlight.xap'
}); });
// Client side form validation // Client side form validation
@ -77,18 +99,5 @@ $(function() {
}); });
</script> </script>
</head>
<body>
<h1>jQuery UI Widget</h1>
<p>You can see this example with different themes on the <a href="http://plupload.com/example_jquery_ui.php">www.plupload.com</a> website.</p>
<form method="post" action="dump.php">
<div id="uploader">
<p>You browser doesn't have Flash, Silverlight, Gears, BrowserPlus or HTML5 support.</p>
</div>
</form>
</body> </body>
</html> </html>

View file

@ -2,26 +2,74 @@
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr"> <html xmlns="http://www.w3.org/1999/xhtml" dir="ltr">
<head> <head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/> <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<link rel="stylesheet" href="css/plupload.queue.css" type="text/css" media="screen" />
<title>Plupload - Queue widget example</title> <title>Plupload - Queue widget example</title>
<style type="text/css"> <style type="text/css">
body {background: #9A7C5F;} body {
font-family:Verdana, Geneva, sans-serif;
font-size:13px;
color:#333;
background:url(../bg.jpg);
}
</style> </style>
<script type="text/javascript" src="http://www.google.com/jsapi"></script> <link rel="stylesheet" href="../../js/jquery.plupload.queue/css/jquery.plupload.queue.css" type="text/css" media="screen" />
<script type="text/javascript">
google.load("jquery", "1.3"); <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>
</script>
<script type="text/javascript" src="../js/gears_init.js"></script>
<script type="text/javascript" src="http://bp.yahooapis.com/2.4.21/browserplus-min.js"></script> <script type="text/javascript" src="http://bp.yahooapis.com/2.4.21/browserplus-min.js"></script>
<script type="text/javascript" src="../js/plupload.full.min.js"></script>
<script type="text/javascript" src="../js/jquery.plupload.queue.min.js"></script> <script type="text/javascript" src="../../js/plupload.js"></script>
<script> <script type="text/javascript" src="../../js/plupload.gears.js"></script>
<script type="text/javascript" src="../../js/plupload.silverlight.js"></script>
<script type="text/javascript" src="../../js/plupload.flash.js"></script>
<script type="text/javascript" src="../../js/plupload.browserplus.js"></script>
<script type="text/javascript" src="../../js/plupload.html4.js"></script>
<script type="text/javascript" src="../../js/plupload.html5.js"></script>
<script type="text/javascript" src="../../js/jquery.plupload.queue/jquery.plupload.queue.js"></script>
<!-- <script type="text/javascript" src="http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js"></script> -->
</head>
<body>
<form method="post" action="dump.php">
<h1>Queue widget example</h1>
<p>Shows the jQuery Plupload Queue widget and under different runtimes.</p>
<div style="float: left; margin-right: 20px">
<h3>Flash runtime</h3>
<div id="flash_uploader" style="width: 450px; height: 330px;">You browser doesn't have Flash installed.</div>
<h3>Gears runtime</h3>
<div id="gears_uploader" style="width: 450px; height: 330px;">You browser doesn't have Gears installed.</div>
</div>
<div style="float: left; margin-right: 20px">
<h3>Silverlight runtime</h3>
<div id="silverlight_uploader" style="width: 450px; height: 330px;">You browser doesn't have Silverlight installed.</div>
<h3>HTML 5 runtime</h3>
<div id="html5_uploader" style="width: 450px; height: 330px;">You browser doesn't support native upload. Try Firefox 3 or Safari 4.</div>
</div>
<div style="float: left; margin-right: 20px">
<h3>BrowserPlus runtime</h3>
<div id="browserplus_uploader" style="width: 450px; height: 330px;">You browser doesn't have BrowserPlus installed.</div>
<h3>HTML 4 runtime</h3>
<div id="html4_uploader" style="width: 450px; height: 330px;">You browser doesn't have HTML 4 support.</div>
</div>
<br style="clear: both" />
<input type="submit" value="Send" />
</form>
<script type="text/javascript">
$(function() { $(function() {
// Setup flash version // Setup flash version
$("#flash_uploader").pluploadQueue({ $("#flash_uploader").pluploadQueue({
// General settings // General settings
runtimes : 'flash', runtimes : 'flash',
url : 'upload.php', url : '../upload.php',
max_file_size : '10mb', max_file_size : '10mb',
chunk_size : '1mb', chunk_size : '1mb',
unique_names : true, unique_names : true,
@ -34,7 +82,7 @@ $(function() {
resize : {width : 320, height : 240, quality : 90}, resize : {width : 320, height : 240, quality : 90},
// Flash settings // Flash settings
flash_swf_url : '../js/plupload.flash.swf' flash_swf_url : '../../js/plupload.flash.swf'
}); });
// Setup gears version // Setup gears version
@ -71,7 +119,7 @@ $(function() {
resize : {width : 320, height : 240, quality : 90}, resize : {width : 320, height : 240, quality : 90},
// Silverlight settings // Silverlight settings
silverlight_xap_url : '../js/plupload.silverlight.xap' silverlight_xap_url : '../../js/plupload.silverlight.xap'
}); });
// Setup html5 version // Setup html5 version
@ -121,43 +169,6 @@ $(function() {
}); });
}); });
</script> </script>
<!-- <script type="text/javascript" src="http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js"></script> -->
</head>
<body>
<form method="post" action="dump.php">
<h1>Queue widget example</h1>
<p>Shows the jQuery Plupload Queue widget and under different runtimes.</p>
<div style="float: left; margin-right: 20px">
<h3>Flash runtime</h3>
<div id="flash_uploader" style="width: 450px; height: 330px;">You browser doesn't have Flash installed.</div>
<h3>Gears runtime</h3>
<div id="gears_uploader" style="width: 450px; height: 330px;">You browser doesn't have Gears installed.</div>
</div>
<div style="float: left; margin-right: 20px">
<h3>Silverlight runtime</h3>
<div id="silverlight_uploader" style="width: 450px; height: 330px;">You browser doesn't have Silverlight installed.</div>
<h3>HTML 5 runtime</h3>
<div id="html5_uploader" style="width: 450px; height: 330px;">You browser doesn't support native upload. Try Firefox 3 or Safari 4.</div>
</div>
<div style="float: left; margin-right: 20px">
<h3>BrowserPlus runtime</h3>
<div id="browserplus_uploader" style="width: 450px; height: 330px;">You browser doesn't have BrowserPlus installed.</div>
<h3>HTML 4 runtime</h3>
<div id="html4_uploader" style="width: 450px; height: 330px;">You browser doesn't have HTML 4 support.</div>
</div>
<br style="clear: both" />
<input type="submit" value="Send" />
</form>
</body> </body>
</html> </html>

View file

@ -75,15 +75,30 @@ $signature = base64_encode(hash_hmac('sha1', $policy, $secret, true));
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/> <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<title>Plupload to Amazon S3 Example</title> <title>Plupload to Amazon S3 Example</title>
<!-- jQuery and jQuery UI --> <style type="text/css">
body {
font-family:Verdana, Geneva, sans-serif;
font-size:13px;
color:#333;
background:url(../bg.jpg);
}
</style>
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.9/themes/base/jquery-ui.css" type="text/css" /> <link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.9/themes/base/jquery-ui.css" type="text/css" />
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script>
<script src=" https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.9/jquery-ui.min.js"></script> <script src=" https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.9/jquery-ui.min.js"></script>
<!-- Load plupload and all it's runtimes and finally the UI widget --> <!-- Load plupload and all it's runtimes and finally the UI widget -->
<link rel="stylesheet" href="css/jquery.ui.plupload.css" type="text/css" /> <link rel="stylesheet" href="../../js/jquery.ui.plupload/css/jquery.ui.plupload.css" type="text/css" />
<script type="text/javascript" src="../js/plupload.full.min.js"></script>
<script type="text/javascript" src="../js/jquery.ui.plupload.min.js"></script> <script type="text/javascript" src="../../js/plupload.js"></script>
<script type="text/javascript" src="../../js/plupload.gears.js"></script>
<script type="text/javascript" src="../../js/plupload.silverlight.js"></script>
<script type="text/javascript" src="../../js/plupload.flash.js"></script>
<script type="text/javascript" src="../../js/plupload.browserplus.js"></script>
<script type="text/javascript" src="../../js/plupload.html4.js"></script>
<script type="text/javascript" src="../../js/plupload.html5.js"></script>
<script type="text/javascript" src="../../js/jquery.ui.plupload/jquery.ui.plupload.js"></script>
<!--<script type="text/javascript" src="http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js"></script>--> <!--<script type="text/javascript" src="http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js"></script>-->
</head> </head>
@ -131,10 +146,10 @@ $(function() {
], ],
// Flash settings // Flash settings
flash_swf_url : '../js/plupload.flash.swf', flash_swf_url : '../../js/plupload.flash.swf',
// Silverlight settings // Silverlight settings
silverlight_xap_url : '../js/plupload.silverlight.xap' silverlight_xap_url : '../../js/plupload.silverlight.xap'
}); });
}); });
</script> </script>

View file

@ -1,194 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<link rel="stylesheet" href="css/plupload.queue.css" type="text/css" media="screen" />
<title>Plupload - Queue widget example</title>
<style type="text/css">
body {background: #9A7C5F;}
</style>
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load("jquery", "1.3");
</script>
<script type="text/javascript" src="../src/javascript/gears_init.js"></script>
<script type="text/javascript" src="http://bp.yahooapis.com/2.4.21/browserplus-min.js"></script>
<!-- Load source versions of the plupload script files -->
<script type="text/javascript" src="../src/javascript/plupload.js"></script>
<script type="text/javascript" src="../src/javascript/plupload.gears.js"></script>
<script type="text/javascript" src="../src/javascript/plupload.silverlight.js"></script>
<script type="text/javascript" src="../src/javascript/plupload.flash.js"></script>
<script type="text/javascript" src="../src/javascript/plupload.browserplus.js"></script>
<script type="text/javascript" src="../src/javascript/plupload.html4.js"></script>
<script type="text/javascript" src="../src/javascript/plupload.html5.js"></script>
<script type="text/javascript" src="../src/javascript/jquery.plupload.queue.js"></script>
<script type="text/javascript" src="http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js"></script>
<script>
$(function() {
// Setup flash version
$("#flash_uploader").pluploadQueue({
// General settings
runtimes : 'flash',
url : 'upload.php',
max_file_size : '10mb',
chunk_size : '1mb',
unique_names : true,
resize : {width : 320, height : 240, quality : 90},
filters : [
{title : "Image files", extensions : "jpg,gif,png"},
{title : "Zip files", extensions : "zip"}
],
// Flash settings
flash_swf_url : '../js/plupload.flash.swf'
});
// Setup gears version
$("#gears_uploader").pluploadQueue({
// General settings
runtimes : 'gears',
url : 'upload.php',
max_file_size : '10mb',
chunk_size : '1mb',
unique_names : true,
resize : {width : 320, height : 240, quality : 90},
filters : [
{title : "Image files", extensions : "jpg,gif,png"},
{title : "Zip files", extensions : "zip"}
]
});
// Setup silverlight version
$("#silverlight_uploader").pluploadQueue({
// General settings
runtimes : 'silverlight',
url : 'upload.php',
max_file_size : '10mb',
chunk_size : '1mb',
unique_names : true,
resize : {width : 320, height : 240, quality : 90},
filters : [
{title : "Image files", extensions : "jpg,gif,png"},
{title : "Zip files", extensions : "zip"}
],
// Silverlight settings
silverlight_xap_url : '../js/plupload.silverlight.xap'
});
// Setup html5 version
$("#html5_uploader").pluploadQueue({
// General settings
runtimes : 'html5',
url : 'upload.php',
max_file_size : '10mb',
chunk_size : '1mb',
unique_names : true,
resize : {width : 320, height : 240, quality : 90},
filters : [
{title : "Image files", extensions : "jpg,gif,png"},
{title : "Zip files", extensions : "zip"}
]
});
// Setup browserplus version
$("#browserplus_uploader").pluploadQueue({
// General settings
runtimes : 'browserplus',
url : 'upload.php',
max_file_size : '10mb',
chunk_size : '1mb',
unique_names : true,
resize : {width : 320, height : 240, quality : 90},
filters : [
{title : "Image files", extensions : "jpg,gif,png"},
{title : "Zip files", extensions : "zip"}
]
});
// Setup browserplus version
$("#html4_uploader").pluploadQueue({
// General settings
runtimes : 'html4',
url : 'upload.php',
max_file_size : '10mb',
chunk_size : '1mb',
unique_names : true,
resize : {width : 320, height : 240, quality : 90},
filters : [
{title : "Image files", extensions : "jpg,gif,png"},
{title : "Zip files", extensions : "zip"}
]
});
// Custom example
var uploader = new plupload.Uploader({
runtimes : 'gears,html5,flash,silverlight,browserplus',
browse_button : 'pickfiles',
url : 'upload.php'
});
uploader.bind('FilesAdded', function(up, files) {
$.each(files, function(i, file) {
$('#filelist').append("<div id=" + file.id + ">File: " + file.name + " (" + plupload.formatSize(file.size) + ") <span></span></div>");
});
});
uploader.bind('UploadProgress', function(up, file) {
$('#' + file.id + " span").html(file.percent + "%");
});
$('#uploadfiles').click(function() {
uploader.start();
});
uploader.init();
});
</script>
<!-- <script type="text/javascript" src="http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js"></script> -->
</head>
<body>
<form method="post" action="dump.php">
<h1>Queue widget example</h1>
<p>Shows the jQuery Plupload Queue widget and under different runtimes.</p>
<div style="float: left; margin-right: 20px">
<h3>Flash runtime</h3>
<div id="flash_uploader" style="width: 450px; height: 330px;">You browser doesn't have Flash installed.</div>
<h3>Gears runtime</h3>
<div id="gears_uploader" style="width: 450px; height: 330px;">You browser doesn't have Gears installed.</div>
</div>
<div style="float: left; margin-right: 20px">
<h3>Silverlight runtime</h3>
<div id="silverlight_uploader" style="width: 450px; height: 330px;">You browser doesn't have Silverlight installed.</div>
<h3>HTML 5 runtime</h3>
<div id="html5_uploader" style="width: 450px; height: 330px;">You browser doesn't support native upload. Try Firefox 3 or Safari 4.</div>
</div>
<div style="float: left; margin-right: 20px">
<h3>BrowserPlus runtime</h3>
<div id="browserplus_uploader" style="width: 450px; height: 330px;">You browser doesn't have BrowserPlus installed.</div>
<h3>HTML4 runtime</h3>
<div id="html4_uploader" style="width: 450px; height: 330px;">You browser doesn't have a HTML 4 browser.</div>
<div>
<h3>Custom example</h3>
<div id="filelist"></div>
<input id="pickfiles" type="button" value="Pick files" />
<input id="uploadfiles" type="button" value="Upload" />
</div>
</div>
<br style="clear: both" />
<input type="submit" value="Send" />
</form>
</body>
</html>

View file

@ -17,9 +17,11 @@
header("Pragma: no-cache"); header("Pragma: no-cache");
// Settings // Settings
$targetDir = ini_get("upload_tmp_dir") . DIRECTORY_SEPARATOR . "plupload"; //$targetDir = ini_get("upload_tmp_dir") . DIRECTORY_SEPARATOR . "plupload";
$cleanupTargetDir = false; // Remove old files $targetDir = 'uploads/';
$maxFileAge = 60 * 60; // Temp file age in seconds
//$cleanupTargetDir = false; // Remove old files
//$maxFileAge = 60 * 60; // Temp file age in seconds
// 5 minutes execution time // 5 minutes execution time
@set_time_limit(5 * 60); @set_time_limit(5 * 60);
@ -53,6 +55,8 @@
@mkdir($targetDir); @mkdir($targetDir);
// Remove old temp files // Remove old temp files
/* this doesn't really work by now
if (is_dir($targetDir) && ($dir = opendir($targetDir))) { if (is_dir($targetDir) && ($dir = opendir($targetDir))) {
while (($file = readdir($dir)) !== false) { while (($file = readdir($dir)) !== false) {
$filePath = $targetDir . DIRECTORY_SEPARATOR . $file; $filePath = $targetDir . DIRECTORY_SEPARATOR . $file;
@ -65,6 +69,7 @@
closedir($dir); closedir($dir);
} else } else
die('{"jsonrpc" : "2.0", "error" : {"code": 100, "message": "Failed to open temp directory."}, "id" : "id"}'); die('{"jsonrpc" : "2.0", "error" : {"code": 100, "message": "Failed to open temp directory."}, "id" : "id"}');
*/
// Look for the content type header // Look for the content type header
if (isset($_SERVER["HTTP_CONTENT_TYPE"])) if (isset($_SERVER["HTTP_CONTENT_TYPE"]))
@ -115,4 +120,5 @@
// Return JSON-RPC response // Return JSON-RPC response
die('{"jsonrpc" : "2.0", "result" : null, "id" : "id"}'); die('{"jsonrpc" : "2.0", "result" : null, "id" : "id"}');
?> ?>

View file

@ -1,86 +0,0 @@
// Copyright 2007, Google Inc.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// 3. Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Sets up google.gears.*, which is *the only* supported way to access Gears.
//
// Circumvent this file at your own risk!
//
// In the future, Gears may automatically define google.gears.* without this
// file. Gears may use these objects to transparently fix bugs and compatibility
// issues. Applications that use the code below will continue to work seamlessly
// when that happens.
(function() {
// We are already defined. Hooray!
if (window.google && google.gears) {
return;
}
var factory = null;
// Firefox
if (typeof GearsFactory != 'undefined') {
factory = new GearsFactory();
} else {
// IE
try {
factory = new ActiveXObject('Gears.Factory');
// privateSetGlobalObject is only required and supported on WinCE.
if (factory.getBuildInfo().indexOf('ie_mobile') != -1) {
factory.privateSetGlobalObject(this);
}
} catch (e) {
// Safari
if ((typeof navigator.mimeTypes != 'undefined')
&& navigator.mimeTypes["application/x-googlegears"]) {
factory = document.createElement("object");
factory.style.display = "none";
factory.width = 0;
factory.height = 0;
factory.type = "application/x-googlegears";
document.documentElement.appendChild(factory);
}
}
}
// *Do not* define any objects if Gears is not installed. This mimics the
// behavior of Gears defining the objects in the future.
if (!factory) {
return;
}
// Now set up the objects, being careful not to overwrite anything.
//
// Note: In Internet Explorer for Windows Mobile, you can't add properties to
// the window object. However, global objects are automatically added as
// properties of the window object in all browsers.
if (!window.google) {
google = {};
}
if (!google.gears) {
google.gears = {factory: factory};
}
})();

View file

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

View file

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View file

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View file

Before

Width:  |  Height:  |  Size: 180 B

After

Width:  |  Height:  |  Size: 180 B

View file

Before

Width:  |  Height:  |  Size: 1 KiB

After

Width:  |  Height:  |  Size: 1 KiB

View file

Before

Width:  |  Height:  |  Size: 994 B

After

Width:  |  Height:  |  Size: 994 B

View file

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View file

Before

Width:  |  Height:  |  Size: 399 B

After

Width:  |  Height:  |  Size: 399 B

File diff suppressed because one or more lines are too long

View file

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View file

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
(function(f,b,d,e){var a={},g={};function c(){var h;try{h=navigator.plugins["Shockwave Flash"];h=h.description}catch(j){try{h=new ActiveXObject("ShockwaveFlash.ShockwaveFlash").GetVariable("$version")}catch(i){h="0.0"}}h=h.match(/\d+/g);return parseFloat(h[0]+"."+h[1])}d.flash={trigger:function(j,h,i){setTimeout(function(){var m=a[j],l,k;if(m){m.trigger("Flash:"+h,i)}},0)}};d.runtimes.Flash=d.addRuntime("flash",{getFeatures:function(){return{jpgresize:true,pngresize:true,maxWidth:8091,maxHeight:8091,chunks:true,progress:true,multipart:true}},init:function(j,o){var n,i,k,p=0,h=b.body;if(c()<10){o({success:false});return}g[j.id]=false;a[j.id]=j;n=b.getElementById(j.settings.browse_button);i=b.createElement("div");i.id=j.id+"_flash_container";d.extend(i.style,{position:"absolute",top:"0px",background:j.settings.shim_bgcolor||"transparent",zIndex:99999,width:"100%",height:"100%"});i.className="plupload flash";if(j.settings.container){h=b.getElementById(j.settings.container);if(d.getStyle(h,"position")==="static"){h.style.position="relative"}}h.appendChild(i);k="id="+escape(j.id);i.innerHTML='<object id="'+j.id+'_flash" width="100%" height="100%" style="outline:0" type="application/x-shockwave-flash" data="'+j.settings.flash_swf_url+'"><param name="movie" value="'+j.settings.flash_swf_url+'" /><param name="flashvars" value="'+k+'" /><param name="wmode" value="transparent" /><param name="allowscriptaccess" value="always" /></object>';function m(){return b.getElementById(j.id+"_flash")}function l(){if(p++>5000){o({success:false});return}if(!g[j.id]){setTimeout(l,1)}}l();n=i=null;j.bind("Flash:Init",function(){var r={},q;m().setFileFilters(j.settings.filters,j.settings.multi_selection);if(g[j.id]){return}g[j.id]=true;j.bind("UploadFile",function(s,u){var v=s.settings,t=j.settings.resize||{};m().uploadFile(r[u.id],v.url,{name:u.target_name||u.name,mime:d.mimeTypes[u.name.replace(/^.+\.([^.]+)/,"$1").toLowerCase()]||"application/octet-stream",chunk_size:v.chunk_size,width:t.width,height:t.height,quality:t.quality,multipart:v.multipart,multipart_params:v.multipart_params||{},file_data_name:v.file_data_name,format:/\.(jpg|jpeg)$/i.test(u.name)?"jpg":"png",headers:v.headers,urlstream_upload:v.urlstream_upload})});j.bind("Flash:UploadProcess",function(t,s){var u=t.getFile(r[s.id]);if(u.status!=d.FAILED){u.loaded=s.loaded;u.size=s.size;t.trigger("UploadProgress",u)}});j.bind("Flash:UploadChunkComplete",function(s,u){var v,t=s.getFile(r[u.id]);v={chunk:u.chunk,chunks:u.chunks,response:u.text};s.trigger("ChunkUploaded",t,v);if(t.status!=d.FAILED){m().uploadNextChunk()}if(u.chunk==u.chunks-1){t.status=d.DONE;s.trigger("FileUploaded",t,{response:u.text})}});j.bind("Flash:SelectFiles",function(s,v){var u,t,w=[],x;for(t=0;t<v.length;t++){u=v[t];x=d.guid();r[x]=u.id;r[u.id]=x;w.push(new d.File(x,u.name,u.size))}if(w.length){j.trigger("FilesAdded",w)}});j.bind("Flash:SecurityError",function(s,t){j.trigger("Error",{code:d.SECURITY_ERROR,message:d.translate("Security error."),details:t.message,file:j.getFile(r[t.id])})});j.bind("Flash:GenericError",function(s,t){j.trigger("Error",{code:d.GENERIC_ERROR,message:d.translate("Generic error."),details:t.message,file:j.getFile(r[t.id])})});j.bind("Flash:IOError",function(s,t){j.trigger("Error",{code:d.IO_ERROR,message:d.translate("IO error."),details:t.message,file:j.getFile(r[t.id])})});j.bind("Flash:ImageError",function(s,t){j.trigger("Error",{code:parseInt(t.code,10),message:d.translate("Image error."),file:j.getFile(r[t.id])})});j.bind("Flash:StageEvent:rollOver",function(s){var t,u;t=b.getElementById(j.settings.browse_button);u=s.settings.browse_button_hover;if(t&&u){d.addClass(t,u)}});j.bind("Flash:StageEvent:rollOut",function(s){var t,u;t=b.getElementById(j.settings.browse_button);u=s.settings.browse_button_hover;if(t&&u){d.removeClass(t,u)}});j.bind("Flash:StageEvent:mouseDown",function(s){var t,u;t=b.getElementById(j.settings.browse_button);u=s.settings.browse_button_active;if(t&&u){d.addClass(t,u);d.addEvent(b.body,"mouseup",function(){d.removeClass(t,u)},s.id)}});j.bind("Flash:StageEvent:mouseUp",function(s){var t,u;t=b.getElementById(j.settings.browse_button);u=s.settings.browse_button_active;if(t&&u){d.removeClass(t,u)}});j.bind("QueueChanged",function(s){j.refresh()});j.bind("FilesRemoved",function(s,u){var t;for(t=0;t<u.length;t++){m().removeFile(r[u[t].id])}});j.bind("StateChanged",function(s){j.refresh()});j.bind("Refresh",function(s){var t,u,v;m().setFileFilters(j.settings.filters,j.settings.multi_selection);t=b.getElementById(s.settings.browse_button);if(t){u=d.getPos(t,b.getElementById(s.settings.container));v=d.getSize(t);d.extend(b.getElementById(s.id+"_flash_container").style,{top:u.y+"px",left:u.x+"px",width:v.w+"px",height:v.h+"px"})}});j.bind("Destroy",function(s){var t;d.removeAllEvents(b.body,s.id);delete g[s.id];delete a[s.id];t=b.getElementById(s.id+"_flash_container");if(t){h.removeChild(t)}});o({success:true})})}})})(window,document,plupload);

View file

@ -1 +0,0 @@
(function(f,b,d,e){var a={},g={};function c(){var h;try{h=navigator.plugins["Shockwave Flash"];h=h.description}catch(j){try{h=new ActiveXObject("ShockwaveFlash.ShockwaveFlash").GetVariable("$version")}catch(i){h="0.0"}}h=h.match(/\d+/g);return parseFloat(h[0]+"."+h[1])}d.flash={trigger:function(j,h,i){setTimeout(function(){var m=a[j],l,k;if(m){m.trigger("Flash:"+h,i)}},0)}};d.runtimes.Flash=d.addRuntime("flash",{getFeatures:function(){return{jpgresize:true,pngresize:true,maxWidth:8091,maxHeight:8091,chunks:true,progress:true,multipart:true}},init:function(j,o){var n,i,k,p=0,h=b.body;if(c()<10){o({success:false});return}g[j.id]=false;a[j.id]=j;n=b.getElementById(j.settings.browse_button);i=b.createElement("div");i.id=j.id+"_flash_container";d.extend(i.style,{position:"absolute",top:"0px",background:j.settings.shim_bgcolor||"transparent",zIndex:99999,width:"100%",height:"100%"});i.className="plupload flash";if(j.settings.container){h=b.getElementById(j.settings.container);h.style.position="relative"}h.appendChild(i);k="id="+escape(j.id);i.innerHTML='<object id="'+j.id+'_flash" width="100%" height="100%" style="outline:0" type="application/x-shockwave-flash" data="'+j.settings.flash_swf_url+'"><param name="movie" value="'+j.settings.flash_swf_url+'" /><param name="flashvars" value="'+k+'" /><param name="wmode" value="transparent" /><param name="allowscriptaccess" value="always" /></object>';function m(){return b.getElementById(j.id+"_flash")}function l(){if(p++>5000){o({success:false});return}if(!g[j.id]){setTimeout(l,1)}}l();n=i=null;j.bind("Flash:Init",function(){var s={},r,q=j.settings.resize||{};m().setFileFilters(j.settings.filters,j.settings.multi_selection);if(g[j.id]){return}g[j.id]=true;j.bind("UploadFile",function(t,u){var v=t.settings;m().uploadFile(s[u.id],v.url,{name:u.target_name||u.name,mime:d.mimeTypes[u.name.replace(/^.+\.([^.]+)/,"$1")]||"application/octet-stream",chunk_size:v.chunk_size,width:q.width,height:q.height,quality:q.quality||90,multipart:v.multipart,multipart_params:v.multipart_params||{},file_data_name:v.file_data_name,format:/\.(jpg|jpeg)$/i.test(u.name)?"jpg":"png",headers:v.headers,urlstream_upload:v.urlstream_upload})});j.bind("Flash:UploadProcess",function(u,t){var v=u.getFile(s[t.id]);if(v.status!=d.FAILED){v.loaded=t.loaded;v.size=t.size;u.trigger("UploadProgress",v)}});j.bind("Flash:UploadChunkComplete",function(t,v){var w,u=t.getFile(s[v.id]);w={chunk:v.chunk,chunks:v.chunks,response:v.text};t.trigger("ChunkUploaded",u,w);if(u.status!=d.FAILED){m().uploadNextChunk()}if(v.chunk==v.chunks-1){u.status=d.DONE;t.trigger("FileUploaded",u,{response:v.text})}});j.bind("Flash:SelectFiles",function(t,w){var v,u,x=[],y;for(u=0;u<w.length;u++){v=w[u];y=d.guid();s[y]=v.id;s[v.id]=y;x.push(new d.File(y,v.name,v.size))}if(x.length){j.trigger("FilesAdded",x)}});j.bind("Flash:SecurityError",function(t,u){j.trigger("Error",{code:d.SECURITY_ERROR,message:d.translate("Security error."),details:u.message,file:j.getFile(s[u.id])})});j.bind("Flash:GenericError",function(t,u){j.trigger("Error",{code:d.GENERIC_ERROR,message:d.translate("Generic error."),details:u.message,file:j.getFile(s[u.id])})});j.bind("Flash:IOError",function(t,u){j.trigger("Error",{code:d.IO_ERROR,message:d.translate("IO error."),details:u.message,file:j.getFile(s[u.id])})});j.bind("Flash:ImageError",function(t,u){j.trigger("Error",{code:parseInt(u.code),message:d.translate("Image error."),file:j.getFile(s[u.id])})});j.bind("Flash:StageEvent:rollOver",function(t){var u,v;u=b.getElementById(j.settings.browse_button);v=t.settings.browse_button_hover;if(u&&v){d.addClass(u,v)}});j.bind("Flash:StageEvent:rollOut",function(t){var u,v;u=b.getElementById(j.settings.browse_button);v=t.settings.browse_button_hover;if(u&&v){d.removeClass(u,v)}});j.bind("Flash:StageEvent:mouseDown",function(t){var u,v;u=b.getElementById(j.settings.browse_button);v=t.settings.browse_button_active;if(u&&v){d.addClass(u,v);d.addEvent(b.body,"mouseup",function(){d.removeClass(u,v)},t.id)}});j.bind("Flash:StageEvent:mouseUp",function(t){var u,v;u=b.getElementById(j.settings.browse_button);v=t.settings.browse_button_active;if(u&&v){d.removeClass(u,v)}});j.bind("QueueChanged",function(t){j.refresh()});j.bind("FilesRemoved",function(t,v){var u;for(u=0;u<v.length;u++){m().removeFile(s[v[u].id])}});j.bind("StateChanged",function(t){j.refresh()});j.bind("Refresh",function(t){var u,v,w;m().setFileFilters(j.settings.filters,j.settings.multi_selection);u=b.getElementById(t.settings.browse_button);if(u){v=d.getPos(u,b.getElementById(t.settings.container));w=d.getSize(u);d.extend(b.getElementById(t.id+"_flash_container").style,{top:v.y+"px",left:v.x+"px",width:w.w+"px",height:w.h+"px"})}});j.bind("Destroy",function(t){var u;d.removeAllEvents(b.body,t.id);delete g[t.id];delete a[t.id];u=b.getElementById(t.id+"_flash_container");if(u){h.removeChild(u)}});o({success:true})})}})})(window,document,plupload);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
(function(){if(window.google&&google.gears){return}var a=null;if(typeof GearsFactory!="undefined"){a=new GearsFactory()}else{try{a=new ActiveXObject("Gears.Factory");if(a.getBuildInfo().indexOf("ie_mobile")!=-1){a.privateSetGlobalObject(this)}}catch(b){if((typeof navigator.mimeTypes!="undefined")&&navigator.mimeTypes["application/x-googlegears"]){a=document.createElement("object");a.style.display="none";a.width=0;a.height=0;a.type="application/x-googlegears";document.documentElement.appendChild(a)}}}if(!a){return}if(!window.google){window.google={}}if(!google.gears){google.gears={factory:a}}})();(function(e,b,c,d){var f={};function a(h,j,l){var g,i,k,n;i=google.gears.factory.create("beta.canvas");try{i.decode(h);if(!j.width){j.width=i.width}if(!j.height){j.height=i.height}n=Math.min(width/i.width,height/i.height);if(n<1||(n===1&&l==="image/jpeg")){i.resize(Math.round(i.width*n),Math.round(i.height*n));if(j.quality){return i.encode(l,{quality:j.quality/100})}return i.encode(l)}}catch(m){}return h}c.runtimes.Gears=c.addRuntime("gears",{getFeatures:function(){return{dragdrop:true,jpgresize:true,pngresize:true,chunks:true,progress:true,multipart:true}},init:function(i,k){var j;if(!e.google||!google.gears){return k({success:false})}try{j=google.gears.factory.create("beta.desktop")}catch(h){return k({success:false})}function g(n){var m,l,o=[],p;for(l=0;l<n.length;l++){m=n[l];p=c.guid();f[p]=m.blob;o.push(new c.File(p,m.name,m.blob.length))}i.trigger("FilesAdded",o)}i.bind("PostInit",function(){var m=i.settings,l=b.getElementById(m.drop_element);if(l){c.addEvent(l,"dragover",function(n){j.setDropEffect(n,"copy");n.preventDefault()},i.id);c.addEvent(l,"drop",function(o){var n=j.getDragData(o,"application/x-gears-files");if(n){g(n.files)}o.preventDefault()},i.id);l=0}c.addEvent(b.getElementById(m.browse_button),"click",function(r){var q=[],o,n,p;r.preventDefault();for(o=0;o<m.filters.length;o++){p=m.filters[o].extensions.split(",");for(n=0;n<p.length;n++){q.push("."+p[n])}}j.openFiles(g,{singleFile:!m.multi_selection,filter:q})},i.id)});i.bind("UploadFile",function(r,o){var t=0,s,p,q=0,n=r.settings.resize,l;if(n&&/\.(png|jpg|jpeg)$/i.test(o.name)){f[o.id]=a(f[o.id],n,/\.png$/i.test(o.name)?"image/png":"image/jpeg")}o.size=f[o.id].length;p=r.settings.chunk_size;l=p>0;s=Math.ceil(o.size/p);if(!l){p=o.size;s=1}function m(){var y,A,v=r.settings.multipart,u=0,z={name:o.target_name||o.name},w=r.settings.url;function x(C){var B,H="----pluploadboundary"+c.guid(),E="--",G="\r\n",D,F;if(v){y.setRequestHeader("Content-Type","multipart/form-data; boundary="+H);B=google.gears.factory.create("beta.blobbuilder");c.each(c.extend(z,r.settings.multipart_params),function(J,I){B.append(E+H+G+'Content-Disposition: form-data; name="'+I+'"'+G+G);B.append(J+G)});F=c.mimeTypes[o.name.replace(/^.+\.([^.]+)/,"$1").toLowerCase()]||"application/octet-stream";B.append(E+H+G+'Content-Disposition: form-data; name="'+r.settings.file_data_name+'"; filename="'+o.name+'"'+G+"Content-Type: "+F+G+G);B.append(C);B.append(G+E+H+E+G);D=B.getAsBlob();u=D.length-C.length;C=D}y.send(C)}if(o.status==c.DONE||o.status==c.FAILED||r.state==c.STOPPED){return}if(l){z.chunk=t;z.chunks=s}A=Math.min(p,o.size-(t*p));if(!v){w=c.buildUrl(r.settings.url,z)}y=google.gears.factory.create("beta.httprequest");y.open("POST",w);if(!v){y.setRequestHeader("Content-Disposition",'attachment; filename="'+o.name+'"');y.setRequestHeader("Content-Type","application/octet-stream")}c.each(r.settings.headers,function(C,B){y.setRequestHeader(B,C)});y.upload.onprogress=function(B){o.loaded=q+B.loaded-u;r.trigger("UploadProgress",o)};y.onreadystatechange=function(){var B;if(y.readyState==4){if(y.status==200){B={chunk:t,chunks:s,response:y.responseText,status:y.status};r.trigger("ChunkUploaded",o,B);if(B.cancelled){o.status=c.FAILED;return}q+=A;if(++t>=s){o.status=c.DONE;r.trigger("FileUploaded",o,{response:y.responseText,status:y.status})}else{m()}}else{r.trigger("Error",{code:c.HTTP_ERROR,message:c.translate("HTTP Error."),file:o,chunk:t,chunks:s,status:y.status})}}};if(t<s){x(f[o.id].slice(t*p,A))}}m()});i.bind("Destroy",function(l){var m,n,o={browseButton:l.settings.browse_button,dropElm:l.settings.drop_element};for(m in o){n=b.getElementById(o[m]);if(n){c.removeAllEvents(n,l.id)}}});k({success:true})}})})(window,document,plupload);

View file

@ -1 +0,0 @@
(function(e,b,c,d){var f={};function a(l,h,o,n,g){var p,j,i,k;j=google.gears.factory.create("beta.canvas");try{j.decode(l);k=Math.min(h/j.width,o/j.height);if(k<1){j.resize(Math.round(j.width*k),Math.round(j.height*k));return j.encode(g,{quality:n/100})}}catch(m){}return l}c.runtimes.Gears=c.addRuntime("gears",{getFeatures:function(){return{dragdrop:true,jpgresize:true,pngresize:true,chunks:true,progress:true,multipart:true}},init:function(i,k){var j;if(!e.google||!google.gears){return k({success:false})}try{j=google.gears.factory.create("beta.desktop")}catch(h){return k({success:false})}function g(n){var m,l,o=[],p;for(l=0;l<n.length;l++){m=n[l];p=c.guid();f[p]=m.blob;o.push(new c.File(p,m.name,m.blob.length))}i.trigger("FilesAdded",o)}i.bind("PostInit",function(){var m=i.settings,l=b.getElementById(m.drop_element);if(l){c.addEvent(l,"dragover",function(n){j.setDropEffect(n,"copy");n.preventDefault()},i.id);c.addEvent(l,"drop",function(o){var n=j.getDragData(o,"application/x-gears-files");if(n){g(n.files)}o.preventDefault()},i.id);l=0}c.addEvent(b.getElementById(m.browse_button),"click",function(r){var q=[],o,n,p;r.preventDefault();for(o=0;o<m.filters.length;o++){p=m.filters[o].extensions.split(",");for(n=0;n<p.length;n++){q.push("."+p[n])}}j.openFiles(g,{singleFile:!m.multi_selection,filter:q})},i.id)});i.bind("UploadFile",function(r,o){var t=0,s,p,q=0,n=r.settings.resize,l;if(n&&/\.(png|jpg|jpeg)$/i.test(o.name)){f[o.id]=a(f[o.id],n.width,n.height,n.quality||90,/\.png$/i.test(o.name)?"image/png":"image/jpeg")}o.size=f[o.id].length;p=r.settings.chunk_size;l=p>0;s=Math.ceil(o.size/p);if(!l){p=o.size;s=1}function m(){var y,A,v=r.settings.multipart,u=0,z={name:o.target_name||o.name},w=r.settings.url;function x(C){var B,H="----pluploadboundary"+c.guid(),E="--",G="\r\n",D,F;if(v){y.setRequestHeader("Content-Type","multipart/form-data; boundary="+H);B=google.gears.factory.create("beta.blobbuilder");c.each(c.extend(z,r.settings.multipart_params),function(J,I){B.append(E+H+G+'Content-Disposition: form-data; name="'+I+'"'+G+G);B.append(J+G)});F=c.mimeTypes[o.name.replace(/^.+\.([^.]+)/,"$1")]||"application/octet-stream";B.append(E+H+G+'Content-Disposition: form-data; name="'+r.settings.file_data_name+'"; filename="'+o.name+'"'+G+"Content-Type: "+F+G+G);B.append(C);B.append(G+E+H+E+G);D=B.getAsBlob();u=D.length-C.length;C=D}y.send(C)}if(o.status==c.DONE||o.status==c.FAILED||r.state==c.STOPPED){return}if(l){z.chunk=t;z.chunks=s}A=Math.min(p,o.size-(t*p));if(!v){w=c.buildUrl(r.settings.url,z)}y=google.gears.factory.create("beta.httprequest");y.open("POST",w);if(!v){y.setRequestHeader("Content-Disposition",'attachment; filename="'+o.name+'"');y.setRequestHeader("Content-Type","application/octet-stream")}c.each(r.settings.headers,function(C,B){y.setRequestHeader(B,C)});y.upload.onprogress=function(B){o.loaded=q+B.loaded-u;r.trigger("UploadProgress",o)};y.onreadystatechange=function(){var B;if(y.readyState==4){if(y.status==200){B={chunk:t,chunks:s,response:y.responseText,status:y.status};r.trigger("ChunkUploaded",o,B);if(B.cancelled){o.status=c.FAILED;return}q+=A;if(++t>=s){o.status=c.DONE;r.trigger("FileUploaded",o,{response:y.responseText,status:y.status})}else{m()}}else{r.trigger("Error",{code:c.HTTP_ERROR,message:c.translate("HTTP Error."),file:o,chunk:t,chunks:s,status:y.status})}}};if(t<s){x(f[o.id].slice(t*p,A))}}m()});i.bind("Destroy",function(l){var m,n,o={browseButton:l.settings.browse_button,dropElm:l.settings.drop_element};for(m in o){n=b.getElementById(o[m]);if(n){c.removeAllEvents(n,l.id)}}});k({success:true})}})})(window,document,plupload);

View file

@ -0,0 +1 @@
(function(d,a,b,c){function e(f){return a.getElementById(f)}b.runtimes.Html4=b.addRuntime("html4",{getFeatures:function(){return{multipart:true,canOpenDialog:navigator.userAgent.indexOf("WebKit")!==-1}},init:function(f,g){f.bind("Init",function(p){var j=a.body,n,h="javascript",k,x,q,z=[],r=/MSIE/.test(navigator.userAgent),t=[],m=p.settings.filters,o,l,s,w;no_type_restriction:for(o=0;o<m.length;o++){l=m[o].extensions.split(/,/);for(w=0;w<l.length;w++){if(l[w]==="*"){t=[];break no_type_restriction}s=b.mimeTypes[l[w]];if(s){t.push(s)}}}t=t.join(",");function v(){var B,y,i,A;q=b.guid();z.push(q);B=a.createElement("form");B.setAttribute("id","form_"+q);B.setAttribute("method","post");B.setAttribute("enctype","multipart/form-data");B.setAttribute("encoding","multipart/form-data");B.setAttribute("target",p.id+"_iframe");B.style.position="absolute";y=a.createElement("input");y.setAttribute("id","input_"+q);y.setAttribute("type","file");y.setAttribute("accept",t);y.setAttribute("size",1);A=e(p.settings.browse_button);if(p.features.canOpenDialog&&A){b.addEvent(e(p.settings.browse_button),"click",function(C){y.click();C.preventDefault()},p.id)}b.extend(y.style,{width:"100%",height:"100%",opacity:0,fontSize:"99px"});b.extend(B.style,{overflow:"hidden"});i=p.settings.shim_bgcolor;if(i){B.style.background=i}if(r){b.extend(y.style,{filter:"alpha(opacity=0)"})}b.addEvent(y,"change",function(F){var D=F.target,C,E=[],G;if(D.value){e("form_"+q).style.top=-1048575+"px";C=D.value.replace(/\\/g,"/");C=C.substring(C.length,C.lastIndexOf("/")+1);E.push(new b.File(q,C));if(!p.features.canOpenDialog){b.removeAllEvents(B,p.id)}else{b.removeEvent(A,"click",p.id)}b.removeEvent(y,"change",p.id);v();if(E.length){f.trigger("FilesAdded",E)}}},p.id);B.appendChild(y);j.appendChild(B);p.refresh()}function u(){var i=a.createElement("div");i.innerHTML='<iframe id="'+p.id+'_iframe" name="'+p.id+'_iframe" src="'+h+':&quot;&quot;" style="display:none"></iframe>';n=i.firstChild;j.appendChild(n);b.addEvent(n,"load",function(C){var D=C.target,B,y;if(!k){return}try{B=D.contentWindow.document||D.contentDocument||d.frames[D.id].document}catch(A){p.trigger("Error",{code:b.SECURITY_ERROR,message:b.translate("Security error."),file:k});return}y=B.documentElement.innerText||B.documentElement.textContent;if(y){k.status=b.DONE;k.loaded=1025;k.percent=100;p.trigger("UploadProgress",k);p.trigger("FileUploaded",k,{response:y})}},p.id)}if(p.settings.container){j=e(p.settings.container);if(b.getStyle(j,"position")==="static"){j.style.position="relative"}}p.bind("UploadFile",function(i,A){var B,y;if(A.status==b.DONE||A.status==b.FAILED||i.state==b.STOPPED){return}B=e("form_"+A.id);y=e("input_"+A.id);y.setAttribute("name",i.settings.file_data_name);B.setAttribute("action",i.settings.url);b.each(b.extend({name:A.target_name||A.name},i.settings.multipart_params),function(E,C){var D=a.createElement("input");b.extend(D,{type:"hidden",name:C,value:E});B.insertBefore(D,B.firstChild)});k=A;e("form_"+q).style.top=-1048575+"px";B.submit();B.parentNode.removeChild(B)});p.bind("FileUploaded",function(i){i.refresh()});p.bind("StateChanged",function(i){if(i.state==b.STARTED){u()}if(i.state==b.STOPPED){d.setTimeout(function(){b.removeEvent(n,"load",i.id);n.parentNode.removeChild(n)},0)}});p.bind("Refresh",function(A){var F,B,C,D,i,G,H,E,y;F=e(A.settings.browse_button);if(F){i=b.getPos(F,e(A.settings.container));G=b.getSize(F);H=e("form_"+q);E=e("input_"+q);b.extend(H.style,{top:i.y+"px",left:i.x+"px",width:G.w+"px",height:G.h+"px"});if(A.features.canOpenDialog){y=parseInt(F.parentNode.style.zIndex,10);if(isNaN(y)){y=0}b.extend(F.style,{zIndex:y});if(b.getStyle(F,"position")==="static"){b.extend(F.style,{position:"relative"})}b.extend(H.style,{zIndex:y-1})}C=A.settings.browse_button_hover;D=A.settings.browse_button_active;B=A.features.canOpenDialog?F:H;if(C){b.addEvent(B,"mouseover",function(){b.addClass(F,C)},A.id);b.addEvent(B,"mouseout",function(){b.removeClass(F,C)},A.id)}if(D){b.addEvent(B,"mousedown",function(){b.addClass(F,D)},A.id);b.addEvent(a.body,"mouseup",function(){b.removeClass(F,D)},A.id)}}});f.bind("FilesRemoved",function(y,B){var A,C;for(A=0;A<B.length;A++){C=e("form_"+B[A].id);if(C){C.parentNode.removeChild(C)}}});f.bind("Destroy",function(i){var y,A,B,C={inputContainer:"form_"+q,inputFile:"input_"+q,browseButton:i.settings.browse_button};for(y in C){A=e(C[y]);if(A){b.removeAllEvents(A,i.id)}}b.removeAllEvents(a.body,i.id);b.each(z,function(E,D){B=e("form_"+E);if(B){j.removeChild(B)}})});v()});g({success:true})}})})(window,document,plupload);

View file

@ -1 +0,0 @@
(function(d,a,b,c){function e(f){return a.getElementById(f)}b.runtimes.Html4=b.addRuntime("html4",{getFeatures:function(){return{multipart:true,canOpenDialog:navigator.userAgent.indexOf("WebKit")!==-1}},init:function(f,g){f.bind("Init",function(p){var j=a.body,n,h="javascript",k,x,q,z=[],r=/MSIE/.test(navigator.userAgent),t=[],m=p.settings.filters,o,l,s,w;for(o=0;o<m.length;o++){l=m[o].extensions.split(/,/);for(w=0;w<l.length;w++){s=b.mimeTypes[l[w]];if(s){t.push(s)}}}t=t.join(",");function v(){var B,y,i,A;q=b.guid();z.push(q);B=a.createElement("form");B.setAttribute("id","form_"+q);B.setAttribute("method","post");B.setAttribute("enctype","multipart/form-data");B.setAttribute("encoding","multipart/form-data");B.setAttribute("target",p.id+"_iframe");B.style.position="absolute";y=a.createElement("input");y.setAttribute("id","input_"+q);y.setAttribute("type","file");y.setAttribute("accept",t);y.setAttribute("size",1);A=e(p.settings.browse_button);if(p.features.canOpenDialog&&A){b.addEvent(e(p.settings.browse_button),"click",function(C){y.click();C.preventDefault()},p.id)}b.extend(y.style,{width:"100%",height:"100%",opacity:0,fontSize:"2em"});b.extend(B.style,{overflow:"hidden"});i=p.settings.shim_bgcolor;if(i){B.style.background=i}if(r){b.extend(y.style,{filter:"alpha(opacity=0)"})}b.addEvent(y,"change",function(F){var D=F.target,C,E=[],G;if(D.value){e("form_"+q).style.top=-1048575+"px";C=D.value.replace(/\\/g,"/");C=C.substring(C.length,C.lastIndexOf("/")+1);E.push(new b.File(q,C));if(!p.features.canOpenDialog){b.removeAllEvents(B,p.id)}else{b.removeEvent(A,"click",p.id)}b.removeEvent(y,"change",p.id);v();if(E.length){f.trigger("FilesAdded",E)}}},p.id);B.appendChild(y);j.appendChild(B);p.refresh()}function u(){var i=a.createElement("div");i.innerHTML='<iframe id="'+p.id+'_iframe" name="'+p.id+'_iframe" src="'+h+':&quot;&quot;" style="display:none"></iframe>';n=i.firstChild;j.appendChild(n);b.addEvent(n,"load",function(C){var D=C.target,B,y;if(!k){return}try{B=D.contentWindow.document||D.contentDocument||d.frames[D.id].document}catch(A){p.trigger("Error",{code:b.SECURITY_ERROR,message:b.translate("Security error."),file:k});return}y=B.documentElement.innerText||B.documentElement.textContent;if(y){k.status=b.DONE;k.loaded=1025;k.percent=100;p.trigger("UploadProgress",k);p.trigger("FileUploaded",k,{response:y})}},p.id)}if(p.settings.container){j=e(p.settings.container);j.style.position="relative"}p.bind("UploadFile",function(i,A){var B,y;if(A.status==b.DONE||A.status==b.FAILED||i.state==b.STOPPED){return}B=e("form_"+A.id);y=e("input_"+A.id);y.setAttribute("name",i.settings.file_data_name);B.setAttribute("action",i.settings.url);b.each(b.extend({name:A.target_name||A.name},i.settings.multipart_params),function(E,C){var D=a.createElement("input");b.extend(D,{type:"hidden",name:C,value:E});B.insertBefore(D,B.firstChild)});k=A;e("form_"+q).style.top=-1048575+"px";B.submit();B.parentNode.removeChild(B)});p.bind("FileUploaded",function(i){i.refresh()});p.bind("StateChanged",function(i){if(i.state==b.STARTED){u()}if(i.state==b.STOPPED){d.setTimeout(function(){b.removeEvent(n,"load",i.id);n.parentNode.removeChild(n)},0)}});p.bind("Refresh",function(A){var F,B,C,D,i,G,H,E,y;F=e(A.settings.browse_button);if(F){i=b.getPos(F,e(A.settings.container));G=b.getSize(F);H=e("form_"+q);E=e("input_"+q);b.extend(H.style,{top:i.y+"px",left:i.x+"px",width:G.w+"px",height:G.h+"px"});if(A.features.canOpenDialog){y=parseInt(F.parentNode.style.zIndex,10);if(isNaN(y)){y=0}b.extend(F.style,{position:"relative",zIndex:y});b.extend(H.style,{zIndex:y-1})}C=A.settings.browse_button_hover;D=A.settings.browse_button_active;B=A.features.canOpenDialog?F:H;if(C){b.addEvent(B,"mouseover",function(){b.addClass(F,C)},A.id);b.addEvent(B,"mouseout",function(){b.removeClass(F,C)},A.id)}if(D){b.addEvent(B,"mousedown",function(){b.addClass(F,D)},A.id);b.addEvent(a.body,"mouseup",function(){b.removeClass(F,D)},A.id)}}});f.bind("FilesRemoved",function(y,B){var A,C;for(A=0;A<B.length;A++){C=e("form_"+B[A].id);if(C){C.parentNode.removeChild(C)}}});f.bind("Destroy",function(i){var y,A,B,C={inputContainer:"form_"+q,inputFile:"input_"+q,browseButton:i.settings.browse_button};for(y in C){A=e(C[y]);if(A){b.removeAllEvents(A,i.id)}}b.removeAllEvents(a.body,i.id);b.each(z,function(E,D){B=e("form_"+E);if(B){j.removeChild(B)}})});v()});g({success:true})}})})(window,document,plupload);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,8 +0,0 @@
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Moxiecode.Plupload.App">
<Application.Resources>
<!-- Resources scoped at the Application level should be defined here. -->
</Application.Resources>
</Application>

View file

@ -1,45 +0,0 @@
/**
* App.xaml.cs
*
* Copyright 2009, Moxiecode Systems AB
* Released under GPL License.
*
* License: http://www.plupload.com/license
* Contributing: http://www.plupload.com/contributing
*/
using System.Windows;
using System;
using System.Windows.Browser;
namespace Moxiecode.Plupload {
/// <summary>
/// Partial class for the Silverlight application.
/// </summary>
public partial class App : Application {
public App() {
this.Startup += this.OnStartup;
this.UnhandledException += this.Application_UnhandledException;
InitializeComponent();
}
private void OnStartup(object sender, StartupEventArgs e) {
this.RootVisual = new Page(e.InitParams);
}
private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e) {
if (!System.Diagnostics.Debugger.IsAttached) {
e.Handled = true;
try {
string errorMsg = e.ExceptionObject.Message + @"\n" + e.ExceptionObject.StackTrace;
errorMsg = errorMsg.Replace("\"", "\\\"").Replace("\r\n", @"\n");
System.Windows.Browser.HtmlPage.Window.Eval("throw new Error(\"Unhandled Error in Silverlight 2 Application: " + errorMsg + "\");");
} catch (Exception) {
}
}
}
}
}

View file

@ -1,222 +0,0 @@
/// Copyright (c) 2008 Jeffrey Powers for Fluxcapacity Open Source.
/// Under the MIT License, details: License.txt..
// NOTE: Compile with DYNAMIC_IDCT for a decode performance boost.
// May not yield a perceptible boost for small images,
// since there is some overhead in emitting CIL dynamically.
using System;
using System.Reflection.Emit;
using System.Reflection;
namespace FluxJpeg.Core
{
/// <summary>
/// Implements the Discrete Cosine Transform with dynamic CIL
/// </summary>
public partial class DCT
{
private float[] _temp = new float[64];
// Cosine matrix and transposed cosine matrix
private static readonly float[,] c = buildC();
private static readonly float[,] cT = buildCT();
internal DCT()
{
#if DYNAMIC_IDCT
dynamicIDCT = dynamicIDCT ?? EmitIDCT();
#endif
}
/// <summary>
/// Precomputes cosine terms in A.3.3 of
/// http://www.w3.org/Graphics/JPEG/itu-t81.pdf
///
/// Closely follows the term precomputation in the
/// Java Advanced Imaging library.
/// </summary>
private static float[,] buildC()
{
float[,] c = new float[8, 8];
for (int i = 0; i < 8; i++) // i == u or v
{
for (int j = 0; j < 8; j++) // j == x or y
{
c[i, j] = i == 0 ?
0.353553391f : /* 1 / SQRT(8) */
(float)(0.5 * Math.Cos(((2.0 * j + 1) * i * Math.PI) / 16.0));
}
}
return c;
}
private static float[,] buildCT()
{
// Transpose i,k <-- j,i
float[,] cT = new float[8, 8];
for (int i = 0; i < 8; i++)
for (int j = 0; j < 8; j++)
cT[j, i] = c[i, j];
return cT;
}
public static void SetValueClipped(byte[,] arr, int i, int j, float val)
{
// Clip into the 0...255 range & round
arr[i, j] = val < 0 ? (byte)0
: val > 255 ? (byte)255
: (byte)(val + 0.5);
}
/// See figure A.3.3 IDCT (informative) on A-5.
/// http://www.w3.org/Graphics/JPEG/itu-t81.pdf
internal byte[,] FastIDCT(float[] input)
{
byte[,] output = new byte[8, 8];
#if DYNAMIC_IDCT
// Fastest, dynamic MSIL stream
dynamicIDCT(input, _temp, output);
#else
#region Slower, easy-to-read, pure C# IDCT
float temp, val = 0;
int idx = 0;
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
val = 0;
for(int k = 0; k < 8; k++)
{
val += input[i * 8 + k] * c[k, j];
}
_temp[idx++] = val;
}
}
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
temp = 128f;
for (int k = 0; k < 8; k++)
{
temp += cT[i, k] * _temp[k * 8 + j];
}
if (temp < 0) output[i, j] = 0;
else if (temp > 255) output[i, j] = 255;
else output[i, j] = (byte)(temp + 0.5); // Implements rounding
}
}
#endregion
#endif
return output;
}
#if DYNAMIC_IDCT
/// <summary>
/// Generates a pure-IL nonbranching stream of instructions
/// that perform the inverse DCT. Relies on helper function
/// SetValueClipped.
/// </summary>
/// <returns>A delegate to the DynamicMethod</returns>
private static IDCTFunc EmitIDCT()
{
Type[] args = { typeof(float[]), typeof(float[]), typeof(byte[,]) };
DynamicMethod idctMethod = new DynamicMethod("dynamicIDCT",
null, // no return type
args); // input arrays
ILGenerator il = idctMethod.GetILGenerator();
int idx = 0;
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
il.Emit(OpCodes.Ldarg_1); // 1 {temp}
il.Emit(OpCodes.Ldc_I4_S, (short)idx++); // 3 {temp, idx}
for (int k = 0; k < 8; k++)
{
il.Emit(OpCodes.Ldarg_0); // {in}
il.Emit(OpCodes.Ldc_I4_S, (short)(i * 8 + k)); // {in,idx}
il.Emit(OpCodes.Ldelem_R4); // {in[idx]}
il.Emit(OpCodes.Ldc_R4, c[k, j]); // {in[idx],c[k,j]}
il.Emit(OpCodes.Mul); // {in[idx]*c[k,j]}
if (k != 0) il.Emit(OpCodes.Add);
}
il.Emit(OpCodes.Stelem_R4); // {}
}
}
var meth = typeof(DCT).GetMethod("SetValueClipped",
BindingFlags.Static | BindingFlags.Public, null,
CallingConventions.Standard,
new Type[] {
typeof(byte[,]), // arr
typeof(int), // i
typeof(int), // j
typeof(float) } // val
, null);
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
il.Emit(OpCodes.Ldarg_2); // {output}
il.Emit(OpCodes.Ldc_I4_S, (short)i); // {output,i}
il.Emit(OpCodes.Ldc_I4_S, (short)j); // X={output,i,j}
il.Emit(OpCodes.Ldc_R4, 128.0f); // {X,128.0f}
for (int k = 0; k < 8; k++)
{
il.Emit(OpCodes.Ldarg_1); // {X,temp}
il.Emit(OpCodes.Ldc_I4_S,
(short)(k * 8 + j)); // {X,temp,idx}
il.Emit(OpCodes.Ldelem_R4); // {X,temp[idx]}
il.Emit(OpCodes.Ldc_R4, cT[i, k]); // {X,temp[idx],cT[i,k]}
il.Emit(OpCodes.Mul); // {X,in[idx]*c[k,j]}
il.Emit(OpCodes.Add);
}
il.EmitCall(OpCodes.Call, meth, null);
}
}
il.Emit(OpCodes.Ret);
return (IDCTFunc)idctMethod.CreateDelegate(typeof(IDCTFunc));
}
private delegate void IDCTFunc(float[] input, float[] temp, byte[,] output);
private static IDCTFunc dynamicIDCT = null;
#endif
}
}

View file

@ -1,121 +0,0 @@
/// Copyright (c) 2008 Jeffrey Powers for Fluxcapacity Open Source.
/// Under the MIT License, details: License.txt.
using System;
using System.Collections.Generic;
using System.Text;
namespace FluxJpeg.Core
{
public class JpegHeader
{
public byte Marker;
public byte[] Data;
internal bool IsJFIF = false;
public new string ToString { get { return Encoding.UTF8.GetString(Data, 0, Data.Length); } }
}
public class DecodedJpeg
{
private Image _image; public Image Image { get { return _image; } }
internal int[] BlockWidth;
internal int[] BlockHeight;
internal int Precision = 8;
internal int[] HsampFactor = { 1, 1, 1 };
internal int[] VsampFactor = { 1, 1, 1 };
internal bool[] lastColumnIsDummy = new bool[] { false, false, false };
internal bool[] lastRowIsDummy = new bool[] { false, false, false };
internal int[] compWidth, compHeight;
internal int MaxHsampFactor;
internal int MaxVsampFactor;
public bool HasJFIF { get; private set; }
private List<JpegHeader> _metaHeaders;
public IList<JpegHeader> MetaHeaders { get { return _metaHeaders.AsReadOnly(); } }
public DecodedJpeg(Image image, IEnumerable<JpegHeader> metaHeaders)
{
_image = image;
// Handles null as an empty list
_metaHeaders = (metaHeaders == null) ?
new List<JpegHeader>(0) : new List<JpegHeader>(metaHeaders);
// Check if the JFIF header was present
foreach (JpegHeader h in _metaHeaders)
if (h.IsJFIF) { HasJFIF = true; break; }
int components = _image.ComponentCount;
compWidth = new int[components];
compHeight = new int[components];
BlockWidth = new int[components];
BlockHeight = new int[components];
Initialize();
}
public DecodedJpeg(Image image)
: this(image, null)
{
_metaHeaders = new List<JpegHeader>();
string comment = "Jpeg Codec | fluxcapacity.net ";
_metaHeaders.Add(
new JpegHeader() {
Marker = JPEGMarker.COM,
Data = System.Text.Encoding.UTF8.GetBytes(comment)
}
);
}
/// <summary>
/// This method creates and fills three arrays, Y, Cb, and Cr using the input image.
/// </summary>
private void Initialize()
{
int w = _image.Width, h = _image.Height;
int y;
MaxHsampFactor = 1;
MaxVsampFactor = 1;
for (y = 0; y < _image.ComponentCount; y++)
{
MaxHsampFactor = Math.Max(MaxHsampFactor, HsampFactor[y]);
MaxVsampFactor = Math.Max(MaxVsampFactor, VsampFactor[y]);
}
for (y = 0; y < _image.ComponentCount; y++)
{
compWidth[y] = (((w % 8 != 0) ? ((int)Math.Ceiling((double)w / 8.0)) * 8 : w) / MaxHsampFactor) * HsampFactor[y];
if (compWidth[y] != ((w / MaxHsampFactor) * HsampFactor[y]))
{
lastColumnIsDummy[y] = true;
}
// results in a multiple of 8 for compWidthz
// this will make the rest of the program fail for the unlikely
// event that someone tries to compress an 16 x 16 pixel image
// which would of course be worse than pointless
BlockWidth[y] = (int)Math.Ceiling((double)compWidth[y] / 8.0);
compHeight[y] = (((h % 8 != 0) ? ((int)Math.Ceiling((double)h / 8.0)) * 8 : h) / MaxVsampFactor) * VsampFactor[y];
if (compHeight[y] != ((h / MaxVsampFactor) * VsampFactor[y]))
{
lastRowIsDummy[y] = true;
}
BlockHeight[y] = (int)Math.Ceiling((double)compHeight[y] / 8.0);
}
}
}
}

View file

@ -1,487 +0,0 @@
/// Copyright (c) 2008 Jeffrey Powers for Fluxcapacity Open Source.
/// Under the MIT License, details: License.txt.
// Partially derives from a Java encoder, JpegEncoder.java by James R Weeks.
// Implements Baseline JPEG Encoding http://www.opennet.ru/docs/formats/jpeg.txt
using System;
using FluxJpeg.Core.IO;
using System.IO;
using System.Collections.Generic;
namespace FluxJpeg.Core
{
internal class HuffmanTable
{
public static int HUFFMAN_MAX_TABLES = 4;
private short[] huffcode = new short[256];
private short[] huffsize = new short[256];
private short[] valptr = new short[16];
private short[] mincode = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,-1,-1};
private short[] maxcode = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
private short[] huffval;
private short[] bits;
int bufferPutBits, bufferPutBuffer;
internal int ImageHeight;
internal int ImageWidth;
internal int[,] DC_matrix0;
internal int[,] AC_matrix0;
internal int[,] DC_matrix1;
internal int[,] AC_matrix1;
internal int[][,] DC_matrix;
internal int[][,] AC_matrix;
internal int NumOfDCTables;
internal int NumOfACTables;
public List<short[]> bitsList;
public List<short[]> val;
public static byte JPEG_DC_TABLE = 0;
public static byte JPEG_AC_TABLE = 1;
private short lastk = 0;
internal HuffmanTable(JpegHuffmanTable table)
{
if (table != null)
{
huffval = table.Values;
bits = table.Lengths;
GenerateSizeTable();
GenerateCodeTable();
GenerateDecoderTables();
}
else
{
// Encode initialization
bitsList = new List<short[]>();
bitsList.Add(JpegHuffmanTable.StdDCLuminance.Lengths);
bitsList.Add(JpegHuffmanTable.StdACLuminance.Lengths);
bitsList.Add(JpegHuffmanTable.StdDCChrominance.Lengths);
bitsList.Add(JpegHuffmanTable.StdACChrominance.Lengths);
val = new List<short[]>();
val.Add(JpegHuffmanTable.StdDCLuminance.Values);
val.Add(JpegHuffmanTable.StdACLuminance.Values);
val.Add(JpegHuffmanTable.StdDCChrominance.Values);
val.Add(JpegHuffmanTable.StdACChrominance.Values);
initHuf();
}
}
/// <summary>See Figure C.1</summary>
private void GenerateSizeTable()
{
short index = 0;
for (short i = 0; i < bits.Length; i++)
{
for (short j = 0; j < bits[i]; j++)
{
huffsize[index] = (short)(i + 1);
index++;
}
}
lastk = index;
}
/// <summary>See Figure C.2</summary>
private void GenerateCodeTable()
{
short k = 0;
short si = huffsize[0];
short code = 0;
for (short i = 0; i < huffsize.Length; i++)
{
while (huffsize[k] == si)
{
huffcode[k] = code;
code++;
k++;
}
code <<= 1;
si++;
}
}
/// <summary>See figure F.15</summary>
private void GenerateDecoderTables()
{
short bitcount = 0;
for (int i = 0; i < 16; i++)
{
if (bits[i] != 0)
valptr[i] = bitcount;
for (int j = 0; j < bits[i]; j++)
{
if (huffcode[j + bitcount] < mincode[i] || mincode[i] == -1)
mincode[i] = huffcode[j + bitcount];
if (huffcode[j + bitcount] > maxcode[i])
maxcode[i] = huffcode[j + bitcount];
}
if (mincode[i] != -1)
valptr[i] = (short)(valptr[i] - mincode[i]);
bitcount += bits[i];
}
}
/// <summary>Figure F.12</summary>
public static int Extend(int diff, int t)
{
// here we use bitshift to implement 2^ ...
// NOTE: Math.Pow returns 0 for negative powers, which occassionally happen here!
int Vt = 1 << t - 1;
// WAS: int Vt = (int)Math.Pow(2, (t - 1));
if (diff < Vt)
{
Vt = (-1 << t) + 1;
diff = diff + Vt;
}
return diff;
}
/// <summary>Figure F.16 - Reads the huffman code bit-by-bit.</summary>
/*public int Decode(JPEGBinaryReader JPEGStream)
{
int i = 0;
short code = (short)JPEGStream.ReadBits(1);
while (code > maxcode[i])
{
i++;
code <<= 1;
code |= (short)JPEGStream.ReadBits(1);
}
int val = huffval[code + (valptr[i])];
if (val < 0)
val = 256 + val;
return val;
}*/
/// <summary>
/// HuffmanBlockEncoder run length encodes and Huffman encodes the quantized data.
/// </summary>
internal void HuffmanBlockEncoder(Stream outStream, int[] zigzag, int prec, int DCcode, int ACcode)
{
int temp, temp2, nbits, k, r, i;
NumOfDCTables = 2;
NumOfACTables = 2;
// The DC portion
temp = temp2 = zigzag[0] - prec;
if (temp < 0)
{
temp = -temp;
temp2--;
}
nbits = 0;
while (temp != 0)
{
nbits++;
temp >>= 1;
}
// if (nbits > 11) nbits = 11;
bufferIt(outStream,
DC_matrix[DCcode][nbits, 0],
DC_matrix[DCcode][nbits, 1]);
// The arguments in bufferIt are code and size.
if (nbits != 0)
{
bufferIt(outStream, temp2, nbits);
}
// The AC portion
r = 0;
for (k = 1; k < 64; k++)
{
if ((temp = zigzag[ ZigZag.ZigZagMap[k] ]) == 0)
{
r++;
}
else
{
while (r > 15)
{
bufferIt(outStream,
AC_matrix[ACcode][0xF0, 0],
AC_matrix[ACcode][0xF0, 1]);
r -= 16;
}
temp2 = temp;
if (temp < 0)
{
temp = -temp;
temp2--;
}
nbits = 1;
while ((temp >>= 1) != 0)
{
nbits++;
}
i = (r << 4) + nbits;
bufferIt(outStream,
AC_matrix[ACcode][i, 0],
AC_matrix[ACcode][i, 1]);
bufferIt(outStream, temp2, nbits);
r = 0;
}
}
if (r > 0)
{
bufferIt(outStream,
AC_matrix[ACcode][0, 0],
AC_matrix[ACcode][0, 1]);
}
}
/// <summary>
/// Uses an integer long (32 bits) buffer to store the Huffman encoded bits
/// and sends them to outStream by the byte.
/// </summary>
void bufferIt(Stream outStream, int code, int size)
{
int PutBuffer = code;
int PutBits = bufferPutBits;
PutBuffer &= (1 << size) - 1;
PutBits += size;
PutBuffer <<= 24 - PutBits;
PutBuffer |= bufferPutBuffer;
while (PutBits >= 8)
{
int c = ((PutBuffer >> 16) & 0xFF);
outStream.WriteByte((byte)c);
// FF must be escaped
if (c == 0xFF) outStream.WriteByte(0);
PutBuffer <<= 8;
PutBits -= 8;
}
bufferPutBuffer = PutBuffer;
bufferPutBits = PutBits;
}
public void FlushBuffer(Stream outStream)
{
int PutBuffer = bufferPutBuffer;
int PutBits = bufferPutBits;
while (PutBits >= 8)
{
int c = ((PutBuffer >> 16) & 0xFF);
outStream.WriteByte((byte)c);
// FF must be escaped
if (c == 0xFF) outStream.WriteByte(0);
PutBuffer <<= 8;
PutBits -= 8;
}
if (PutBits > 0)
{
int c = ((PutBuffer >> 16) & 0xFF);
outStream.WriteByte((byte)c);
}
}
/// <summary>
/// Initialisation of the Huffman codes for Luminance and Chrominance.
/// This code results in the same tables created in the IJG Jpeg-6a
/// library.
/// </summary>
public void initHuf()
{
DC_matrix0 = new int[12, 2];
DC_matrix1 = new int[12, 2];
AC_matrix0 = new int[255, 2];
AC_matrix1 = new int[255, 2];
DC_matrix = new int[2][,];
AC_matrix = new int[2][,];
int p, l, i, lastp, si, code;
int[] huffsize = new int[257];
int[] huffcode = new int[257];
short[] bitsDCchrominance = JpegHuffmanTable.StdDCChrominance.Lengths;
short[] bitsACchrominance = JpegHuffmanTable.StdACChrominance.Lengths;
short[] bitsDCluminance = JpegHuffmanTable.StdDCLuminance.Lengths;
short[] bitsACluminance = JpegHuffmanTable.StdACLuminance.Lengths;
short[] valDCchrominance = JpegHuffmanTable.StdDCChrominance.Values;
short[] valACchrominance = JpegHuffmanTable.StdACChrominance.Values;
short[] valDCluminance = JpegHuffmanTable.StdDCLuminance.Values;
short[] valACluminance = JpegHuffmanTable.StdACLuminance.Values;
/*
* init of the DC values for the chrominance
* [,0] is the code [,1] is the number of bit
*/
p = 0;
for (l = 0; l < 16; l++)
{
for (i = 1; i <= bitsDCchrominance[l]; i++)
{
huffsize[p++] = l+1;
}
}
huffsize[p] = 0;
lastp = p;
code = 0;
si = huffsize[0];
p = 0;
while (huffsize[p] != 0)
{
while (huffsize[p] == si)
{
huffcode[p++] = code;
code++;
}
code <<= 1;
si++;
}
for (p = 0; p < lastp; p++)
{
DC_matrix1[valDCchrominance[p], 0] = huffcode[p];
DC_matrix1[valDCchrominance[p], 1] = huffsize[p];
}
/*
* Init of the AC hufmann code for the chrominance
* matrix [,,0] is the code & matrix[,,1] is the number of bit needed
*/
p = 0;
for (l = 0; l < 16; l++)
{
for (i = 1; i <= bitsACchrominance[l]; i++)
{
huffsize[p++] = l+1;
}
}
huffsize[p] = 0;
lastp = p;
code = 0;
si = huffsize[0];
p = 0;
while (huffsize[p] != 0)
{
while (huffsize[p] == si)
{
huffcode[p++] = code;
code++;
}
code <<= 1;
si++;
}
for (p = 0; p < lastp; p++)
{
AC_matrix1[valACchrominance[p], 0] = huffcode[p];
AC_matrix1[valACchrominance[p], 1] = huffsize[p];
}
/*
* init of the DC values for the luminance
* [,0] is the code [,1] is the number of bit
*/
p = 0;
for (l = 0; l < 16; l++)
{
for (i = 1; i <= bitsDCluminance[l]; i++)
{
huffsize[p++] = l+1;
}
}
huffsize[p] = 0;
lastp = p;
code = 0;
si = huffsize[0];
p = 0;
while (huffsize[p] != 0)
{
while (huffsize[p] == si)
{
huffcode[p++] = code;
code++;
}
code <<= 1;
si++;
}
for (p = 0; p < lastp; p++)
{
DC_matrix0[valDCluminance[p], 0] = huffcode[p];
DC_matrix0[valDCluminance[p], 1] = huffsize[p];
}
/*
* Init of the AC hufmann code for luminance
* matrix [,,0] is the code & matrix[,,1] is the number of bit
*/
p = 0;
for (l = 0; l < 16; l++)
{
for (i = 1; i <= bitsACluminance[l]; i++)
{
huffsize[p++] = l+1;
}
}
huffsize[p] = 0;
lastp = p;
code = 0;
si = huffsize[0];
p = 0;
while (huffsize[p] != 0)
{
while (huffsize[p] == si)
{
huffcode[p++] = code;
code++;
}
code <<= 1;
si++;
}
for (int q = 0; q < lastp; q++)
{
AC_matrix0[valACluminance[q], 0] = huffcode[q];
AC_matrix0[valACluminance[q], 1] = huffsize[q];
}
DC_matrix[0] = DC_matrix0;
DC_matrix[1] = DC_matrix1;
AC_matrix[0] = AC_matrix0;
AC_matrix[1] = AC_matrix1;
}
}
}

View file

@ -1,702 +0,0 @@
/// Copyright (c) 2008 Jeffrey Powers for Fluxcapacity Open Source.
/// Under the MIT License, details: License.txt.
using System;
using System.Collections.Generic;
using System.Text;
using FluxJpeg.Core.IO;
using System.Reflection.Emit;
using System.Diagnostics;
namespace FluxJpeg.Core.Decoder
{
internal class JpegComponent
{
public byte factorH, factorV, component_id, quant_id;
public int width = 0, height = 0;
public HuffmanTable ACTable;
public HuffmanTable DCTable;
public int[] QuantizationTable {
set
{
quantizationTable = value;
_quant = EmitQuantize();
}
}
private int[] quantizationTable;
public float previousDC = 0;
private JpegScan parent;
// Current MCU block
float[,][] scanMCUs = null;
private List<float[,][]> scanData = new List<float[,][]>();
public int BlockCount { get { return scanData.Count; } }
private List<byte[,]> scanDecoded = new List<byte[,]>();
public int spectralStart, spectralEnd;
public int successiveLow;
public JpegComponent(JpegScan parentScan, byte id, byte factorHorizontal, byte factorVertical,
byte quantizationID, byte colorMode)
{
parent = parentScan;
/* Set default tables in case they're not provided. J. Powers */
// TODO: only gen if needed
if (colorMode == JPEGFrame.JPEG_COLOR_YCbCr)
{
if (id == 1) // Luminance
{
ACTable = new HuffmanTable(JpegHuffmanTable.StdACLuminance);
DCTable = new HuffmanTable(JpegHuffmanTable.StdDCLuminance);
}
else
{
ACTable = new HuffmanTable( JpegHuffmanTable.StdACChrominance);
DCTable = new HuffmanTable( JpegHuffmanTable.StdACLuminance);
}
}
component_id = id;
factorH = factorHorizontal;
factorV = factorVertical;
quant_id = quantizationID;
}
/// <summary>
/// If a restart marker is found with too little of an MCU count (i.e. our
/// Restart Interval is 63 and we have 61 we copy the last MCU until it's full)
/// </summary>
public void padMCU(int index, int length)
{
scanMCUs = new float[factorH, factorV][];
for(int n = 0; n < length; n++)
{
if (scanData.Count >= (index + length)) continue;
for (int i = 0; i < factorH; i++)
for (int j = 0; j < factorV; j++)
scanMCUs[i, j] = (float[])scanData[index - 1][i,j].Clone();
scanData.Add(scanMCUs);
}
}
/// <summary>
/// Reset the interval by setting the previous DC value
/// </summary>
public void resetInterval()
{
previousDC = 0;
}
private delegate void QuantizeDel(float[] arr);
private QuantizeDel _quant = null;
private QuantizeDel EmitQuantize()
{
Type[] args = { typeof(float[]) };
DynamicMethod quantizeMethod = new DynamicMethod("Quantize",
null, // no return type
args); // input array
ILGenerator il = quantizeMethod.GetILGenerator();
for (int i = 0; i < quantizationTable.Length; i++)
{
float mult = (float)quantizationTable[i];
// Sz Stack:
il.Emit(OpCodes.Ldarg_0); // 1 {arr}
il.Emit(OpCodes.Ldc_I4_S, (short)i); // 3 {arr,i}
il.Emit(OpCodes.Ldarg_0); // 1 {arr,i,arr}
il.Emit(OpCodes.Ldc_I4_S, (short)i); // 3 {arr,i,arr,i}
il.Emit(OpCodes.Ldelem_R4); // 1 {arr,i,arr[i]}
il.Emit(OpCodes.Ldc_R4, mult); // 5 {arr,i,arr[i],mult}
il.Emit(OpCodes.Mul); // 1 {arr,i,arr[i]*mult}
il.Emit(OpCodes.Stelem_R4); // 1 {}
}
il.Emit(OpCodes.Ret);
return (QuantizeDel)quantizeMethod.CreateDelegate(typeof(QuantizeDel));
}
/// <summary>
/// Run the Quantization backward method on all of the block data.
/// </summary>
public void quantizeData()
{
for (int i = 0; i < scanData.Count; i++)
{
for(int v = 0; v < factorV; v++)
for (int h = 0; h < factorH; h++)
{
// Dynamic IL method
_quant(scanData[i][h, v]);
// Old technique
//float[] toQuantize = scanData[i][h, v];
//for (int j = 0; j < 64; j++) toQuantize[j] *= quantizationTable[j];
}
}
}
public void setDCTable(JpegHuffmanTable table)
{
DCTable = new HuffmanTable(table);
}
public void setACTable(JpegHuffmanTable table)
{
ACTable = new HuffmanTable(table);
}
DCT _dct = new DCT();
/// <summary>
/// Run the Inverse DCT method on all of the block data
/// </summary>
public void idctData()
{
float[] unZZ = new float[64];
float[] toDecode = null;
for (int i = 0; i < scanData.Count; i++)
{
for (int v = 0; v < factorV; v++)
for (int h = 0; h < factorH; h++)
{
toDecode = scanData[i][h, v];
ZigZag.UnZigZag(toDecode, unZZ);
//FJCore.Profiling.IDCTWatch.Start();
scanDecoded.Add(_dct.FastIDCT(unZZ));
//FJCore.Profiling.IDCTWatch.Stop();
}
}
}
private int factorUpV { get { return parent.MaxV / factorV; } }
private int factorUpH { get { return parent.MaxH / factorH; } }
/// <summary>
/// Stretches components as needed to normalize the size of all components.
/// For example, in a 2x1 (4:2:2) sequence, the Cr and Cb channels will be
/// scaled vertically by a factor of 2.
/// </summary>
public void scaleByFactors( BlockUpsamplingMode mode )
{
int factorUpVertical = factorUpV,
factorUpHorizontal = factorUpH;
if (factorUpVertical == 1 && factorUpHorizontal == 1) return;
for (int i = 0; i < scanDecoded.Count; i++)
{
byte[,] src = scanDecoded[i];
int oldV = src.GetLength(0),
oldH = src.GetLength(1),
newV = oldV * factorUpVertical,
newH = oldH * factorUpHorizontal;
byte[,] dest = new byte[newV, newH];
switch (mode)
{
case BlockUpsamplingMode.BoxFilter:
#region Upsampling by repeating values
/* Perform scaling (Box filter) */
for (int u = 0; u < newH; u++)
{
int src_u = u / factorUpHorizontal;
for (int v = 0; v < newV; v++)
{
int src_v = v / factorUpVertical;
dest[v, u] = src[src_v, src_u];
}
}
#endregion
break;
case BlockUpsamplingMode.Interpolate:
#region Upsampling by interpolation
for (int u = 0; u < newH; u++)
{
for (int v = 0; v < newV; v++)
{
int val = 0;
for (int x = 0; x < factorUpHorizontal; x++)
{
int src_u = (u + x) / factorUpHorizontal;
if (src_u >= oldH) src_u = oldH - 1;
for (int y = 0; y < factorUpVertical; y++)
{
int src_v = (v + y) / factorUpVertical;
if (src_v >= oldV) src_v = oldV - 1;
val += src[src_v, src_u];
}
}
dest[v, u] = (byte)(val / (factorUpHorizontal * factorUpVertical));
}
}
#endregion
break;
default:
throw new ArgumentException("Upsampling mode not supported.");
}
scanDecoded[i] = dest;
}
}
public void writeBlock(byte[][,] raster, byte[,] data,
int compIndex, int x, int y)
{
int w = raster[0].GetLength(0),
h = raster[0].GetLength(1);
byte[,] comp = raster[compIndex];
// Blocks may spill over the frame so we bound by the frame size
int yMax = data.GetLength(0); if ((y + yMax) > h) yMax = h - y;
int xMax = data.GetLength(1); if ((x + xMax) > w) xMax = w - x;
for (int yIndex = 0; yIndex < yMax; yIndex++)
{
for (int xIndex = 0; xIndex < xMax; xIndex++)
{
comp[x + xIndex, y + yIndex] = data[yIndex, xIndex];
}
}
}
public void writeDataScaled(byte[][,] raster, int componentIndex, BlockUpsamplingMode mode)
{
int x = 0, y = 0, lastblockheight = 0, incrementblock = 0;
int blockIdx = 0;
int w = raster[0].GetLength(0),
h = raster[0].GetLength(1);
// Keep looping through all of the blocks until there are no more.
while (blockIdx < scanDecoded.Count)
{
int blockwidth = 0;
int blockheight = 0;
if (x >= w) { x = 0; y += incrementblock; }
// Loop through the horizontal component blocks of the MCU first
// then for each horizontal line write out all of the vertical
// components
for (int factorVIndex = 0; factorVIndex < factorV; factorVIndex++)
{
blockwidth = 0;
for (int factorHIndex = 0; factorHIndex < factorH; factorHIndex++)
{
// Captures the width of this block so we can increment the X coordinate
byte[,] blockdata = scanDecoded[blockIdx++];
// Writes the data at the specific X and Y coordinate of this component
writeBlockScaled(raster, blockdata, componentIndex, x, y, mode);
blockwidth += blockdata.GetLength(1) * factorUpH;
x += blockdata.GetLength(1) * factorUpH;
blockheight = blockdata.GetLength(0) * factorUpV;
}
y += blockheight;
x -= blockwidth;
lastblockheight += blockheight;
}
y -= lastblockheight;
incrementblock = lastblockheight;
lastblockheight = 0;
x += blockwidth;
}
}
private void writeBlockScaled(byte[][,] raster, byte[,] blockdata, int compIndex, int x, int y, BlockUpsamplingMode mode)
{
int w = raster[0].GetLength(0),
h = raster[0].GetLength(1);
int factorUpVertical = factorUpV,
factorUpHorizontal = factorUpH;
int oldV = blockdata.GetLength(0),
oldH = blockdata.GetLength(1),
newV = oldV * factorUpVertical,
newH = oldH * factorUpHorizontal;
byte[,] comp = raster[compIndex];
// Blocks may spill over the frame so we bound by the frame size
int yMax = newV; if ((y + yMax) > h) yMax = h - y;
int xMax = newH; if ((x + xMax) > w) xMax = w - x;
switch (mode)
{
case BlockUpsamplingMode.BoxFilter:
#region Upsampling by repeating values
// Special case 1: No scale-up
if (factorUpVertical == 1 && factorUpHorizontal == 1)
{
for (int u = 0; u < xMax; u++)
for (int v = 0; v < yMax; v++)
comp[u + x, y + v] = blockdata[v, u];
}
// Special case 2: Perform scale-up 4 pixels at a time
else if (factorUpHorizontal == 2 &&
factorUpVertical == 2 &&
xMax == newH && yMax == newV)
{
for (int src_u = 0; src_u < oldH; src_u++)
{
int bx = src_u * 2 + x;
for ( int src_v = 0; src_v < oldV; src_v++)
{
byte val = blockdata[src_v, src_u];
int by = src_v * 2 + y;
comp[bx, by] = val;
comp[bx, by + 1] = val;
comp[bx + 1, by] = val;
comp[bx + 1, by + 1] = val;
}
}
}
else
{
/* Perform scaling (Box filter) */
for (int u = 0; u < xMax; u++)
{
int src_u = u / factorUpHorizontal;
for (int v = 0; v < yMax; v++)
{
int src_v = v / factorUpVertical;
comp[u + x, y + v] = blockdata[src_v, src_u];
}
}
}
#endregion
break;
// JRP 4/7/08 -- This mode is disabled temporarily as it needs to be fixed after
// recent performance tweaks.
// It can produce slightly better (less blocky) decodings.
//case BlockUpsamplingMode.Interpolate:
// #region Upsampling by interpolation
// for (int u = 0; u < newH; u++)
// {
// for (int v = 0; v < newV; v++)
// {
// int val = 0;
// for (int x = 0; x < factorUpHorizontal; x++)
// {
// int src_u = (u + x) / factorUpHorizontal;
// if (src_u >= oldH) src_u = oldH - 1;
// for (int y = 0; y < factorUpVertical; y++)
// {
// int src_v = (v + y) / factorUpVertical;
// if (src_v >= oldV) src_v = oldV - 1;
// val += src[src_v, src_u];
// }
// }
// dest[v, u] = (byte)(val / (factorUpHorizontal * factorUpVertical));
// }
// }
// #endregion
// break;
default:
throw new ArgumentException("Upsampling mode not supported.");
}
}
internal delegate void DecodeFunction(JPEGBinaryReader jpegReader, float[] zigzagMCU);
public DecodeFunction Decode;
public void DecodeBaseline(JPEGBinaryReader stream, float[] dest)
{
float dc = decode_dc_coefficient(stream);
decode_ac_coefficients(stream, dest);
dest[0] = dc;
}
public void DecodeDCFirst(JPEGBinaryReader stream, float[] dest)
{
float[] datablock = new float[64];
int s = DCTable.Decode(stream);
int r = stream.ReadBits(s);
s = HuffmanTable.Extend(r, s);
s = (int)previousDC + s;
previousDC = s;
dest[0] = s << successiveLow;
}
public void DecodeACFirst(JPEGBinaryReader stream, float[] zz)
{
if (stream.eob_run > 0)
{
stream.eob_run--;
return;
}
for (int k = spectralStart; k <= spectralEnd; k++)
{
int s = ACTable.Decode(stream);
int r = s >> 4;
s &= 15;
if (s != 0)
{
k += r;
r = (int)stream.ReadBits(s);
s = (int)HuffmanTable.Extend(r, s);
zz[k] = s << successiveLow;
}
else
{
if (r != 15)
{
stream.eob_run = 1 << r;
if (r != 0)
stream.eob_run += stream.ReadBits(r);
stream.eob_run--;
break;
}
k += 15;
}
}
}
public void DecodeDCRefine(JPEGBinaryReader stream, float[] dest)
{
if (stream.ReadBits(1) == 1)
{
dest[0] = (int)dest[0] | (1 << successiveLow);
}
}
public void DecodeACRefine(JPEGBinaryReader stream, float[] dest)
{
int p1 = 1 << successiveLow;
int m1 = (-1) << successiveLow;
int k = spectralStart;
if (stream.eob_run == 0)
for (; k <= spectralEnd; k++)
{
#region Decode and check S
int s = ACTable.Decode(stream);
int r = s >> 4;
s &= 15;
if (s != 0)
{
if (s != 1)
throw new Exception("Decode Error");
if (stream.ReadBits(1) == 1)
s = p1;
else
s = m1;
}
else
{
if (r != 15)
{
stream.eob_run = 1 << r;
if (r > 0)
stream.eob_run += stream.ReadBits(r);
break;
}
} // if (s != 0)
#endregion
// Apply the update
do
{
if (dest[k] != 0)
{
if (stream.ReadBits(1) == 1)
{
if (((int)dest[k] & p1) == 0)
{
if (dest[k] >= 0)
dest[k] += p1;
else
dest[k] += m1;
}
}
}
else
{
if (--r < 0)
break;
}
k++;
} while (k <= spectralEnd);
if( (s != 0) && k < 64)
{
dest[k] = s;
}
} // for k = start ... end
if (stream.eob_run > 0)
{
for (; k <= spectralEnd; k++)
{
if (dest[k] != 0)
{
if (stream.ReadBits(1) == 1)
{
if (((int)dest[k] & p1) == 0)
{
if (dest[k] >= 0)
dest[k] += p1;
else
dest[k] += m1;
}
}
}
}
stream.eob_run--;
}
}
public void SetBlock(int idx)
{
if (scanData.Count < idx)
throw new Exception("Invalid block ID.");
// expand the data list
if (scanData.Count == idx)
{
scanMCUs = new float[factorH, factorV][];
for (int i = 0; i < factorH; i++)
for (int j = 0; j < factorV; j++)
scanMCUs[i, j] = new float[64];
scanData.Add(scanMCUs);
}
else // reference an existing block
{
scanMCUs = scanData[idx];
}
}
public void DecodeMCU(JPEGBinaryReader jpegReader, int i, int j)
{
Decode(jpegReader, scanMCUs[i,j]);
}
/// <summary>
/// Generated from text on F-22, F.2.2.1 - Huffman decoding of DC
/// coefficients on ISO DIS 10918-1. Requirements and Guidelines.
/// </summary>
/// <param name="JPEGStream">Stream that contains huffman bits</param>
/// <returns>DC coefficient</returns>
public float decode_dc_coefficient(JPEGBinaryReader JPEGStream)
{
int t = DCTable.Decode(JPEGStream);
float diff = JPEGStream.ReadBits(t);
diff = HuffmanTable.Extend((int)diff, t);
diff = (previousDC + diff);
previousDC = diff;
return diff;
}
/// <summary>
/// Generated from text on F-23, F.13 - Huffman decoded of AC coefficients
/// on ISO DIS 10918-1. Requirements and Guidelines.
/// </summary>
internal void decode_ac_coefficients(JPEGBinaryReader JPEGStream, float[] zz)
{
for (int k = 1; k < 64; k++)
{
int s = ACTable.Decode(JPEGStream);
int r = s >> 4;
s &= 15;
if (s != 0)
{
k += r;
r = (int)JPEGStream.ReadBits(s);
s = (int)HuffmanTable.Extend(r, s);
zz[k] = s;
}
else
{
if (r != 15)
{
//throw new JPEGMarkerFoundException();
return;
}
k += 15;
}
}
}
}
}

View file

@ -1,614 +0,0 @@
/// Copyright (c) 2008 Jeffrey Powers for Fluxcapacity Open Source.
/// Under the MIT License, details: License.txt.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using FluxJpeg.Core.IO;
using System.Diagnostics;
namespace FluxJpeg.Core.Decoder
{
public enum BlockUpsamplingMode {
/// <summary> The simplest upsampling mode. Produces sharper edges. </summary>
BoxFilter,
/// <summary> Smoother upsampling. May improve color spread for some images. </summary>
Interpolate
}
public class JpegDecodeProgressChangedArgs : EventArgs
{
public bool SizeReady;
public int Width;
public int Height;
public bool Abort;
public long ReadPosition; // 0 to input stream length
public double DecodeProgress; // 0 to 1.0
}
public class JpegDecoder
{
public static long ProgressUpdateByteInterval = 100;
public event EventHandler<JpegDecodeProgressChangedArgs> DecodeProgressChanged;
private JpegDecodeProgressChangedArgs DecodeProgress = new JpegDecodeProgressChangedArgs();
public BlockUpsamplingMode BlockUpsamplingMode { get; set; }
byte majorVersion, minorVersion;
private enum UnitType { None = 0, Inches = 1, Centimeters = 2 };
UnitType Units;
ushort XDensity, YDensity;
byte Xthumbnail, Ythumbnail;
byte[] thumbnail;
Image image;
int width;
int height;
bool progressive = false;
byte marker;
/// <summary>
/// This decoder expects JFIF 1.02 encoding.
/// </summary>
internal const byte MAJOR_VERSION = (byte)1;
internal const byte MINOR_VERSION = (byte)2;
/// <summary>
/// The length of the JFIF field not including thumbnail data.
/// </summary>
internal static short JFIF_FIXED_LENGTH = 16;
/// <summary>
/// The length of the JFIF extension field not including extension data.
/// </summary>
internal static short JFXX_FIXED_LENGTH = 8;
private JPEGBinaryReader jpegReader;
List<JPEGFrame> jpegFrames = new List<JPEGFrame>();
JpegHuffmanTable[] dcTables = new JpegHuffmanTable[4];
JpegHuffmanTable[] acTables = new JpegHuffmanTable[4];
JpegQuantizationTable[] qTables = new JpegQuantizationTable[4];
public JpegDecoder(Stream input)
{
jpegReader = new JPEGBinaryReader(input);
if (jpegReader.GetNextMarker() != JPEGMarker.SOI)
throw new Exception("Failed to find SOI marker.");
}
/// <summary>
/// Tries to parse the JFIF APP0 header
/// See http://en.wikipedia.org/wiki/JFIF
/// </summary>
private bool TryParseJFIF(byte[] data)
{
IO.BinaryReader reader = new IO.BinaryReader(new MemoryStream(data));
int length = data.Length + 2; // Data & length
if (!(length >= JFIF_FIXED_LENGTH))
return false; // Header's too small.
byte[] identifier = new byte[5];
reader.Read(identifier, 0, identifier.Length);
if (identifier[0] != JPEGMarker.JFIF_J
|| identifier[1] != JPEGMarker.JFIF_F
|| identifier[2] != JPEGMarker.JFIF_I
|| identifier[3] != JPEGMarker.JFIF_F
|| identifier[4] != JPEGMarker.X00)
return false; // Incorrect bytes
majorVersion = reader.ReadByte();
minorVersion = reader.ReadByte();
if (majorVersion != MAJOR_VERSION
|| (majorVersion == MAJOR_VERSION
&& minorVersion > MINOR_VERSION)) // changed from <
return false; // Unsupported version
Units = (UnitType)reader.ReadByte();
if (Units != UnitType.None &&
Units != UnitType.Inches &&
Units != UnitType.Centimeters)
return false; // Invalid units
XDensity = reader.ReadShort();
YDensity = reader.ReadShort();
Xthumbnail = reader.ReadByte();
Ythumbnail = reader.ReadByte();
// 3 * for RGB data
int thumbnailLength = 3 * Xthumbnail * Ythumbnail;
if (length > JFIF_FIXED_LENGTH
&& thumbnailLength != length - JFIF_FIXED_LENGTH)
return false; // Thumbnail fields invalid
if (thumbnailLength > 0)
{
thumbnail = new byte[thumbnailLength];
if (reader.Read(thumbnail, 0, thumbnailLength) != thumbnailLength)
return false; // Thumbnail data was missing!
}
return true;
}
public DecodedJpeg Decode()
{
// The frames in this jpeg are loaded into a list. There is
// usually just one frame except in heirarchial progression where
// there are multiple frames.
JPEGFrame frame = null;
// The restart interval defines how many MCU's we should have
// between the 8-modulo restart marker. The restart markers allow
// us to tell whether or not our decoding process is working
// correctly, also if there is corruption in the image we can
// recover with these restart intervals. (See RSTm DRI).
int resetInterval = 0;
bool haveMarker = false;
bool foundJFIF = false;
List<JpegHeader> headers = new List<JpegHeader>();
// Loop through until there are no more markers to read in, at
// that point everything is loaded into the jpegFrames array and
// can be processed.
while (true)
{
if (DecodeProgress.Abort) return null;
#region Switch over marker types
switch (marker)
{
case JPEGMarker.APP0:
// APP1 is used for EXIF data
case JPEGMarker.APP1:
// Seldomly, APP2 gets used for extended EXIF, too
case JPEGMarker.APP2:
case JPEGMarker.APP3:
case JPEGMarker.APP4:
case JPEGMarker.APP5:
case JPEGMarker.APP6:
case JPEGMarker.APP7:
case JPEGMarker.APP8:
case JPEGMarker.APP9:
case JPEGMarker.APP10:
case JPEGMarker.APP11:
case JPEGMarker.APP12:
case JPEGMarker.APP13:
case JPEGMarker.APP14:
case JPEGMarker.APP15:
// COM: Comment
case JPEGMarker.COM:
// Debug.WriteLine(string.Format("Extracting Header, Type={0:X}", marker));
JpegHeader header = ExtractHeader();
#region Check explicitly for Exif Data
if (header.Marker == JPEGMarker.APP1 && header.Data.Length >= 6)
{
byte[] d = header.Data;
if( d[0] == 'E' &&
d[1] == 'x' &&
d[2] == 'i' &&
d[3] == 'f' &&
d[4] == 0 &&
d[5] == 0)
{
// Exif. Do something?
}
}
#endregion
#region Check for Adobe header
if (header.Data.Length >= 5 && header.Marker == JPEGMarker.APP14)
{
string asText = UTF8Encoding.UTF8.GetString(header.Data, 0, 5);
if (asText == "Adobe") {
// ADOBE HEADER. Do anything?
}
}
#endregion
headers.Add(header);
if (!foundJFIF && marker == JPEGMarker.APP0)
{
foundJFIF = TryParseJFIF(header.Data);
if (foundJFIF) // Found JFIF... do JFIF extension follow?
{
header.IsJFIF = true;
marker = jpegReader.GetNextMarker();
// Yes, they do.
if (marker == JPEGMarker.APP0)
{
header = ExtractHeader();
headers.Add(header);
}
else // No. Delay processing this one.
haveMarker = true;
}
}
break;
case JPEGMarker.SOF0:
case JPEGMarker.SOF2:
// SOFn Start of Frame Marker, Baseline DCT - This is the start
// of the frame header that defines certain variables that will
// be carried out through the rest of the encoding. Multiple
// frames are used in a hierarchical system, however most JPEG's
// only contain a single frame.
// Progressive or baseline?
progressive = marker == JPEGMarker.SOF2;
jpegFrames.Add(new JPEGFrame());
frame = (JPEGFrame)jpegFrames[jpegFrames.Count - 1];
frame.ProgressUpdateMethod = new Action<long>(UpdateStreamProgress);
// Skip the frame length.
jpegReader.ReadShort();
// Bits percision, either 8 or 12.
frame.setPrecision(jpegReader.ReadByte());
// Scan lines (height)
frame.ScanLines = jpegReader.ReadShort();
// Scan samples per line (width)
frame.SamplesPerLine = jpegReader.ReadShort();
// Number of Color Components (channels).
frame.ComponentCount = jpegReader.ReadByte();
DecodeProgress.Height = frame.Height;
DecodeProgress.Width = frame.Width;
DecodeProgress.SizeReady = true;
if(DecodeProgressChanged != null)
{
DecodeProgressChanged(this, DecodeProgress);
if (DecodeProgress.Abort) return null;
}
// Add all of the necessary components to the frame.
for (int i = 0; i < frame.ComponentCount; i++)
{
byte compId = jpegReader.ReadByte();
byte sampleFactors = jpegReader.ReadByte();
byte qTableId = jpegReader.ReadByte();
byte sampleHFactor = (byte)(sampleFactors >> 4);
byte sampleVFactor = (byte)(sampleFactors & 0x0f);
frame.AddComponent(compId, sampleHFactor, sampleVFactor, qTableId);
}
break;
case JPEGMarker.DHT:
// DHT non-SOF Marker - Huffman Table is required for decoding
// the JPEG stream, when we receive a marker we load in first
// the table length (16 bits), the table class (4 bits), table
// identifier (4 bits), then we load in 16 bytes and each byte
// represents the count of bytes to load in for each of the 16
// bytes. We load this into an array to use later and move on 4
// huffman tables can only be used in an image.
int huffmanLength = (jpegReader.ReadShort() - 2);
// Keep looping until we are out of length.
int index = huffmanLength;
// Multiple tables may be defined within a DHT marker. This
// will keep reading until there are no tables left, most
// of the time there are just one tables.
while (index > 0)
{
// Read the identifier information and class
// information about the Huffman table, then read the
// 16 byte codelength in and read in the Huffman values
// and put it into table info.
byte huffmanInfo = jpegReader.ReadByte();
byte tableClass = (byte)(huffmanInfo >> 4);
byte huffmanIndex = (byte)(huffmanInfo & 0x0f);
short[] codeLength = new short[16];
for (int i = 0; i < codeLength.Length; i++)
codeLength[i] = jpegReader.ReadByte();
int huffmanValueLen = 0;
for (int i = 0; i < 16; i++)
huffmanValueLen += codeLength[i];
index -= (huffmanValueLen + 17);
short[] huffmanVal = new short[huffmanValueLen];
for (int i = 0; i < huffmanVal.Length; i++)
{
huffmanVal[i] = jpegReader.ReadByte();
}
// Assign DC Huffman Table.
if (tableClass == HuffmanTable.JPEG_DC_TABLE)
dcTables[(int)huffmanIndex] = new JpegHuffmanTable(codeLength, huffmanVal);
// Assign AC Huffman Table.
else if (tableClass == HuffmanTable.JPEG_AC_TABLE)
acTables[(int)huffmanIndex] = new JpegHuffmanTable(codeLength, huffmanVal);
}
break;
case JPEGMarker.DQT:
// DQT non-SOF Marker - This defines the quantization
// coeffecients, this allows us to figure out the quality of
// compression and unencode the data. The data is loaded and
// then stored in to an array.
short quantizationLength = (short)(jpegReader.ReadShort() - 2);
for (int j = 0; j < quantizationLength / 65; j++)
{
byte quantSpecs = jpegReader.ReadByte();
int[] quantData = new int[64];
if ((byte)(quantSpecs >> 4) == 0)
// Precision 8 bit.
{
for (int i = 0; i < 64; i++)
quantData[i] = jpegReader.ReadByte();
}
else if ((byte)(quantSpecs >> 4) == 1)
// Precision 16 bit.
{
for (int i = 0; i < 64; i++)
quantData[i] = jpegReader.ReadShort();
}
qTables[(int)(quantSpecs & 0x0f)] = new JpegQuantizationTable(quantData);
}
break;
case JPEGMarker.SOS:
Debug.WriteLine("Start of Scan (SOS)");
// SOS non-SOF Marker - Start Of Scan Marker, this is where the
// actual data is stored in a interlaced or non-interlaced with
// from 1-4 components of color data, if three components most
// likely a YCrCb model, this is a fairly complex process.
// Read in the scan length.
ushort scanLen = jpegReader.ReadShort();
// Number of components in the scan.
byte numberOfComponents = jpegReader.ReadByte();
byte[] componentSelector = new byte[numberOfComponents];
for (int i = 0; i < numberOfComponents; i++)
{
// Component ID, packed byte containing the Id for the
// AC table and DC table.
byte componentID = jpegReader.ReadByte();
byte tableInfo = jpegReader.ReadByte();
int DC = (tableInfo >> 4) & 0x0f;
int AC = (tableInfo) & 0x0f;
frame.setHuffmanTables(componentID,
acTables[(byte)AC],
dcTables[(byte)DC]);
componentSelector[i] = componentID;
}
byte startSpectralSelection = jpegReader.ReadByte();
byte endSpectralSelection = jpegReader.ReadByte();
byte successiveApproximation = jpegReader.ReadByte();
#region Baseline JPEG Scan Decoding
if (!progressive)
{
frame.DecodeScanBaseline(numberOfComponents, componentSelector, resetInterval, jpegReader, ref marker);
haveMarker = true; // use resultant marker for the next switch(..)
}
#endregion
#region Progressive JPEG Scan Decoding
if (progressive)
{
frame.DecodeScanProgressive(
successiveApproximation, startSpectralSelection, endSpectralSelection,
numberOfComponents, componentSelector, resetInterval, jpegReader, ref marker);
haveMarker = true; // use resultant marker for the next switch(..)
}
#endregion
break;
case JPEGMarker.DRI:
jpegReader.BaseStream.Seek(2, System.IO.SeekOrigin.Current);
resetInterval = jpegReader.ReadShort();
break;
/// Defines the number of lines. (Not usually present)
case JPEGMarker.DNL:
frame.ScanLines = jpegReader.ReadShort();
break;
/// End of Image. Finish the decode.
case JPEGMarker.EOI:
if (jpegFrames.Count == 0)
{
throw new NotSupportedException("No JPEG frames could be located.");
}
else if (jpegFrames.Count == 1)
{
// Only one frame, JPEG Non-Heirarchial Frame.
byte[][,] raster = Image.CreateRaster(frame.Width, frame.Height, frame.ComponentCount);
IList<JpegComponent> components = frame.Scan.Components;
int totalSteps = components.Count * 3; // Three steps per loop
int stepsFinished = 0;
for(int i = 0; i < components.Count; i++)
{
JpegComponent comp = components[i];
comp.QuantizationTable = qTables[comp.quant_id].Table;
// 1. Quantize
comp.quantizeData();
UpdateProgress(++stepsFinished, totalSteps);
// 2. Run iDCT (expensive)
comp.idctData();
UpdateProgress(++stepsFinished, totalSteps);
// 3. Scale the image and write the data to the raster.
comp.writeDataScaled(raster, i, BlockUpsamplingMode);
UpdateProgress(++stepsFinished, totalSteps);
// Ensure garbage collection.
comp = null; GC.Collect();
}
// Grayscale Color Image (1 Component).
if (frame.ComponentCount == 1)
{
ColorModel cm = new ColorModel() { colorspace = ColorSpace.Gray, Opaque = true };
image = new Image(cm, raster);
}
// YCbCr Color Image (3 Components).
else if (frame.ComponentCount == 3)
{
ColorModel cm = new ColorModel() { colorspace = ColorSpace.YCbCr, Opaque = true };
image = new Image(cm, raster);
}
// Possibly CMYK or RGBA ?
else
{
throw new NotSupportedException("Unsupported Color Mode: 4 Component Color Mode found.");
}
// If needed, convert centimeters to inches.
Func<double, double> conv = x =>
Units == UnitType.Inches ? x : x / 2.54;
image.DensityX = conv(XDensity);
image.DensityY = conv(YDensity);
height = frame.Height;
width = frame.Width;
}
else
{
// JPEG Heirarchial Frame
throw new NotSupportedException("Unsupported Codec Type: Hierarchial JPEG");
}
break;
// Only SOF0 (baseline) and SOF2 (progressive) are supported by FJCore
case JPEGMarker.SOF1:
case JPEGMarker.SOF3:
case JPEGMarker.SOF5:
case JPEGMarker.SOF6:
case JPEGMarker.SOF7:
case JPEGMarker.SOF9:
case JPEGMarker.SOF10:
case JPEGMarker.SOF11:
case JPEGMarker.SOF13:
case JPEGMarker.SOF14:
case JPEGMarker.SOF15:
throw new NotSupportedException("Unsupported codec type.");
default: break; // ignore
}
#endregion switch over markers
if (haveMarker) haveMarker = false;
else
{
try
{
marker = jpegReader.GetNextMarker();
}
catch (System.IO.EndOfStreamException)
{
break; /* done reading the file */
}
}
}
DecodedJpeg result = new DecodedJpeg(image, headers);
return result;
}
private JpegHeader ExtractHeader()
{
#region Extract the header
int length = jpegReader.ReadShort() - 2;
byte[] data = new byte[length];
jpegReader.Read(data, 0, length);
#endregion
JpegHeader header = new JpegHeader()
{
Marker = marker,
Data = data
};
return header;
}
#region Decode Progress Monitoring
private void UpdateStreamProgress(long StreamPosition)
{
if (DecodeProgressChanged != null)
{
DecodeProgress.ReadPosition = StreamPosition;
DecodeProgressChanged(this, DecodeProgress);
};
}
private void UpdateProgress(int stepsFinished, int stepsTotal)
{
if (DecodeProgressChanged != null)
{
DecodeProgress.DecodeProgress = (double)stepsFinished / stepsTotal;
DecodeProgressChanged(this, DecodeProgress);
};
}
#endregion
}
}

View file

@ -1,283 +0,0 @@
/// Copyright (c) 2008 Jeffrey Powers for Fluxcapacity Open Source.
/// Under the MIT License, details: License.txt.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FluxJpeg.Core.IO;
namespace FluxJpeg.Core.Decoder
{
internal class JPEGFrame
{
public static byte JPEG_COLOR_GRAY = 1;
public static byte JPEG_COLOR_RGB = 2;
public static byte JPEG_COLOR_YCbCr = 3;
public static byte JPEG_COLOR_CMYK = 4;
public byte precision = 8;
public byte colorMode = JPEGFrame.JPEG_COLOR_YCbCr;
public ushort Width { get; private set; }
public ushort Height { get; private set; }
public JpegScan Scan = new JpegScan();
public Action<long> ProgressUpdateMethod = null;
public void AddComponent(byte componentID, byte sampleHFactor, byte sampleVFactor,
byte quantizationTableID)
{
Scan.AddComponent(componentID, sampleHFactor, sampleVFactor, quantizationTableID, colorMode);
}
public void setPrecision(byte data) { precision = data; }
public ushort ScanLines { set { Height = value; } }
public ushort SamplesPerLine { set { Width = value; } }
public byte ColorMode { get {
return ComponentCount == 1 ?
JPEGFrame.JPEG_COLOR_GRAY :
JPEGFrame.JPEG_COLOR_YCbCr;
}
}
public byte ComponentCount { get ; set; }
public void setHuffmanTables(byte componentID, JpegHuffmanTable ACTable, JpegHuffmanTable DCTable)
{
JpegComponent comp = Scan.GetComponentById(componentID);
if(DCTable != null) comp.setDCTable(DCTable);
if(ACTable != null) comp.setACTable(ACTable);
}
public void DecodeScanBaseline(byte numberOfComponents, byte[] componentSelector, int resetInterval, JPEGBinaryReader jpegReader, ref byte marker)
{
// Set the decode function for all the components
for (int compIndex = 0; compIndex < numberOfComponents; compIndex++)
{
JpegComponent comp = Scan.GetComponentById(componentSelector[compIndex]);
comp.Decode = comp.DecodeBaseline;
}
DecodeScan(numberOfComponents, componentSelector, resetInterval, jpegReader, ref marker);
}
private int mcus_per_row(JpegComponent c)
{
return (((( Width * c.factorH ) + ( Scan.MaxH - 1)) / Scan.MaxH) + 7) / 8;
}
private void DecodeScan(byte numberOfComponents, byte[] componentSelector, int resetInterval, JPEGBinaryReader jpegReader, ref byte marker)
{
//TODO: not necessary
jpegReader.eob_run = 0;
int mcuIndex = 0;
int mcuTotalIndex = 0;
// This loops through until a MarkerTagFound exception is
// found, if the marker tag is a RST (Restart Marker) it
// simply skips it and moves on this system does not handle
// corrupt data streams very well, it could be improved by
// handling misplaced restart markers.
int h = 0, v = 0;
int x = 0;
long lastPosition = jpegReader.BaseStream.Position;
//TODO: replace this with a loop which knows how much data to expect
while (true)
{
#region Inform caller of decode progress
if (ProgressUpdateMethod != null)
{
if (jpegReader.BaseStream.Position >= lastPosition + JpegDecoder.ProgressUpdateByteInterval)
{
lastPosition = jpegReader.BaseStream.Position;
ProgressUpdateMethod(lastPosition);
}
}
#endregion
try
{
// Loop though capturing MCU, instruct each
// component to read in its necessary count, for
// scaling factors the components automatically
// read in how much they need
// Sec A.2.2 from CCITT Rec. T.81 (1992 E)
bool interleaved = !(numberOfComponents == 1);
if (!interleaved)
{
JpegComponent comp = Scan.GetComponentById(componentSelector[0]);
comp.SetBlock(mcuIndex);
comp.DecodeMCU(jpegReader, h, v);
int mcus_per_line = mcus_per_row(comp);
int blocks_per_line = (int) Math.Ceiling((double)this.Width / (8 * comp.factorH));
// TODO: Explain the non-interleaved scan ------
h++; x++;
if (h == comp.factorH)
{
h = 0; mcuIndex++;
}
if( (x % mcus_per_line) == 0)
{
x = 0;
v++;
if (v == comp.factorV)
{
if (h != 0) { mcuIndex++; h = 0; }
v = 0;
}
else
{
mcuIndex -= blocks_per_line;
// we were mid-block
if (h != 0) { mcuIndex++; h = 0; }
}
}
// -----------------------------------------------
}
else // Components are interleaved
{
for (int compIndex = 0; compIndex < numberOfComponents; compIndex++)
{
JpegComponent comp = Scan.GetComponentById(componentSelector[compIndex]);
comp.SetBlock(mcuTotalIndex);
for (int j = 0; j < comp.factorV; j++)
for (int i = 0; i < comp.factorH; i++)
{
comp.DecodeMCU(jpegReader, i, j);
}
}
mcuIndex++;
mcuTotalIndex++;
}
}
// We've found a marker, see if the marker is a restart
// marker or just the next marker in the stream. If
// it's the next marker in the stream break out of the
// while loop, if it's just a restart marker skip it
catch (JPEGMarkerFoundException ex)
{
marker = ex.Marker;
// Handle JPEG Restart Markers, this is where the
// count of MCU's per interval is compared with
// the count actually obtained, if it's short then
// pad on some MCU's ONLY for components that are
// greater than one. Also restart the DC prediction
// to zero.
if (marker == JPEGMarker.RST0
|| marker == JPEGMarker.RST1
|| marker == JPEGMarker.RST2
|| marker == JPEGMarker.RST3
|| marker == JPEGMarker.RST4
|| marker == JPEGMarker.RST5
|| marker == JPEGMarker.RST6
|| marker == JPEGMarker.RST7)
{
for (int compIndex = 0; compIndex < numberOfComponents; compIndex++)
{
JpegComponent comp = Scan.GetComponentById(componentSelector[compIndex]);
if (compIndex > 1)
comp.padMCU(mcuTotalIndex, resetInterval - mcuIndex);
comp.resetInterval();
}
mcuTotalIndex += (resetInterval - mcuIndex);
mcuIndex = 0;
}
else
{
break; // We're at the end of our scan, exit out.
}
}
}
}
public void DecodeScanProgressive(byte successiveApproximation, byte startSpectralSelection, byte endSpectralSelection,
byte numberOfComponents, byte[] componentSelector, int resetInterval, JPEGBinaryReader jpegReader, ref byte marker)
{
byte successiveHigh = (byte)(successiveApproximation >> 4);
byte successiveLow = (byte)(successiveApproximation & 0x0f);
if ((startSpectralSelection > endSpectralSelection) || (endSpectralSelection > 63))
throw new Exception("Bad spectral selection.");
bool dcOnly = startSpectralSelection == 0;
bool refinementScan = (successiveHigh != 0);
if (dcOnly) // DC scan
{
if (endSpectralSelection != 0)
throw new Exception("Bad spectral selection for DC only scan.");
}
else // AC scan
{
if (numberOfComponents > 1)
throw new Exception("Too many components for AC scan!");
}
// Set the decode function for all the components
// TODO: set this for the scan and let the component figure it out
for (int compIndex = 0; compIndex < numberOfComponents; compIndex++)
{
JpegComponent comp = Scan.GetComponentById(componentSelector[compIndex]);
comp.successiveLow = successiveLow;
if (dcOnly)
{
if (refinementScan) // DC refine
comp.Decode = comp.DecodeDCRefine;
else // DC first
comp.Decode = comp.DecodeDCFirst;
}
else
{
comp.spectralStart = startSpectralSelection;
comp.spectralEnd = endSpectralSelection;
if (refinementScan) // AC refine
comp.Decode = comp.DecodeACRefine;
else // AC first
comp.Decode = comp.DecodeACFirst;
}
}
DecodeScan(numberOfComponents, componentSelector, resetInterval, jpegReader, ref marker);
}
}
}

View file

@ -1,183 +0,0 @@
/// Copyright (c) 2008 Jeffrey Powers for Fluxcapacity Open Source.
/// Under the MIT License, details: License.txt.
using System;
using System.Linq;
namespace FluxJpeg.Core
{
/// <summary>
/// The JPEGHuffmanTable class represents a Huffman table read from a
/// JPEG image file. The standard JPEG AC and DC chrominance and
/// luminance values are provided as static fields.
/// </summary>
internal class JpegHuffmanTable
{
private short[] lengths;
private short[] values;
#region Standard JPEG Huffman Tables
public static JpegHuffmanTable StdACChrominance =
new JpegHuffmanTable(new short[] { 0, 2, 1, 2, 4, 4, 3, 4, 7, 5,
4, 4, 0, 1, 2, 0x77 },
new short[] { 0x00, 0x01, 0x02, 0x03, 0x11,
0x04, 0x05, 0x21, 0x31, 0x06,
0x12, 0x41, 0x51, 0x07, 0x61,
0x71, 0x13, 0x22, 0x32, 0x81,
0x08, 0x14, 0x42, 0x91, 0xa1,
0xb1, 0xc1, 0x09, 0x23, 0x33,
0x52, 0xf0, 0x15, 0x62, 0x72,
0xd1, 0x0a, 0x16, 0x24, 0x34,
0xe1, 0x25, 0xf1, 0x17, 0x18,
0x19, 0x1a, 0x26, 0x27, 0x28,
0x29, 0x2a, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3a, 0x43, 0x44,
0x45, 0x46, 0x47, 0x48, 0x49,
0x4a, 0x53, 0x54, 0x55, 0x56,
0x57, 0x58, 0x59, 0x5a, 0x63,
0x64, 0x65, 0x66, 0x67, 0x68,
0x69, 0x6a, 0x73, 0x74, 0x75,
0x76, 0x77, 0x78, 0x79, 0x7a,
0x82, 0x83, 0x84, 0x85, 0x86,
0x87, 0x88, 0x89, 0x8a, 0x92,
0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9a, 0xa2, 0xa3,
0xa4, 0xa5, 0xa6, 0xa7, 0xa8,
0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
0xb5, 0xb6, 0xb7, 0xb8, 0xb9,
0xba, 0xc2, 0xc3, 0xc4, 0xc5,
0xc6, 0xc7, 0xc8, 0xc9, 0xca,
0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
0xd7, 0xd8, 0xd9, 0xda, 0xe2,
0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0xe8, 0xe9, 0xea, 0xf2, 0xf3,
0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
0xf9, 0xfa }, false);
public static JpegHuffmanTable StdACLuminance =
new JpegHuffmanTable(new short[] { 0, 2, 1, 3, 3, 2, 4, 3, 5, 5,
4, 4, 0, 0, 1, 0x7d },
new short[] { 0x01, 0x02, 0x03, 0x00, 0x04,
0x11, 0x05, 0x12, 0x21, 0x31,
0x41, 0x06, 0x13, 0x51, 0x61,
0x07, 0x22, 0x71, 0x14, 0x32,
0x81, 0x91, 0xa1, 0x08, 0x23,
0x42, 0xb1, 0xc1, 0x15, 0x52,
0xd1, 0xf0, 0x24, 0x33, 0x62,
0x72, 0x82, 0x09, 0x0a, 0x16,
0x17, 0x18, 0x19, 0x1a, 0x25,
0x26, 0x27, 0x28, 0x29, 0x2a,
0x34, 0x35, 0x36, 0x37, 0x38,
0x39, 0x3a, 0x43, 0x44, 0x45,
0x46, 0x47, 0x48, 0x49, 0x4a,
0x53, 0x54, 0x55, 0x56, 0x57,
0x58, 0x59, 0x5a, 0x63, 0x64,
0x65, 0x66, 0x67, 0x68, 0x69,
0x6a, 0x73, 0x74, 0x75, 0x76,
0x77, 0x78, 0x79, 0x7a, 0x83,
0x84, 0x85, 0x86, 0x87, 0x88,
0x89, 0x8a, 0x92, 0x93, 0x94,
0x95, 0x96, 0x97, 0x98, 0x99,
0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
0xa6, 0xa7, 0xa8, 0xa9, 0xaa,
0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
0xb7, 0xb8, 0xb9, 0xba, 0xc2,
0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0xc8, 0xc9, 0xca, 0xd2, 0xd3,
0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
0xd9, 0xda, 0xe1, 0xe2, 0xe3,
0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
0xe9, 0xea, 0xf1, 0xf2, 0xf3,
0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
0xf9, 0xfa }, false);
public static JpegHuffmanTable StdDCChrominance =
new JpegHuffmanTable(new short[] { 0, 3, 1, 1, 1, 1, 1, 1, 1, 1,
1, 0, 0, 0, 0, 0 },
new short[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11 }, false);
public static JpegHuffmanTable StdDCLuminance =
new JpegHuffmanTable(new short[] { 0, 1, 5, 1, 1, 1, 1, 1, 1, 0,
0, 0, 0, 0, 0, 0 },
new short[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11 }, false);
#endregion
/// <summary>
/// Construct and initialize a Huffman table. Copies are created of
/// the array arguments. lengths[index] stores the number of Huffman
/// values with Huffman codes of length index + 1. The values array
/// stores the Huffman values in order of increasing code length.
///
/// throws ArgumentException if either parameter is null, if
/// lengths.Length > 16 or values.Length > 256, if any value in
/// length or values is negative, or if the parameters do not
/// describe a valid Huffman table
/// </summary>
/// <param name="lengths"> an array of Huffman code lengths</param>
/// <param name="values">a sorted array of Huffman values</param>
public JpegHuffmanTable(short[] lengths, short[] values)
// Create copies of the lengths and values arguments.
: this(checkLengths(lengths), checkValues(values, lengths), true)
{
}
/// <summary>
/// Private constructor that avoids unnecessary copying and argument checking.
/// </summary>
/// <param name="lengths">lengths an array of Huffman code lengths</param>
/// <param name="values">a sorted array of Huffman values</param>
/// <param name="copy">true if copies should be created of the given arrays</param>
private JpegHuffmanTable(short[] lengths, short[] values, bool copy)
{
this.lengths = copy ? (short[])lengths.Clone() : lengths;
this.values = copy ? (short[])values.Clone() : values;
}
private static short[] checkLengths(short[] lengths)
{
if (lengths == null || lengths.Length > 16)
throw new ArgumentException("Length array is null or too long.");
if(lengths.Any(x => x < 0))
throw new ArgumentException("Negative values cannot appear in the length array.");
for (int i = 0; i < lengths.Length; i++)
{
if (lengths[i] > ((1 << (i + 1)) - 1))
throw new ArgumentException(
string.Format("Invalid number of codes for code length {0}", (i + 1).ToString() ));
}
return lengths;
}
private static short[] checkValues(short[] values, short[] lengths)
{
if (values == null || values.Length > 256)
throw new ArgumentException("Values array is null or too long.");
if (values.Any(x => x < 0))
throw new ArgumentException("Negative values cannot appear in the values array.");
if (values.Length != lengths.Sum(x => (int)x))
throw new ArgumentException("Number of values does not match code length sum.");
return values;
}
/// <summary>
/// Retrieve the array of Huffman code lengths. If the
/// returned array is called lengthcount, there are
/// lengthcount[index] codes of length index + 1.
/// </summary>
public short[] Lengths { get { return lengths; } }
public short[] Values { get { return values; } }
}
}

View file

@ -1,116 +0,0 @@
/// Copyright (c) 2008 Jeffrey Powers for Fluxcapacity Open Source.
/// Under the MIT License, details: License.txt.
using System;
namespace FluxJpeg.Core
{
internal class JpegQuantizationTable
{
// The table entries, stored in natural order.
private int[] table; public int[] Table { get { return table; } }
/// <summary>
/// The standard JPEG luminance quantization table. Values are
/// stored in natural order.
/// </summary>
public static JpegQuantizationTable K1Luminance = new JpegQuantizationTable(new int[]
{
16, 11, 10, 16, 24, 40, 51, 61,
12, 12, 14, 19, 26, 58, 60, 55,
14, 13, 16, 24, 40, 57, 69, 56,
14, 17, 22, 29, 51, 87, 80, 62,
18, 22, 37, 56, 68, 109, 103, 77,
24, 35, 55, 64, 81, 104, 113, 92,
49, 64, 78, 87, 103, 121, 120, 101,
72, 92, 95, 98, 112, 100, 103, 99
}, false);
/// <summary>
/// The standard JPEG luminance quantization table, scaled by
/// one-half. Values are stored in natural order.
/// </summary>
public static JpegQuantizationTable K1Div2Luminance =
K1Luminance.getScaledInstance(0.5f, true);
/// <summary>
/// The standard JPEG chrominance quantization table. Values are
/// stored in natural order.
/// </summary>
public static JpegQuantizationTable K2Chrominance = new JpegQuantizationTable(new int[]
{
17, 18, 24, 47, 99, 99, 99, 99,
18, 21, 26, 66, 99, 99, 99, 99,
24, 26, 56, 99, 99, 99, 99, 99,
47, 66, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99
}, false);
/// <summary>
/// The standard JPEG chrominance quantization table, scaled by
/// one-half. Values are stored in natural order.
/// </summary>
public static JpegQuantizationTable K2Div2Chrominance =
K2Chrominance.getScaledInstance(0.5f, true);
/// <summary>
/// Construct a new JPEG quantization table. A copy is created of
/// the table argument.
/// </summary>
/// <param name="table">The 64-element value table, stored in natural order</param>
public JpegQuantizationTable(int[] table)
: this(checkTable(table), true)
{
}
/// <summary>
/// Private constructor that avoids unnecessary copying and argument
/// checking.
/// </summary>
/// <param name="table">the 64-element value table, stored in natural order</param>
/// <param name="copy">true if a copy should be created of the given table</param>
private JpegQuantizationTable(int[] table, bool copy)
{
this.table = copy ? (int[])table.Clone() : table;
}
private static int[] checkTable(int[] table)
{
if (table == null || table.Length != 64)
throw new ArgumentException("Invalid JPEG quantization table");
return table;
}
/// <summary>
/// Retrieve a copy of this JPEG quantization table with every value
/// scaled by the given scale factor, and clamped from 1 to 255
/// </summary>
/// <param name="scaleFactor">the factor by which to scale this table</param>
/// <param name="forceBaseline"> clamp scaled values to a maximum of 255 if baseline or from 1 to 32767 otherwise.</param>
/// <returns>new scaled JPEG quantization table</returns>
public JpegQuantizationTable getScaledInstance(float scaleFactor,
bool forceBaseline)
{
int[] scaledTable = (int[])table.Clone();
int max = forceBaseline ? 255 : 32767;
for (int i = 0; i < scaledTable.Length; i++)
{
scaledTable[i] = (int)Math.Round(scaleFactor * (float)scaledTable[i]);
if (scaledTable[i] < 1)
scaledTable[i] = 1;
else if (scaledTable[i] > max)
scaledTable[i] = max;
}
return new JpegQuantizationTable(scaledTable, false);
}
}
}

View file

@ -1,37 +0,0 @@
/// Copyright (c) 2008 Jeffrey Powers for Fluxcapacity Open Source.
/// Under the MIT License, details: License.txt.
using System;
using System.Collections.Generic;
using System.Linq;
namespace FluxJpeg.Core.Decoder
{
internal class JpegScan
{
private List<JpegComponent> components = new List<JpegComponent>();
public IList<JpegComponent> Components { get { return components.AsReadOnly(); } }
private int maxV = 0, maxH = 0;
internal int MaxH { get { return maxH; } }
internal int MaxV { get { return maxV; } }
public void AddComponent(byte id, byte factorHorizontal, byte factorVertical,
byte quantizationID, byte colorMode)
{
JpegComponent component = new JpegComponent( this,
id, factorHorizontal, factorVertical, quantizationID, colorMode);
components.Add(component);
// Defined in Annex A
maxH = components.Max(x => x.factorH);
maxV = components.Max(x => x.factorV);
}
public JpegComponent GetComponentById(byte Id)
{
return components.First(x => x.component_id == Id);
}
}
}

View file

@ -1,327 +0,0 @@
/// Copyright (c) 2008 Jeffrey Powers for Fluxcapacity Open Source.
/// Under the MIT License, details: License.txt.
//
// Partially derives from a Java encoder, JpegEncoder.java by James R Weeks.
// Implements Baseline JPEG Encoding http://www.opennet.ru/docs/formats/jpeg.txt
using System;
using System.Collections.Generic;
using System.IO;
namespace FluxJpeg.Core.Encoder
{
public class JpegEncodeProgressChangedArgs : EventArgs
{
public double EncodeProgress; // 0.0 to 1.0
}
public class JpegEncoder
{
JpegEncodeProgressChangedArgs _progress;
DecodedJpeg _input;
Stream _outStream;
HuffmanTable _huf;
DCT _dct;
int _height;
int _width;
int _quality;
private const int Ss = 0;
private const int Se = 63;
private const int Ah = 0;
private const int Al = 0;
private static readonly int[] CompID = { 1, 2, 3 };
private static readonly int[] HsampFactor = { 1, 1, 1 };
private static readonly int[] VsampFactor = { 1, 1, 1 };
private static readonly int[] QtableNumber = { 0, 1, 1 };
private static readonly int[] DCtableNumber = { 0, 1, 1 };
private static readonly int[] ACtableNumber = { 0, 1, 1 };
public event EventHandler<JpegEncodeProgressChangedArgs> EncodeProgressChanged;
public JpegEncoder(Image image, int quality, Stream outStream)
: this(new DecodedJpeg(image), quality, outStream) { /* see overload */ }
/// <summary>
/// Encodes a JPEG, preserving the colorspace and metadata of the input JPEG.
/// </summary>
/// <param name="decodedJpeg">Decoded Jpeg to start with.</param>
/// <param name="quality">Quality of the image from 0 to 100. (Compression from max to min.)</param>
/// <param name="outStream">Stream where the result will be placed.</param>
public JpegEncoder(DecodedJpeg decodedJpeg, int quality, Stream outStream)
{
_input = decodedJpeg;
/* This encoder requires YCbCr */
_input.Image.ChangeColorSpace(ColorSpace.YCbCr);
_quality = quality;
_height = _input.Image.Height;
_width = _input.Image.Width;
_outStream = outStream;
_dct = new DCT(_quality);
_huf = new HuffmanTable(null);
}
public void Encode()
{
_progress = new JpegEncodeProgressChangedArgs();
WriteHeaders();
CompressTo(_outStream);
WriteMarker(new byte[] { 0xFF, 0xD9 }); // End of Image
_progress.EncodeProgress = 1.0;
if (EncodeProgressChanged != null)
EncodeProgressChanged(this, _progress);
_outStream.Flush();
}
internal void WriteHeaders()
{
int i, j, index, offset;
int[] tempArray;
// Start of Image
byte[] SOI = { (byte)0xFF, (byte)0xD8 };
WriteMarker(SOI);
if (!_input.HasJFIF) // Supplement JFIF if missing
{
byte[] JFIF = new byte[18]
{
(byte)0xff, (byte)0xe0,
(byte)0x00, (byte)0x10,
(byte)0x4a, (byte)0x46,
(byte)0x49, (byte)0x46,
(byte)0x00, (byte)0x01,
(byte)0x00, (byte)0x00,
(byte)0x00, (byte)0x01,
(byte)0x00, (byte)0x01,
(byte)0x00, (byte)0x00
};
WriteArray(JFIF);
}
IO.BinaryWriter writer = new IO.BinaryWriter(_outStream);
/* APP headers and COM headers follow the same format
* which has a 16-bit integer length followed by a block
* of binary data. */
foreach (JpegHeader header in _input.MetaHeaders)
{
writer.Write(JPEGMarker.XFF);
writer.Write(header.Marker);
// Header's length
writer.Write((short)(header.Data.Length + 2));
writer.Write(header.Data);
}
// The DQT header
// 0 is the luminance index and 1 is the chrominance index
byte[] DQT = new byte[134];
DQT[0] = JPEGMarker.XFF;
DQT[1] = JPEGMarker.DQT;
DQT[2] = (byte)0x00;
DQT[3] = (byte)0x84;
offset = 4;
for (i = 0; i < 2; i++)
{
DQT[offset++] = (byte)((0 << 4) + i);
tempArray = (int[])_dct.quantum[i];
for (j = 0; j < 64; j++)
{
DQT[offset++] = (byte)tempArray[ ZigZag.ZigZagMap[j] ];
}
}
WriteArray(DQT);
// Start of Frame Header ( Baseline JPEG )
byte[] SOF = new byte[19];
SOF[0] = JPEGMarker.XFF;
SOF[1] = JPEGMarker.SOF0;
SOF[2] = (byte)0x00;
SOF[3] = (byte)17;
SOF[4] = (byte)_input.Precision;
SOF[5] = (byte)((_input.Image.Height >> 8) & 0xFF);
SOF[6] = (byte)((_input.Image.Height) & 0xFF);
SOF[7] = (byte)((_input.Image.Width >> 8) & 0xFF);
SOF[8] = (byte)((_input.Image.Width) & 0xFF);
SOF[9] = (byte)_input.Image.ComponentCount;
index = 10;
for (i = 0; i < SOF[9]; i++)
{
SOF[index++] = (byte)JpegEncoder.CompID[i];
SOF[index++] = (byte)((_input.HsampFactor[i] << 4) + _input.VsampFactor[i]);
SOF[index++] = (byte)JpegEncoder.QtableNumber[i];
}
WriteArray(SOF);
// The DHT Header
byte[] DHT1, DHT2, DHT3, DHT4;
int bytes, temp, oldindex, intermediateindex;
index = 4;
oldindex = 4;
DHT1 = new byte[17];
DHT4 = new byte[4];
DHT4[0] = JPEGMarker.XFF;
DHT4[1] = JPEGMarker.DHT;
for (i = 0; i < 4; i++)
{
bytes = 0;
// top 4 bits: table class (0=DC, 1=AC)
// bottom 4: index (0=luminance, 1=chrominance)
byte huffmanInfo = (i == 0) ? (byte)0x00 :
(i == 1) ? (byte)0x10 :
(i == 2) ? (byte)0x01 : (byte)0x11;
DHT1[index++ - oldindex] = huffmanInfo;
for (j = 0; j < 16; j++)
{
temp = _huf.bitsList[i][j];
DHT1[index++ - oldindex] = (byte)temp;
bytes += temp;
}
intermediateindex = index;
DHT2 = new byte[bytes];
for (j = 0; j < bytes; j++)
{
DHT2[index++ - intermediateindex] = (byte)_huf.val[i][j];
}
DHT3 = new byte[index];
Array.Copy(DHT4, 0, DHT3, 0, oldindex);
Array.Copy(DHT1, 0, DHT3, oldindex, 17);
Array.Copy(DHT2, 0, DHT3, oldindex + 17, bytes);
DHT4 = DHT3;
oldindex = index;
}
DHT4[2] = (byte)(((index - 2) >> 8) & 0xFF);
DHT4[3] = (byte)((index - 2) & 0xFF);
WriteArray(DHT4);
// Start of Scan Header
byte[] SOS = new byte[14];
SOS[0] = JPEGMarker.XFF;
SOS[1] = JPEGMarker.SOS;
SOS[2] = (byte)0x00;
SOS[3] = (byte)12;
SOS[4] = (byte)_input.Image.ComponentCount;
index = 5;
for (i = 0; i < SOS[4]; i++)
{
SOS[index++] = (byte)JpegEncoder.CompID[i];
SOS[index++] = (byte)((JpegEncoder.DCtableNumber[i] << 4) + JpegEncoder.ACtableNumber[i]);
}
SOS[index++] = (byte)JpegEncoder.Ss;
SOS[index++] = (byte)JpegEncoder.Se;
SOS[index++] = (byte)((JpegEncoder.Ah << 4) + JpegEncoder.Al);
WriteArray(SOS);
}
internal void CompressTo(Stream outStream)
{
int i = 0, j = 0, r = 0, c = 0, a = 0, b = 0;
int comp, xpos, ypos, xblockoffset, yblockoffset;
byte[,] inputArray = null;
float[,] dctArray1 = new float[8, 8];
float[,] dctArray2 = new float[8, 8];
int[] dctArray3 = new int[8 * 8];
int[] lastDCvalue = new int[_input.Image.ComponentCount];
int Width = 0, Height = 0;
int MinBlockWidth, MinBlockHeight;
// This initial setting of MinBlockWidth and MinBlockHeight is done to
// ensure they start with values larger than will actually be the case.
MinBlockWidth = ((_width % 8 != 0) ? (int)(Math.Floor((double)_width / 8.0) + 1) * 8 : _width);
MinBlockHeight = ((_height % 8 != 0) ? (int)(Math.Floor((double)_height / 8.0) + 1) * 8 : _height);
for (comp = 0; comp < _input.Image.ComponentCount; comp++)
{
MinBlockWidth = Math.Min(MinBlockWidth, _input.BlockWidth[comp]);
MinBlockHeight = Math.Min(MinBlockHeight, _input.BlockHeight[comp]);
}
xpos = 0;
for (r = 0; r < MinBlockHeight; r++)
{
// Keep track of progress
_progress.EncodeProgress = (double)r / MinBlockHeight;
if (EncodeProgressChanged != null) EncodeProgressChanged(this, _progress);
for (c = 0; c < MinBlockWidth; c++)
{
xpos = c * 8;
ypos = r * 8;
for (comp = 0; comp < _input.Image.ComponentCount; comp++)
{
Width = _input.BlockWidth[comp];
Height = _input.BlockHeight[comp];
inputArray = _input.Image.Raster[comp];
for (i = 0; i < _input.VsampFactor[comp]; i++)
{
for (j = 0; j < _input.HsampFactor[comp]; j++)
{
xblockoffset = j * 8;
yblockoffset = i * 8;
for (a = 0; a < 8; a++)
{
// set Y value. check bounds
int y = ypos + yblockoffset + a; if (y >= _height) break;
for (b = 0; b < 8; b++)
{
int x = xpos + xblockoffset + b; if (x >= _width) break;
dctArray1[a, b] = inputArray[x,y];
}
}
dctArray2 = _dct.FastFDCT(dctArray1);
dctArray3 = _dct.QuantizeBlock(dctArray2, JpegEncoder.QtableNumber[comp]);
_huf.HuffmanBlockEncoder(outStream, dctArray3, lastDCvalue[comp], JpegEncoder.DCtableNumber[comp], JpegEncoder.ACtableNumber[comp]);
lastDCvalue[comp] = dctArray3[0];
}
}
}
}
}
_huf.FlushBuffer(outStream);
}
void WriteMarker(byte[] data)
{
_outStream.Write(data, 0, 2);
}
void WriteArray(byte[] data)
{
int length = (((int)(data[2] & 0xFF)) << 8) + (int)(data[3] & 0xFF) + 2;
_outStream.Write(data, 0, length);
}
}
}

View file

@ -1,201 +0,0 @@
using System;
namespace FluxJpeg.Core
{
public partial class DCT
{
public const int N = 8;
public int[][] quantum = new int[2][];
public double[][] divisors = new double[2][];
// Quantitization Matrix for luminace.
public double[] DivisorsLuminance = new double[N * N];
// Quantitization Matrix for chrominance.
public double[] DivisorsChrominance = new double[N * N];
public DCT(int quality) : this()
{
Initialize(quality);
}
private void Initialize(int quality)
{
double[] aanScaleFactor =
{
1.0, 1.387039845, 1.306562965, 1.175875602,
1.0, 0.785694958, 0.541196100, 0.275899379
};
int i, j, index, Quality;
// jpeg_quality_scaling
if (quality <= 0) Quality = 1;
if (quality > 100) Quality = 100;
if (quality < 50) Quality = 5000 / quality;
else Quality = 200 - quality * 2;
int[] scaledLum = JpegQuantizationTable.K1Luminance
.getScaledInstance(Quality / 100f, true).Table;
index = 0;
for (i = 0; i < 8; i++)
{
for (j = 0; j < 8; j++)
{
DivisorsLuminance[index] =
(double)1.0 /
((double)scaledLum[index] * aanScaleFactor[i] * aanScaleFactor[j] * 8.0);
index++;
}
}
// Creating the chrominance matrix
int[] scaledChrom = JpegQuantizationTable.K2Chrominance
.getScaledInstance(Quality / 100f, true).Table;
index = 0;
for (i = 0; i < 8; i++)
{
for (j = 0; j < 8; j++)
{
DivisorsChrominance[index] = (double)((double)1.0 / ((double)scaledChrom[index] * aanScaleFactor[i] * aanScaleFactor[j] * (double)8.0));
index++;
}
}
quantum[0] = scaledLum;
divisors[0] = DivisorsLuminance;
quantum[1] = scaledChrom;
divisors[1] = DivisorsChrominance;
}
internal float[,] FastFDCT(float[,] input)
{
float[,] output = new float[N, N];
float tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
float tmp10, tmp11, tmp12, tmp13;
float z1, z2, z3, z4, z5, z11, z13;
int i, j;
for (i = 0; i < 8; i++)
for (j = 0; j < 8; j++)
output[i, j] = input[i, j] - 128f;
// Pass 1: process rows.
for (i = 0; i < 8; i++)
{
tmp0 = output[i, 0] + output[i, 7];
tmp7 = output[i, 0] - output[i, 7];
tmp1 = output[i, 1] + output[i, 6];
tmp6 = output[i, 1] - output[i, 6];
tmp2 = output[i, 2] + output[i, 5];
tmp5 = output[i, 2] - output[i, 5];
tmp3 = output[i, 3] + output[i, 4];
tmp4 = output[i, 3] - output[i, 4];
// Even part
tmp10 = tmp0 + tmp3;
tmp13 = tmp0 - tmp3;
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
output[i, 0] = tmp10 + tmp11;
output[i, 4] = tmp10 - tmp11;
z1 = (tmp12 + tmp13) * (float)0.707106781;
output[i, 2] = tmp13 + z1;
output[i, 6] = tmp13 - z1;
// Odd part
tmp10 = tmp4 + tmp5;
tmp11 = tmp5 + tmp6;
tmp12 = tmp6 + tmp7;
// The rotator is modified from fig 4-8 to avoid extra negations.
z5 = (tmp10 - tmp12) * (float)0.382683433;
z2 = ((float)0.541196100) * tmp10 + z5;
z4 = ((float)1.306562965) * tmp12 + z5;
z3 = tmp11 * ((float)0.707106781);
z11 = tmp7 + z3;
z13 = tmp7 - z3;
output[i, 5] = z13 + z2;
output[i, 3] = z13 - z2;
output[i, 1] = z11 + z4;
output[i, 7] = z11 - z4;
}
// Pass 2: process columns
for (i = 0; i < 8; i++)
{
tmp0 = output[0, i] + output[7, i];
tmp7 = output[0, i] - output[7, i];
tmp1 = output[1, i] + output[6, i];
tmp6 = output[1, i] - output[6, i];
tmp2 = output[2, i] + output[5, i];
tmp5 = output[2, i] - output[5, i];
tmp3 = output[3, i] + output[4, i];
tmp4 = output[3, i] - output[4, i];
// Even part
tmp10 = tmp0 + tmp3;
tmp13 = tmp0 - tmp3;
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
output[0, i] = tmp10 + tmp11;
output[4, i] = tmp10 - tmp11;
z1 = (tmp12 + tmp13) * (float)0.707106781;
output[2, i] = tmp13 + z1;
output[6, i] = tmp13 - z1;
// Odd part
tmp10 = tmp4 + tmp5;
tmp11 = tmp5 + tmp6;
tmp12 = tmp6 + tmp7;
// The rotator is modified from fig 4-8 to avoid extra negations.
z5 = (tmp10 - tmp12) * (float)0.382683433;
z2 = ((float)0.541196100) * tmp10 + z5;
z4 = ((float)1.306562965) * tmp12 + z5;
z3 = tmp11 * ((float)0.707106781);
z11 = tmp7 + z3;
z13 = tmp7 - z3;
output[5, i] = z13 + z2;
output[3, i] = z13 - z2;
output[1, i] = z11 + z4;
output[7, i] = z11 - z4;
}
return output;
}
internal int[] QuantizeBlock(float[,] inputData, int code)
{
int[] result = new int[N * N];
int index = 0;
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
{
result[index] = (int)(Math.Round(inputData[i, j] * divisors[code][index]));
index++;
}
return result;
}
}
}

View file

@ -1,404 +0,0 @@
/// Copyright (c) 2009 Jeffrey Powers for Occipital Open Source.
/// Under the MIT License, details: License.txt.
using System;
using System.Threading;
using FluxJpeg.Core;
namespace FluxJpeg.Core.Filtering
{
public class Convolution
{
public static readonly Convolution Instance = new Convolution();
public GrayImage GaussianConv(GrayImage data, double std)
{
float[] filter = GaussianFilter(std);
return Conv2DSeparable(data, filter);
}
public float[] GaussianFilter(double std)
{
const double Precision = 0.01f;
double var = std * std;
double n = Math.Sqrt(-1 * var * Math.Log(Precision));
int half = (int)Math.Ceiling(n);
float[] filter = new float[half];
double sum = -1.0;
for (int i = 0; i < half; i++)
{
double val = Math.Exp(-0.5 * (i * i) / var);
filter[i] = (float)val;
sum += 2 * val;
}
/* Normalize */
for (int i = 0; i < half; i++)
filter[i] /= (float)sum;
return filter;
}
public GrayImage Conv2DSeparable(GrayImage data, float[] filter)
{
GrayImage pass1 = Filter1DSymmetric(data, filter, true);
GrayImage result = Filter1DSymmetric(pass1, filter, true);
return result;
}
private struct FilterJob
{
public float[] filter;
public int start;
public int end;
public GrayImage data;
public GrayImage result;
public int dataPtr;
public int destPtr;
}
/// <summary>
/// Filters an GrayImage with a 1D symmetric filter along the X-axis.
/// (This operation is multithreaded)
/// </summary>
/// <param name="data">GrayImage to be operated on</param>
/// <param name="filter">Filter to use (center tap plus right-hand-side)</param>
/// <param name="transpose">Transpose the result?</param>
/// <returns>Transposed, filtered GrayImage.</returns>
public GrayImage Filter1DSymmetric(GrayImage data, float[] filter, bool transpose)
{
GrayImage result = transpose ?
new GrayImage(data.Height, data.Width) :
new GrayImage(data.Width, data.Height);
int startY = 0;
int destPtr = transpose ? startY : (startY * result.Width);
FilterJob job
= new FilterJob
{
filter = filter,
data = data,
destPtr = destPtr,
result = result,
start = startY,
end = data.Height / 2
};
ParameterizedThreadStart del = transpose ?
new ParameterizedThreadStart(FilterPartSymmetricT) :
new ParameterizedThreadStart(FilterPartSymmetric);
Thread worker = new Thread(del);
worker.Start(job);
startY = data.Height / 2;
destPtr = transpose ? startY : (startY * result.Width);
job.start = startY;
job.destPtr = destPtr;
job.end = data.Height;
del((object)job); // Run the appropriate filter in this thread, too
worker.Join();
return result;
}
/// <summary>
/// Convolves part of an GrayImage with a 1D filter along the X-axis
/// and transposes it as well.
/// </summary>
/// <param name="filterJob">Filter operation details</param>
private void FilterPartSymmetricT(object filterJob)
{
FilterJob fj = (FilterJob)filterJob;
GrayImage data = fj.data;
float[] srcData = data.Scan0;
float[] filter = fj.filter;
GrayImage result = fj.result;
int pad = filter.Length - 1;
#region Filter and transpose
for (int y = fj.start; y < fj.end; y++)
{
int rowStart = y * data.Width;
int ptr = rowStart;
// Left checked region
for (int x = 0; x < pad; x++)
{
float pixel = srcData[ptr] * filter[0];
// Part of the filter that fits within the GrayImage
for (int i = 1; i < x + 1; i++)
pixel += (srcData[ptr + i] + srcData[ptr - i]) * filter[i];
// Part of the filter that falls off the left side
for (int i = x + 1; i < filter.Length; i++)
pixel += (srcData[ptr + i] + srcData[ptr + i]) * filter[i];
result[y, x] = pixel; ptr++;
}
// Unchecked region
for (int x = pad; x < data.Width - pad; x++)
{
float pixel = srcData[ptr] * filter[0];
for (int i = 1; i < filter.Length; i++)
pixel += (srcData[ptr + i] + srcData[ptr - i]) * filter[i];
result[y, x] = pixel; ptr++;
}
// Right checked region
for (int x = data.Width - pad; x < data.Width; x++)
{
float pixel = srcData[ptr] * filter[0];
// Part of the filter that fits within the GrayImage
for (int i = 1; i < (data.Width - x); i++)
pixel += (srcData[ptr + i] + srcData[ptr - i]) * filter[i];
// Part of the filter that falls off the right side
for (int i = (data.Width - x); i < filter.Length; i++)
pixel += (srcData[ptr - i] + srcData[ptr - i]) * filter[i];
result[y, x] = pixel; ptr++;
}
}
#endregion
}
/// <summary>
/// Convolves an GrayImage with a 1D filter along the X-axis.
/// </summary>
/// <param name="filterJob">Filter operation details</param>
private void FilterPartSymmetric(object filterJob)
{
FilterJob fj = (FilterJob)filterJob;
GrayImage data = fj.data;
float[] srcData = data.Scan0;
float[] filter = fj.filter;
GrayImage result = fj.result;
float[] resData = result.Scan0;
int pad = filter.Length - 1;
int destPtr = fj.destPtr;
#region Filter (no transpose)
for (int y = fj.start; y < fj.end; y++)
{
int rowStart = y * data.Width;
int ptr = fj.dataPtr + rowStart;
// Left checked region
for (int x = 0; x < pad; x++)
{
float pixel = srcData[ptr] * filter[0];
// Part of the filter that fits within the GrayImage
for (int i = 1; i < x + 1; i++)
pixel += (srcData[ptr + i] + srcData[ptr - i]) * filter[i];
// Part of the filter that falls off the left side
for (int i = x + 1; i < filter.Length; i++)
pixel += (srcData[ptr + i] + srcData[ptr + i]) * filter[i];
resData[destPtr++] = pixel; ptr++;
}
// Unchecked region
for (int x = pad; x < data.Width - pad; x++)
{
float pixel = srcData[ptr] * filter[0];
for (int i = 1; i < filter.Length; i++)
pixel += (srcData[ptr + i] + srcData[ptr - i]) * filter[i];
resData[destPtr++] = pixel; ptr++;
}
// Right checked region
for (int x = data.Width - pad; x < data.Width; x++)
{
float pixel = srcData[ptr] * filter[0];
// Part of the filter that fits within the GrayImage
for (int i = 0; i < (data.Width - x); i++)
pixel += (srcData[ptr + i] + srcData[ptr - i]) * filter[i];
// Part of the filter that falls off the right side
for (int i = (data.Width - x); i < filter.Length; i++)
pixel += (srcData[ptr + i] + srcData[ptr - i]) * filter[i];
resData[destPtr++] = pixel; ptr++;
}
}
#endregion
}
public GrayImage Conv2DSymmetric(GrayImage data, GrayImage opLR)
{
int xPad = opLR.Width - 1;
int yPad = opLR.Height - 1;
GrayImage padded = new GrayImage(data.Width + 2 * xPad, data.Height + 2 * yPad);
int dataIdx = 0;
for (int y = 0; y < data.Height; y++)
{
int rowStart = (y + yPad) * (data.Width + 2 * xPad) + xPad;
for (int x = 0; x < data.Width; x++)
{
padded.Scan0[rowStart + x] = data.Scan0[dataIdx];
dataIdx++;
}
}
return Conv2DSymm(padded, opLR);
}
/// <summary>
/// Convolves an GrayImage with a 2D-symmetric operator.
/// </summary>
/// <param name="data">Data to be convolved with the operator</param>
/// <param name="opUL">Lower-right quadrant of the operator.</param>
/// <returns></returns>
private GrayImage Conv2DSymm(GrayImage data, GrayImage opLR)
{
if (opLR.Width % 2 != 0 || opLR.Height % 2 != 0)
throw new ArgumentException("Operator must have an even number of rows and columns.");
int xPad = opLR.Width - 1;
int yPad = opLR.Height - 1;
GrayImage result = new GrayImage(data.Width - 2 * xPad, data.Height - 2 * yPad);
for (int y = yPad; y < data.Height - yPad; y++)
{
for (int x = xPad; x < data.Width - xPad; x++)
{
// Center pixel
float pixel = data[x, y] * opLR.Scan0[0];
// Vertical center
for (int op_y = 1; op_y < opLR.Height; op_y++)
pixel += (data[x, y + op_y] + data[x, y - op_y]) * opLR[0, op_y];
//Horizontal center
for (int op_x = 1; op_x < opLR.Width; op_x++)
pixel += (data[x + op_x, y] + data[x - op_x, y]) * opLR[op_x, 0];
//Quadrants
int opIdx = 1;
for (int op_y = 1; op_y < opLR.Height; op_y++)
{
int baseIdx1 = ((y + op_y) * data.Width) + x;
int baseIdx2 = ((y - op_y) * data.Width) + x;
// Loop unrolling can save 25% execution time here
for (int op_x = 1; op_x < opLR.Width; op_x++)
{
pixel += (data.Scan0[baseIdx1 + op_x] +
data.Scan0[baseIdx2 + op_x] +
data.Scan0[baseIdx1 - op_x] +
data.Scan0[baseIdx2 - op_x]) * opLR.Scan0[opIdx];
opIdx++;
}
opIdx++; // Skip 0th col on next row
}
result[x - xPad, y - yPad] = pixel;
} // loop over data x
} // loop over data y
return result;
}
/// <summary>
/// Vanilla 2D convolution. Not optimized.
/// </summary>
/// <param name="data"></param>
/// <param name="op"></param>
/// <returns></returns>
public GrayImage Conv2D(GrayImage data, GrayImage op)
{
GrayImage result = new GrayImage(data.Width, data.Height);
if (op.Width % 2 == 0 || op.Height % 2 == 0)
throw new ArgumentException("Operator must have an odd number of rows and columns.");
int x_offset = op.Width / 2;
int y_offset = op.Height / 2;
for (int y = 0; y < data.Height; y++)
{
for (int x = 0; x < data.Width; x++)
{
float pixel = 0;
float wt = 0;
for (int op_y = 0; op_y < op.Height; op_y++)
{
int d_y = y - y_offset + op_y;
if (d_y < 0 || d_y >= data.Height) continue;
for (int op_x = 0; op_x < op.Width; op_x++)
{
int d_x = x - x_offset + op_x;
if (d_x < 0 || d_x >= data.Width) continue;
float op_val = op[op_x, op_y];
/* Perform actual convolution */
wt += Math.Abs(op_val);
pixel += data[d_x, d_y] * op_val;
}
}
result[x, y] = pixel / wt;
} // loop over data x
} // loop over data y
return result;
}
}
}

View file

@ -1,47 +0,0 @@
/// Copyright (c) 2008-09 Jeffrey Powers for Occipital Open Source.
/// Under the MIT License, details: License.txt.
namespace FluxJpeg.Core.Filtering
{
using System;
public enum ResamplingFilters
{
NearestNeighbor,
LowpassAntiAlias
//Bicubic
}
public class FilterProgressEventArgs : EventArgs { public double Progress; }
internal abstract class Filter
{
protected int _newWidth, _newHeight;
protected byte[][,] _sourceData, _destinationData;
protected bool _color;
public event EventHandler<FilterProgressEventArgs> ProgressChanged;
FilterProgressEventArgs progressArgs = new FilterProgressEventArgs();
protected void UpdateProgress(double progress)
{
progressArgs.Progress = progress;
if (ProgressChanged != null) ProgressChanged(this, progressArgs);
}
public byte[][,] Apply( byte[][,] imageData, int newWidth, int newHeight )
{
_newHeight = newHeight;
_newWidth = newWidth;
_color = !(imageData.Length == 1);
_destinationData = Image.CreateRaster(newWidth, newHeight, imageData.Length);
_sourceData = imageData;
ApplyFilter();
return _destinationData;
}
protected abstract void ApplyFilter();
}
}

View file

@ -1,44 +0,0 @@
/// Copyright (c) 2009 Jeffrey Powers for Occipital Open Source.
/// Under the MIT License, details: License.txt.
namespace FluxJpeg.Core.Filtering
{
using System;
internal class LowpassResize : Filter
{
protected override void ApplyFilter()
{
// get source image size
int width = _sourceData[0].GetLength(0),
height = _sourceData[0].GetLength(1);
int channels = _sourceData.Length;
// Estimate a good filter size for the gaussian.
// Note that gaussian isn't an ideal bandpass filter
// so this is an experimentally determined quantity
double std = (width / _newWidth) * 0.50;
for(int i = 0; i < channels; i++)
{
GrayImage channel = new GrayImage(_sourceData[i]);
channel = Convolution.Instance.GaussianConv(channel, std);
_sourceData[i] = channel.ToByteArray2D();
}
// number of pixels to shift in the original image
double xStep = (double)width / _newWidth,
yStep = (double)height / _newHeight;
NNResize resizer = new NNResize();
_destinationData = resizer.Apply(_sourceData, _newWidth, _newHeight);
}
}
}

View file

@ -1,47 +0,0 @@
/// Copyright (c) 2008 Jeffrey Powers for Fluxcapacity Open Source.
/// Under the MIT License, details: License.txt.
namespace FluxJpeg.Core.Filtering
{
using System;
internal class NNResize : Filter
{
protected override void ApplyFilter()
{
// get source image size
int width = _sourceData[0].GetLength(0),
height = _sourceData[0].GetLength(1);
// number of pixels to shift in the original image
double xStep = (double)width / _newWidth,
yStep = (double)height / _newHeight;
double sX = 0.5*xStep, sY = 0.5*yStep;
int i_sY, i_sX;
for (int y = 0; y < _newHeight; y++)
{
i_sY = (int)sY; sX = 0;
UpdateProgress((double)y / _newHeight);
for (int x = 0; x < _newWidth; x++)
{
i_sX = (int)sX;
_destinationData[0][x, y] = _sourceData[0][i_sX, i_sY];
if (_color) {
_destinationData[1][x, y] = _sourceData[1][i_sX, i_sY];
_destinationData[2][x, y] = _sourceData[2][i_sX, i_sY];
}
sX += xStep;
}
sY += yStep;
}
}
}
}

View file

@ -1,77 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Runtime.InteropServices;
namespace FluxJpeg.Core.Filtering
{
public class GrayImage
{
public float[] Scan0;
private int _width;
private int _height;
public int Width { get { return _width; } }
public int Height { get { return _height; } }
/// <summary>
/// Returns a new 0.0-initialized image of specified size.
/// </summary>
/// <param name="width">Width in pixels</param>
/// <param name="height">Height in pixels</param>
public GrayImage(int width, int height)
{
_width = width; _height = height;
Scan0 = new float[width * height];
}
/// <summary>
/// Creates a 0.0 to 1.0 grayscale image from a bitmap.
/// </summary>
public GrayImage(byte[,] channel)
{
Convert(channel);
}
/// <summary>
/// Access a pixel within the image.
/// </summary>
/// <param name="x">X-coordinate</param>
/// <param name="y">Y-coordinate</param>
/// <returns>Pixel brightness between 0.0 and 1.0</returns>
public float this[int x, int y]
{
get { return Scan0[y * _width + x]; }
set { Scan0[y * _width + x] = value; }
}
private void Convert(byte[,] channel)
{
_width = channel.GetLength(0);
_height = channel.GetLength(1);
Scan0 = new float[_width* _height];
int i = 0;
for (int y = 0; y < _height; y++)
for (int x = 0; x < _width; x++)
Scan0[i++] = channel[x, y] / 255f;
}
public byte[,] ToByteArray2D()
{
byte[,] result = new byte[_width, _height];
int i = 0;
for (int y = 0; y < _height; y++)
for (int x = 0; x < _width; x++)
result[x, y] = (byte)(Scan0[i++] * 255f);
return result;
}
}
}

View file

@ -1,90 +0,0 @@
This software is based in part on the work of the Independent JPEG Group:
The Independent JPEG Group's JPEG software
==========================================
LEGAL ISSUES
============
In plain English:
1. We don't promise that this software works. (But if you find any bugs,
please let us know!)
2. You can use this software for whatever you want. You don't have to pay us.
3. You may not pretend that you wrote this software. If you use it in a
program, you must acknowledge somewhere in your documentation that
you've used the IJG code.
In legalese:
The authors make NO WARRANTY or representation, either express or implied,
with respect to this software, its quality, accuracy, merchantability, or
fitness for a particular purpose. This software is provided "AS IS", and you,
its user, assume the entire risk as to its quality and accuracy.
This software is copyright (C) 1991-1998, Thomas G. Lane.
All Rights Reserved except as specified below.
Permission is hereby granted to use, copy, modify, and distribute this
software (or portions thereof) for any purpose, without fee, subject to these
conditions:
(1) If any part of the source code for this software is distributed, then this
README file must be included, with this copyright and no-warranty notice
unaltered; and any additions, deletions, or changes to the original files
must be clearly indicated in accompanying documentation.
(2) If only executable code is distributed, then the accompanying
documentation must state that "this software is based in part on the work of
the Independent JPEG Group".
(3) Permission for use of this software is granted only if the user accepts
full responsibility for any undesirable consequences; the authors accept
NO LIABILITY for damages of any kind.
These conditions apply to any software derived from or based on the IJG code,
not just to the unmodified library. If you use our work, you ought to
acknowledge us.
Permission is NOT granted for the use of any IJG author's name or company name
in advertising or publicity relating to this software or products derived from
it. This software may be referred to only as "the Independent JPEG Group's
software".
We specifically permit and encourage the use of this software as the basis of
commercial products, provided that all warranty or liability claims are
assumed by the product vendor.
ansi2knr.c is included in this distribution by permission of L. Peter Deutsch,
sole proprietor of its copyright holder, Aladdin Enterprises of Menlo Park, CA.
ansi2knr.c is NOT covered by the above copyright and conditions, but instead
by the usual distribution terms of the Free Software Foundation; principally,
that you must include source code if you redistribute it. (See the file
ansi2knr.c for full details.) However, since ansi2knr.c is not needed as part
of any program generated from the IJG code, this does not limit you more than
the foregoing paragraphs do.
The Unix configuration script "configure" was produced with GNU Autoconf.
It is copyright by the Free Software Foundation but is freely distributable.
The same holds for its supporting scripts (config.guess, config.sub,
ltconfig, ltmain.sh). Another support script, install-sh, is copyright
by M.I.T. but is also freely distributable.
It appears that the arithmetic coding option of the JPEG spec is covered by
patents owned by IBM, AT&T, and Mitsubishi. Hence arithmetic coding cannot
legally be used without obtaining one or more licenses. For this reason,
support for arithmetic coding has been removed from the free JPEG software.
(Since arithmetic coding provides only a marginal gain over the unpatented
Huffman mode, it is unlikely that very many implementations will support it.)
So far as we are aware, there are no patent restrictions on the remaining
code.
The IJG distribution formerly included code to read and write GIF files.
To avoid entanglement with the Unisys LZW patent, GIF reading support has
been removed altogether, and the GIF writer has been simplified to produce
"uncompressed GIFs". This technique does not use the LZW algorithm; the
resulting GIF files are larger than usual, but are readable by all standard
GIF decoders.
We are required to state that
"The Graphics Interchange Format(c) is the Copyright property of
CompuServe Incorporated. GIF(sm) is a Service Mark property of
CompuServe Incorporated."

View file

@ -1,46 +0,0 @@
/// Copyright (c) 2008 Jeffrey Powers for Fluxcapacity Open Source.
/// Under the MIT License, details: License.txt.
using System;
using System.IO;
namespace FluxJpeg.Core.IO
{
/// <summary>
/// Big-endian binary reader
/// </summary>
internal class BinaryReader
{
Stream _stream;
byte[] _buffer;
public Stream BaseStream { get { return _stream; } }
public BinaryReader(byte[] data) : this(new MemoryStream(data)) { }
public BinaryReader(Stream stream)
{
_stream = stream;
_buffer = new byte[2];
}
public byte ReadByte()
{
int b = _stream.ReadByte();
if (b == -1) throw new EndOfStreamException();
return (byte)b;
}
public ushort ReadShort()
{
_stream.Read(_buffer, 0, 2);
return (ushort)((_buffer[0] << 8) | (_buffer[1] & 0xff));
}
public int Read(byte[] buffer, int offset, int count)
{
return _stream.Read(buffer, offset, count);
}
}
}

View file

@ -1,45 +0,0 @@
/// Copyright (c) 2008 Jeffrey Powers for Fluxcapacity Open Source.
/// Under the MIT License, details: License.txt.
using System;
using System.Text;
using System.IO;
namespace FluxJpeg.Core.IO
{
/// <summary>
/// A Big-endian binary writer.
/// </summary>
internal class BinaryWriter
{
private Stream _stream;
internal BinaryWriter(Stream stream)
{
_stream = stream;
}
internal void Write(byte[] val)
{
_stream.Write(val, 0, val.Length);
}
internal void Write(byte[] val, int offset, int count)
{
_stream.Write(val, offset, count);
}
internal void Write(short val)
{
_stream.WriteByte((byte)(( val >> 8 ) & 0xFF));
_stream.WriteByte((byte)(val & 0xFF));
}
internal void Write(byte val)
{
_stream.WriteByte(val);
}
}
}

View file

@ -1,117 +0,0 @@
/// Copyright (c) 2008 Jeffrey Powers for Fluxcapacity Open Source.
/// Under the MIT License, details: License.txt.
using System;
using System.IO;
namespace FluxJpeg.Core.IO
{
internal class JPEGMarkerFoundException : Exception
{
public JPEGMarkerFoundException(byte marker) { this.Marker = marker; }
public byte Marker;
}
internal class JPEGBinaryReader : IO.BinaryReader
{
public int eob_run = 0;
private byte marker;
public JPEGBinaryReader(Stream input)
: base(input)
{
}
/// <summary>
/// Seeks through the stream until a marker is found.
/// </summary>
public byte GetNextMarker()
{
try { while (true) { ReadJpegByte(); } }
catch (JPEGMarkerFoundException ex) {
return ex.Marker;
}
}
byte _bitBuffer;
protected int _bitsLeft = 0;
public int BitOffset
{
get { return (8 - _bitsLeft) % 8; }
set
{
if (_bitsLeft != 0) BaseStream.Seek(-1, SeekOrigin.Current);
_bitsLeft = (8 - value) % 8;
}
}
/// <summary>
/// Places n bits from the stream, where the most-significant bits
/// from the first byte read end up as the most-significant of the returned
/// n bits.
/// </summary>
/// <param name="n">Number of bits to return</param>
/// <returns>Integer containing the bits desired -- shifted all the way right.</returns>
public int ReadBits(int n)
{
int result = 0;
#region Special case -- included for optimization purposes
if (_bitsLeft >= n)
{
_bitsLeft-=n;
result = _bitBuffer >> (8 - n);
_bitBuffer = (byte)(_bitBuffer << n);
return result;
}
#endregion
while (n > 0)
{
if (_bitsLeft == 0)
{
_bitBuffer = ReadJpegByte();
_bitsLeft = 8;
}
int take = n <= _bitsLeft ? n : _bitsLeft;
result = result | ((_bitBuffer >> 8 - take) << (n - take));
_bitBuffer = (byte)(_bitBuffer << take);
_bitsLeft -= take;
n -= take;
}
return result;
}
protected byte ReadJpegByte()
{
byte c = ReadByte();
/* If it's 0xFF, check and discard stuffed zero byte */
if (c == JPEGMarker.XFF)
{
// Discard padded oxFFs
while ((c = ReadByte()) == 0xff) ;
// ff00 is the escaped form of 0xff
if (c == 0) c = 0xff;
else
{
// Otherwise we've found a new marker.
marker = c;
throw new JPEGMarkerFoundException(marker);
}
}
return c;
}
}
}

View file

@ -1,183 +0,0 @@
/// Copyright (c) 2008 Jeffrey Powers for Fluxcapacity Open Source.
/// Under the MIT License, details: License.txt.
using System;
#if SILVERLIGHT
#else
using System.Drawing;
using System.Drawing.Imaging;
#endif
namespace FluxJpeg.Core {
public struct ColorModel {
public ColorSpace colorspace;
public bool Opaque;
}
public enum ColorSpace { Gray, YCbCr, RGB }
public class Image {
private ColorModel _cm;
private byte[][,] _raster;
public byte[][,] Raster { get { return _raster; } }
public ColorModel ColorModel { get { return _cm; } }
/// <summary> X density (dots per inch).</summary>
public double DensityX { get; set; }
/// <summary> Y density (dots per inch).</summary>
public double DensityY { get; set; }
public int ComponentCount { get { return _raster.Length; } }
/// <summary>
/// Converts the colorspace of an image (in-place)
/// </summary>
/// <param name="cs">Colorspace to convert into</param>
/// <returns>Self</returns>
public Image ChangeColorSpace(ColorSpace cs) {
// Colorspace is already correct
if (_cm.colorspace == cs) return this;
byte[] ycbcr = new byte[3];
byte[] rgb = new byte[3];
if (_cm.colorspace == ColorSpace.RGB && cs == ColorSpace.YCbCr) {
/*
* Y' = + 0.299 * R'd + 0.587 * G'd + 0.114 * B'd
Cb = 128 - 0.168736 * R'd - 0.331264 * G'd + 0.5 * B'd
Cr = 128 + 0.5 * R'd - 0.418688 * G'd - 0.081312 * B'd
*
*/
for (int x = 0; x < width; x++)
for (int y = 0; y < height; y++) {
YCbCr.fromRGB(ref _raster[0][x, y], ref _raster[1][x, y], ref _raster[2][x, y]);
}
_cm.colorspace = ColorSpace.YCbCr;
} else if (_cm.colorspace == ColorSpace.YCbCr && cs == ColorSpace.RGB) {
for (int x = 0; x < width; x++)
for (int y = 0; y < height; y++) {
// 0 is LUMA
// 1 is BLUE
// 2 is RED
YCbCr.toRGB(ref _raster[0][x, y], ref _raster[1][x, y], ref _raster[2][x, y]);
}
_cm.colorspace = ColorSpace.RGB;
} else if (_cm.colorspace == ColorSpace.Gray && cs == ColorSpace.YCbCr) {
// To convert to YCbCr, we just add two 128-filled chroma channels
byte[,] Cb = new byte[width, height];
byte[,] Cr = new byte[width, height];
for (int x = 0; x < width; x++)
for (int y = 0; y < height; y++) {
Cb[x, y] = 128; Cr[x, y] = 128;
}
_raster = new byte[][,] { _raster[0], Cb, Cr };
_cm.colorspace = ColorSpace.YCbCr;
} else if (_cm.colorspace == ColorSpace.Gray && cs == ColorSpace.RGB) {
ChangeColorSpace(ColorSpace.YCbCr);
ChangeColorSpace(ColorSpace.RGB);
} else {
throw new Exception("Colorspace conversion not supported.");
}
return this;
}
private int width; private int height;
public int Width { get { return width; } }
public int Height { get { return height; } }
public Image(ColorModel cm, byte[][,] raster) {
width = raster[0].GetLength(0);
height = raster[0].GetLength(1);
_cm = cm;
_raster = raster;
}
public static byte[][,] CreateRaster(int width, int height, int bands) {
// Create the raster
byte[][,] raster = new byte[bands][,];
for (int b = 0; b < bands; b++)
raster[b] = new byte[width, height];
return raster;
}
delegate void ConvertColor(ref byte c1, ref byte c2, ref byte c3);
#if SILVERLIGHT
#else
public Bitmap ToBitmap()
{
ConvertColor ColorConverter;
switch(_cm.colorspace)
{
case ColorSpace.YCbCr:
ColorConverter = YCbCr.toRGB;
break;
default:
throw new Exception("Colorspace not supported yet.");
}
int _width = width;
int _height = height;
Bitmap bitmap = new Bitmap(_width, _height, PixelFormat.Format32bppArgb);
BitmapData bmData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
System.Drawing.Imaging.ImageLockMode.WriteOnly,
System.Drawing.Imaging.PixelFormat.Format32bppArgb);
byte[] outColor = new byte[3];
byte[] inColor = new byte[3];
unsafe
{
int i = 0;
byte* ptrBitmap = (byte*)bmData.Scan0;
for (int y = 0; y < _height; y++)
{
for (int x = 0; x < _width; x++)
{
ptrBitmap[0] = (byte)_raster[0][x, y];
ptrBitmap[1] = (byte)_raster[1][x, y];
ptrBitmap[2] = (byte)_raster[2][x, y];
ColorConverter(ref ptrBitmap[0], ref ptrBitmap[1], ref ptrBitmap[2]);
// Swap RGB --> BGR
byte R = ptrBitmap[0];
ptrBitmap[0] = ptrBitmap[2];
ptrBitmap[2] = R;
ptrBitmap[3] = 255; /* 100% opacity */
ptrBitmap += 4; // advance to the next pixel
i++; // "
}
}
}
bitmap.UnlockBits(bmData);
return bitmap;
}
#endif
}
}

View file

@ -1,40 +0,0 @@
This software is based in part on the Java Advanced Imaging IO by Sun Microsystems.
That software is governed by the following license:
===================================================
Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistribution of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistribution in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
Neither the name of Sun Microsystems, Inc. or the names of
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
This software is provided "AS IS," without a warranty of any
kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL
NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF
USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR
ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
You acknowledge that this software is not designed or intended for
use in the design, construction, operation or maintenance of any
nuclear facility.

View file

@ -1,128 +0,0 @@
/// Copyright (c) 2008 Jeffrey Powers for Fluxcapacity Open Source.
/// Under the MIT License, details: License.txt.
using System;
namespace FluxJpeg.Core
{
internal sealed class JPEGMarker
{
// JFIF identifiers
public const byte JFIF_J = (byte)0x4a;
public const byte JFIF_F = (byte)0x46;
public const byte JFIF_I = (byte)0x49;
public const byte JFIF_X = (byte)0x46;
// JFIF extension codes
public const byte JFXX_JPEG = (byte)0x10;
public const byte JFXX_ONE_BPP = (byte)0x11;
public const byte JFXX_THREE_BPP = (byte)0x13;
// Marker prefix. Next byte is a marker, unless ...
public const byte XFF = (byte)0xff;
// ... marker byte encoding an xff.
public const byte X00 = (byte)0x00;
#region Section Markers
/// <summary>Huffman Table</summary>
public const byte DHT = (byte)0xc4;
/// <summary>Quantization Table</summary>
public const byte DQT = (byte)0xdb;
/// <summary>Start of Scan</summary>
public const byte SOS = (byte)0xda;
/// <summary>Define Restart Interval</summary>
public const byte DRI = (byte)0xdd;
/// <summary>Comment</summary>
public const byte COM = (byte)0xfe;
/// <summary>Start of Image</summary>
public const byte SOI = (byte)0xd8;
/// <summary>End of Image</summary>
public const byte EOI = (byte)0xd9;
/// <summary>Define Number of Lines</summary>
public const byte DNL = (byte)0xdc;
#endregion
#region Application Reserved Keywords
public const byte APP0 = (byte)0xe0;
public const byte APP1 = (byte)0xe1;
public const byte APP2 = (byte)0xe2;
public const byte APP3 = (byte)0xe3;
public const byte APP4 = (byte)0xe4;
public const byte APP5 = (byte)0xe5;
public const byte APP6 = (byte)0xe6;
public const byte APP7 = (byte)0xe7;
public const byte APP8 = (byte)0xe8;
public const byte APP9 = (byte)0xe9;
public const byte APP10 = (byte)0xea;
public const byte APP11 = (byte)0xeb;
public const byte APP12 = (byte)0xec;
public const byte APP13 = (byte)0xed;
public const byte APP14 = (byte)0xee;
public const byte APP15 = (byte)0xef;
#endregion
public const byte RST0 = (byte)0xd0;
public const byte RST1 = (byte)0xd1;
public const byte RST2 = (byte)0xd2;
public const byte RST3 = (byte)0xd3;
public const byte RST4 = (byte)0xd4;
public const byte RST5 = (byte)0xd5;
public const byte RST6 = (byte)0xd6;
public const byte RST7 = (byte)0xd7;
#region Start of Frame (SOF)
/// <summary>Nondifferential Huffman-coding frame (baseline dct)</summary>
public const byte SOF0 = (byte)0xc0;
/// <summary>Nondifferential Huffman-coding frame (extended dct)</summary>
public const byte SOF1 = (byte)0xc1;
/// <summary>Nondifferential Huffman-coding frame (progressive dct)</summary>
public const byte SOF2 = (byte)0xc2;
/// <summary>Nondifferential Huffman-coding frame Lossless (Sequential)</summary>
public const byte SOF3 = (byte)0xc3;
/// <summary>Differential Huffman-coding frame Sequential DCT</summary>
public const byte SOF5 = (byte)0xc5;
/// <summary>Differential Huffman-coding frame Progressive DCT</summary>
public const byte SOF6 = (byte)0xc6;
/// <summary>Differential Huffman-coding frame lossless</summary>
public const byte SOF7 = (byte)0xc7;
/// <summary>Nondifferential Arithmetic-coding frame (extended dct)</summary>
public const byte SOF9 = (byte)0xc9;
/// <summary>Nondifferential Arithmetic-coding frame (progressive dct)</summary>
public const byte SOF10 = (byte)0xca;
/// <summary>Nondifferential Arithmetic-coding frame (lossless)</summary>
public const byte SOF11 = (byte)0xcb;
/// <summary>Differential Arithmetic-coding frame (sequential dct)</summary>
public const byte SOF13 = (byte)0xcd;
/// <summary>Differential Arithmetic-coding frame (progressive dct)</summary>
public const byte SOF14 = (byte)0xce;
/// <summary>Differential Arithmetic-coding frame (lossless)</summary>
public const byte SOF15 = (byte)0xcf;
#endregion
}
}

View file

@ -1,24 +0,0 @@
Copyright (c) 2008-2009 Occipital Open Source
Partial derivations: See IJG.txt and JAI.txt.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

View file

@ -1,30 +0,0 @@
FJCore: A Fluxcapacity Open Source Project
--------------------------------------------------------------------------------------------
Thanks for checking out FJCore, an image library including a pure C# implementation
of the JPEG baseline and progressive codecs.
Design goals:
- No external dependencies (besides a C# compiler and ECMA-standard CIL runtime)
- High performance
- High image quality
- Simple, intuitive usage pattern
With your help, we can make this one of the most readable and efficient libraries
available to run on any CIL runtime (including the .NET framework, Mono, and Silverlight)!
Try FJCore online: fluxtools.net/emailphotos
More information: fluxcapacity.net/open-source
--------------------------------------------------------------------------------------------
April 7, 2008:
- Initial release.
July 13, 2008:
- Encoder is now included.
- Silverlight project added (both FJCore and FJCoreWin share source).
- FJExample, a Silverlight test application, is included.

View file

@ -1,98 +0,0 @@
/// Copyright (c) 2008 Jeffrey Powers for Fluxcapacity Open Source.
/// Under the MIT License, details: License.txt.
using System;
using System.Collections.Generic;
using System.Text;
using FluxJpeg.Core.Filtering;
namespace FluxJpeg.Core
{
public class ResizeNotNeededException : Exception { }
public class ResizeProgressChangedEventArgs : EventArgs { public double Progress; }
public class ImageResizer
{
private ResizeProgressChangedEventArgs progress = new ResizeProgressChangedEventArgs();
public event EventHandler<ResizeProgressChangedEventArgs> ProgressChanged;
private Image _input;
public ImageResizer(Image input)
{
_input = input;
}
public static bool ResizeNeeded(FluxJpeg.Core.Image image, int maxEdgeLength)
{
double scale = (image.Width > image.Height) ?
(double)maxEdgeLength / image.Width :
(double)maxEdgeLength / image.Height;
return scale < 1.0; // true if we must downscale
}
public Image Resize(int maxEdgeLength, ResamplingFilters technique)
{
double scale = 0;
if (_input.Width > _input.Height)
scale = (double)maxEdgeLength / _input.Width;
else
scale = (double)maxEdgeLength / _input.Height;
if (scale >= 1.0)
throw new ResizeNotNeededException();
else
return Resize(scale, technique);
}
public Image Resize(int maxWidth, int maxHeight, ResamplingFilters technique)
{
double wFrac = (double)maxWidth / _input.Width;
double hFrac = (double)maxHeight / _input.Height;
double scale = 0;
// Make the image as large as possible, while
// fitting in the supplied box and
// obeying the aspect ratio
if (wFrac < hFrac) { scale = wFrac; }
else { scale = hFrac; }
if (scale >= 1.0)
throw new ResizeNotNeededException();
else
return Resize(scale, technique);
}
public Image Resize(double scale, ResamplingFilters technique)
{
int height = (int)(scale * _input.Height);
int width = (int)(scale * _input.Width);
Filter resizeFilter;
switch (technique)
{
case ResamplingFilters.NearestNeighbor:
resizeFilter = new NNResize();
break;
case ResamplingFilters.LowpassAntiAlias:
resizeFilter = new LowpassResize();
break;
default:
throw new NotSupportedException();
}
return new Image(_input.ColorModel, resizeFilter.Apply(_input.Raster, width, height));
}
void ResizeProgressChanged(object sender, Filtering.FilterProgressEventArgs e)
{
progress.Progress = e.Progress;
if (ProgressChanged != null) ProgressChanged(this, progress);
}
}
}

View file

@ -1,59 +0,0 @@
/// Copyright (c) 2008 Jeffrey Powers for Fluxcapacity Open Source.
/// Under the MIT License, details: License.txt.
using System;
namespace FluxJpeg.Core
{
internal class YCbCr
{
public static void toRGB(ref byte c1, ref byte c2, ref byte c3)
{
double dY = (double)c1;
double dCb2 = (double)c2 - 128;
double dCr2 = (double)c3 - 128;
double dR = dY + 1.402 * dCr2;
double dG = dY - 0.34414 * dCb2 - 0.71414 * dCr2;
double dB = dY + 1.772 * dCb2;
c1 = dR > 255 ? (byte)255 : dR < 0 ? (byte)0 : (byte)dR;
c2 = dG > 255 ? (byte)255 : dG < 0 ? (byte)0 : (byte)dG;
c3 = dB > 255 ? (byte)255 : dB < 0 ? (byte)0 : (byte)dB;
}
public static void fromRGB(ref byte c1, ref byte c2, ref byte c3)
{
double dR = (double)c1;
double dG = (double)c2;
double dB = (double)c3;
c1 = (byte)(0.299 * dR + 0.587 * dG + 0.114 * dB);
c2 = (byte)(-0.16874 * dR - 0.33126 * dG + 0.5 * dB + 128);
c3 = (byte)(0.5 * dR - 0.41869 * dG - 0.08131 * dB + 128);
}
///* RGB to YCbCr range 0-255 */
//public static void fromRGB(byte[] rgb, byte[] ycbcr)
//{
// ycbcr[0] = (byte)((0.299 * (float)rgb[0] + 0.587 * (float)rgb[1] + 0.114 * (float)rgb[2]));
// ycbcr[1] = (byte)(128 + (byte)((-0.16874 * (float)rgb[0] - 0.33126 * (float)rgb[1] + 0.5 * (float)rgb[2])));
// ycbcr[2] = (byte)(128 + (byte)((0.5 * (float)rgb[0] - 0.41869 * (float)rgb[1] - 0.08131 * (float)rgb[2])));
//}
/* RGB to YCbCr range 0-255 */
public static float[] fromRGB(float[] data)
{
float[] dest = new float[3];
dest[0] = (float)((0.299 * (float)data[0] + 0.587 * (float)data[1] + 0.114 * (float)data[2]));
dest[1] = 128 + (float)((-0.16874 * (float)data[0] - 0.33126 * (float)data[1] + 0.5 * (float)data[2]));
dest[2] = 128 + (float)((0.5 * (float)data[0] - 0.41869 * (float)data[1] - 0.08131 * (float)data[2]));
return (dest);
}
}
}

View file

@ -1,65 +0,0 @@
/// Copyright (c) 2008 Jeffrey Powers for Fluxcapacity Open Source.
/// Under the MIT License, details: License.txt.
namespace FluxJpeg.Core
{
internal class ZigZag
{
#region Alternate Form
internal static readonly int[] ZigZagMap =
{
0, 1, 8, 16, 9, 2, 3, 10,
17, 24, 32, 25, 18, 11, 4, 5,
12, 19, 26, 33, 40, 48, 41, 34,
27, 20, 13, 6, 7, 14, 21, 28,
35, 42, 49, 56, 57, 50, 43, 36,
29, 22, 15, 23, 30, 37, 44, 51,
58, 59, 52, 45, 38, 31, 39, 46,
53, 60, 61, 54, 47, 55, 62, 63
};
//public static void UnZigZag(float[] input, float[] output)
//{
// for (int i = 0; i < 64; i++)
// output[ZigZagMap[i] / 8, ZigZagMap[i] % 8] = input[i];
//}
#endregion
public static void UnZigZag(float[] input, float[] output)
{
output[0] = input[0]; output[1] = input[1];
output[8] = input[2]; output[16] = input[3];
output[9] = input[4]; output[2] = input[5];
output[3] = input[6]; output[10] = input[7];
output[17] = input[8]; output[24] = input[9];
output[32] = input[10]; output[25] = input[11];
output[18] = input[12]; output[11] = input[13];
output[4] = input[14]; output[5] = input[15];
output[12] = input[16]; output[19] = input[17];
output[26] = input[18]; output[33] = input[19];
output[40] = input[20]; output[48] = input[21];
output[41] = input[22]; output[34] = input[23];
output[27] = input[24]; output[20] = input[25];
output[13] = input[26]; output[6] = input[27];
output[7] = input[28]; output[14] = input[29];
output[21] = input[30]; output[28] = input[31];
output[35] = input[32]; output[42] = input[33];
output[49] = input[34]; output[56] = input[35];
output[57] = input[36]; output[50] = input[37];
output[43] = input[38]; output[36] = input[39];
output[29] = input[40]; output[22] = input[41];
output[15] = input[42]; output[23] = input[43];
output[30] = input[44]; output[37] = input[45];
output[44] = input[46]; output[51] = input[47];
output[58] = input[48]; output[59] = input[49];
output[52] = input[50]; output[45] = input[51];
output[38] = input[52]; output[31] = input[53];
output[39] = input[54]; output[46] = input[55];
output[53] = input[56]; output[60] = input[57];
output[61] = input[58]; output[54] = input[59];
output[47] = input[60]; output[55] = input[61];
output[62] = input[62]; output[63] = input[63];
}
}
}

View file

@ -1,614 +0,0 @@
/**
* FileReference.cs
*
* Copyright 2009, Moxiecode Systems AB
* Released under GPL License.
*
* License: http://www.plupload.com/license
* Contributing: http://www.plupload.com/contributing
*/
using System;
using System.IO;
using System.Threading;
using System.Windows.Threading;
using System.Net;
using System.Text.RegularExpressions;
using System.Windows.Browser;
using System.Windows.Media.Imaging;
using System.Collections.Generic;
using FluxJpeg.Core.Encoder;
using FluxJpeg.Core;
using Plupload.PngEncoder;
namespace Moxiecode.Plupload {
enum ImageType {
Jpeg,
Png
}
/// <summary>
/// Description of File.
/// </summary>
public class FileReference {
#region private fields
private string name, uploadUrl, id, targetName, mimeType;
private FileInfo info;
private SynchronizationContext syncContext;
private int chunk, chunks, chunkSize;
private bool multipart, chunking;
private long size;
private string fileDataName;
private Dictionary<string, object> multipartParams;
private Dictionary<string, object> headers;
private Stream imageStream;
#endregion
/// <summary>Upload compleate delegate.</summary>
public delegate void UploadCompleteHandler(object sender, UploadEventArgs e);
/// <summary>Upload chunk compleate delegate.</summary>
public delegate void UploadChunkCompleteHandler(object sender, UploadEventArgs e);
/// <summary>Upload error delegate.</summary>
public delegate void ErrorHandler(object sender, ErrorEventArgs e);
/// <summary>Upload progress delegate.</summary>
public delegate void ProgressHandler(object sender, ProgressEventArgs e);
/// <summary>Upload complete event</summary>
public event UploadCompleteHandler UploadComplete;
/// <summary>Upload chunk complete event</summary>
public event UploadChunkCompleteHandler UploadChunkComplete;
/// <summary>Error event</summary>
public event ErrorHandler Error;
/// <summary>Progress event</summary>
public event ProgressHandler Progress;
/// <summary>
/// Main constructor for the file reference.
/// </summary>
/// <param name="id">Unique file id for item.</param>
/// <param name="info">FileInfo that got returned from a file selection.</param>
public FileReference(string id, FileInfo info) {
this.id = id;
this.name = info.Name;
this.info = info;
this.size = info.Length;
}
/// <summary>Unique id for the file reference.</summary>
public string Id {
get { return id; }
}
/// <summary>File name to use with upload.</summary>
public string Name {
get { return name; }
set { name = value; }
}
/// <summary>File size for the selected file.</summary>
public long Size {
get { return this.size; }
}
/// <summary>
/// Uploads the file to the specific url and using the specified chunk_size.
/// </summary>
/// <param name="upload_url">URL to upload to.</param>
/// <param name="chunk_size">Chunk size to use.</param>
/// <param name="image_width">Image width to scale to.</param>
/// <param name="image_height">Image height to scale to.</param>
/// <param name="image_quality">Image quality to store as.</param>
public void Upload(string upload_url, string json_settings) {
int chunkSize = 0, imageWidth = 0, imageHeight = 0, imageQuality = 90;
Dictionary<string, object> settings = (Dictionary<string, object>) Moxiecode.Plupload.Utils.JsonReader.ParseJson(json_settings);
chunkSize = Convert.ToInt32(settings["chunk_size"]);
imageWidth = Convert.ToInt32(settings["image_width"]);
imageHeight = Convert.ToInt32(settings["image_height"]);
imageQuality = Convert.ToInt32(settings["image_quality"]);
this.fileDataName = (string)settings["file_data_name"];
this.multipart = Convert.ToBoolean(settings["multipart"]);
this.multipartParams = (Dictionary<string, object>)settings["multipart_params"];
this.headers = (Dictionary<string, object>)settings["headers"];
this.targetName = (string) settings["name"];
this.mimeType = (string) settings["mime"];
this.chunk = 0;
this.chunking = chunkSize > 0;
this.uploadUrl = upload_url;
try {
// Is jpeg and image size is defined
if (Regex.IsMatch(this.name, @"\.(jpeg|jpg|png)$", RegexOptions.IgnoreCase) && (imageWidth != 0 || imageHeight != 0)) {
if (Regex.IsMatch(this.name, @"\.png$"))
this.imageStream = this.ResizeImage(this.info.OpenRead(), imageWidth, imageHeight, imageQuality, ImageType.Png);
else
this.imageStream = this.ResizeImage(this.info.OpenRead(), imageWidth, imageHeight, imageQuality, ImageType.Jpeg);
this.imageStream.Seek(0, SeekOrigin.Begin);
this.size = this.imageStream.Length;
}
} catch (Exception ex) {
syncContext.Send(delegate {
this.OnIOError(new ErrorEventArgs(ex.Message, 0, this.chunks));
}, this);
}
if (this.chunking) {
this.chunkSize = chunkSize;
this.chunks = (int) Math.Ceiling((double) this.Size / (double) chunkSize);
} else {
this.chunkSize = (int) this.Size;
this.chunks = 1;
}
this.UploadNextChunk();
}
private int ReadByteRange(byte[] buffer, int position, int offset, int count) {
Stream fileStream;
int bytes = -1;
// Read from image memory stream if it's defined
if (this.imageStream != null) {
this.imageStream.Seek(position, SeekOrigin.Begin);
return this.imageStream.Read(buffer, offset, count);
}
// Open the file and read the specified part of it
fileStream = this.info.OpenRead();
using (fileStream) {
fileStream.Seek(position, SeekOrigin.Begin);
bytes = fileStream.Read(buffer, offset, count);
fileStream.Close();
}
return bytes;
}
/// <summary>
/// Uploads the next chunk if there are more in queue.
/// </summary>
/// <returns>True/false if there are more chunks to be uploaded.</returns>
public bool UploadNextChunk() {
string url = this.uploadUrl;
// Is there more chunks
if (this.chunk >= this.chunks)
return false;
this.syncContext = SynchronizationContext.Current;
// Add name, chunk and chunks to query string when we don't use multipart
if (!this.multipart) {
if (url.IndexOf('?') == -1) {
url += '?';
}
url += "name=" + Uri.EscapeDataString(this.targetName);
if (this.chunking) {
url += "&chunk=" + this.chunk;
url += "&chunks=" + this.chunks;
}
}
HttpWebRequest req = WebRequest.Create(new Uri(HtmlPage.Document.DocumentUri, url)) as HttpWebRequest;
req.Method = "POST";
// Add custom headers
if (this.headers != null) {
foreach (string key in this.headers.Keys)
req.Headers[key] = (string)this.headers[key];
}
IAsyncResult asyncResult = req.BeginGetRequestStream(new AsyncCallback(RequestStreamCallback), req);
return true;
}
#region protected methods
protected virtual void OnUploadComplete(UploadEventArgs e) {
if (UploadComplete != null)
UploadComplete(this, e);
}
protected virtual void OnUploadChunkComplete(UploadEventArgs e) {
if (UploadChunkComplete != null)
UploadChunkComplete(this, e);
}
protected virtual void OnIOError(ErrorEventArgs e) {
if (Error != null)
Error(this, e);
}
protected virtual void OnProgress(ProgressEventArgs e) {
if (Progress != null)
Progress(this, e);
}
#endregion
#region private methods
private void RequestStreamCallback(IAsyncResult ar) {
HttpWebRequest request = (HttpWebRequest) ar.AsyncState;
string boundary = "----pluploadboundary" + DateTime.Now.Ticks, dashdash = "--", crlf = "\r\n";
Stream requestStream = null;
byte[] buffer = new byte[16384], strBuff;
int bytes, loaded = 0, end;
int percent, lastPercent = 0;
try {
requestStream = request.EndGetRequestStream(ar);
if (this.multipart) {
request.ContentType = "multipart/form-data; boundary=" + boundary;
// Add name to multipart array
this.multipartParams["name"] = this.targetName;
// Add chunking when needed
if (this.chunking) {
this.multipartParams["chunk"] = this.chunk;
this.multipartParams["chunks"] = this.chunks;
}
// Append mutlipart parameters
foreach (KeyValuePair<string, object> pair in this.multipartParams) {
strBuff = this.StrToByteArray(dashdash + boundary + crlf +
"Content-Disposition: form-data; name=\"" + pair.Key + '"' + crlf + crlf +
pair.Value + crlf
);
requestStream.Write(strBuff, 0, strBuff.Length);
}
// Append multipart file header
strBuff = this.StrToByteArray(
dashdash + boundary + crlf +
"Content-Disposition: form-data; name=\"" + this.fileDataName + "\"; filename=\"" + this.name + '"' +
crlf + "Content-Type: " + this.mimeType + crlf + crlf
);
requestStream.Write(strBuff, 0, strBuff.Length);
} else {
request.ContentType = "application/octet-stream";
}
// Move to start
loaded = this.chunk * this.chunkSize;
// Find end
end = (this.chunk + 1) * this.chunkSize;
if (end > this.Size)
end = (int) this.Size;
while (loaded < end && (bytes = ReadByteRange(buffer, loaded, 0, end - loaded < buffer.Length ? end - loaded : buffer.Length)) != 0) {
loaded += bytes;
percent = (int) Math.Round((double) loaded / (double) this.Size * 100.0);
if (percent > lastPercent) {
syncContext.Post(delegate {
if (percent > lastPercent) {
this.OnProgress(new ProgressEventArgs(loaded, this.Size));
lastPercent = percent;
}
}, this);
}
requestStream.Write(buffer, 0, bytes);
requestStream.Flush();
}
// Append multipart file footer
if (this.multipart) {
strBuff = this.StrToByteArray(crlf + dashdash + boundary + dashdash + crlf);
requestStream.Write(strBuff, 0, strBuff.Length);
}
} catch (Exception ex) {
syncContext.Send(delegate {
this.OnIOError(new ErrorEventArgs(ex.Message, this.chunk, this.chunks));
}, this);
} finally {
try {
if (requestStream != null) {
requestStream.Close();
requestStream.Dispose();
requestStream = null;
}
} catch (Exception ex) {
syncContext.Send(delegate {
this.OnIOError(new ErrorEventArgs(ex.Message, this.chunk, this.chunks));
}, this);
}
}
try {
request.BeginGetResponse(new AsyncCallback(ResponseCallback), request);
} catch (Exception ex) {
syncContext.Send(delegate {
this.OnIOError(new ErrorEventArgs(ex.Message, this.chunk, this.chunks));
}, this);
}
}
private void ResponseCallback(IAsyncResult ar) {
try {
HttpWebRequest request = ar.AsyncState as HttpWebRequest;
WebResponse response = request.EndGetResponse(ar);
syncContext.Post(ExtractResponse, response);
} catch (Exception ex) {
syncContext.Send(delegate {
this.OnIOError(new ErrorEventArgs(ex.Message, this.chunk, this.chunks));
}, this);
}
}
private void ExtractResponse(object state) {
HttpWebResponse response = state as HttpWebResponse;
StreamReader respReader = null;
Stream respStream = null;
string content;
try {
respStream = response.GetResponseStream();
if (response.StatusCode == HttpStatusCode.OK) {
respReader = new StreamReader(respStream);
if (respStream != null) {
content = respReader.ReadToEnd();
} else
throw new Exception("Error could not open response stream.");
} else
throw new Exception("Error server returned status: " + ((int) response.StatusCode) + " " + response.StatusDescription);
this.chunk++;
syncContext.Send(delegate {
this.OnUploadChunkComplete(new UploadEventArgs(content, this.chunk - 1, this.chunks));
}, this);
} catch (Exception ex) {
syncContext.Send(delegate {
this.OnIOError(new ErrorEventArgs(ex.Message, chunk, chunks));
}, this);
} finally {
if (respStream != null)
respStream.Close();
if (respReader != null)
respReader.Close();
response.Close();
}
}
private void Debug(string msg) {
((ScriptObject) HtmlPage.Window.Eval("console")).Invoke("log", new string[] {msg});
}
private Stream ResizeImage(Stream image_stream, int width, int height, int quality, ImageType type) {
try {
// Load the image as a writeablebitmap
WriteableBitmap writableBitmap;
BitmapImage bitmapImage = new BitmapImage();
bitmapImage.SetSource(image_stream);
writableBitmap = new WriteableBitmap(bitmapImage);
double scale = Math.Min((double) width / writableBitmap.PixelWidth, (double) height / writableBitmap.PixelHeight);
// No resize needed
if (scale >= 1.0)
return image_stream;
// Setup shorter names and pixelbuffers
int w = writableBitmap.PixelWidth;
int h = writableBitmap.PixelHeight;
int[] p = writableBitmap.Pixels;
byte[][,] imageRaster = new byte[3][,]; // RGB colors
imageRaster[0] = new byte[w, h];
imageRaster[1] = new byte[w, h];
imageRaster[2] = new byte[w, h];
// Copy WriteableBitmap data into buffer for FluxJpeg
int i = 0;
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
int color = p[i++];
imageRaster[0][x, y] = (byte) (color >> 16); // R
imageRaster[1][x, y] = (byte) (color >> 8); // G
imageRaster[2][x, y] = (byte) (color); // B
}
}
// Create new FluxJpeg image based on pixel data
FluxJpeg.Core.Image jpegImage = new FluxJpeg.Core.Image(new ColorModel {
colorspace = ColorSpace.RGB
}, imageRaster);
// Calc new proportional size
width = (int) Math.Round(writableBitmap.PixelWidth * scale);
height = (int) Math.Round(writableBitmap.PixelHeight * scale);
// Resize the image
ImageResizer resizer = new ImageResizer(jpegImage);
Image resizedImage = resizer.Resize(width, height, FluxJpeg.Core.Filtering.ResamplingFilters.LowpassAntiAlias);
Stream imageStream = new MemoryStream();
if (type == ImageType.Jpeg) {
// Encode the resized image as Jpeg
JpegEncoder jpegEncoder = new JpegEncoder(resizedImage, quality, imageStream);
jpegEncoder.Encode();
} else {
int[] pixelBuffer = new int[resizedImage.Height * resizedImage.Width];
byte[][,] resizedRaster = resizedImage.Raster;
// Convert FJCore raster to PixelBuffer
for (int y = 0; y < resizedImage.Height; y++) {
for (int x = 0; x < resizedImage.Width; x++) {
int color = 0;
color = color | resizedRaster[0][x, y] << 16; // R
color = color | resizedRaster[1][x, y] << 8; // G
color = color | resizedRaster[2][x, y]; // B
pixelBuffer[(y * resizedImage.Width) + x] = color;
}
}
// Encode the resized image as Png
PngEncoder pngEncoder = new PngEncoder(pixelBuffer, resizedImage.Width, resizedImage.Height, false, PngEncoder.FILTER_NONE, Deflater.BEST_COMPRESSION);
byte[] pngBuffer = pngEncoder.pngEncode();
imageStream.Write(pngBuffer, 0, pngBuffer.Length);
}
return imageStream;
} catch {
// Ignore the error and let the server resize the image
}
return image_stream;
}
private byte[] StrToByteArray(string str) {
System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
return encoding.GetBytes(str);
}
#endregion
}
/// <summary>
/// Upload event arguments class.
/// </summary>
public class UploadEventArgs : EventArgs {
#region private fields
private string response;
private int chunk, chunks;
#endregion
/// <summary>
/// Main constructor for the upload event.
/// </summary>
/// <param name="response">Response contents as a string.</param>
public UploadEventArgs(string response) : this(response, 0, 0) {
}
/// <summary>
/// Main constructor for the upload event.
/// </summary>
/// <param name="response">Response contents as a string.</param>
/// <param name="chunk">Current chunk number.</param>
/// <param name="chunks">Total chunks.</param>
public UploadEventArgs(string response, int chunk, int chunks) {
this.response = response;
this.chunk = chunk;
this.chunks = chunks;
}
/// <summary>Response from upload request.</summary>
public string Response {
get { return response; }
}
/// <summary>Chunk number.</summary>
public int Chunk {
get { return chunk; }
}
/// <summary>Total number of chunks.</summary>
public int Chunks {
get { return chunks; }
}
}
/// <summary>
/// Error event arguments class.
/// </summary>
public class ErrorEventArgs : EventArgs {
#region private fields
private string message;
private int chunk, chunks;
#endregion
/// <summary>
/// Main constructor for the error event.
/// </summary>
/// <param name="message">Error message.</param>
public ErrorEventArgs(string message) : this(message, 0, 0) {
this.message = message;
}
/// <summary>
/// Main constructor for the error event.
/// </summary>
/// <param name="message">Error message.</param>
/// <param name="chunk">Current chunk number.</param>
/// <param name="chunks">Total chunks.</param>
public ErrorEventArgs(string message, int chunk, int chunks) {
this.message = message;
this.chunk = chunk;
this.chunks = chunks;
}
/// <summary>Chunk number.</summary>
public int Chunk {
get { return chunk; }
}
/// <summary>Total number of chunks.</summary>
public int Chunks {
get { return chunks; }
}
/// <summary>Error message.</summary>
public string Message {
get { return message; }
}
}
/// <summary>
/// Progress event arguments class.
/// </summary>
public class ProgressEventArgs : EventArgs {
#region private fields
private long loaded, total;
#endregion
/// <summary>
/// Main constructor for the progress events args.
/// </summary>
/// <param name="loaded">Number of bytes uploaded.</param>
/// <param name="total">Total bytes to upload.</param>
public ProgressEventArgs(long loaded, long total) {
this.loaded = loaded;
this.total = total;
}
/// <summary>Total bytes to upload.</summary>
public long Total {
get { return total; }
}
/// <summary>Number of bytes upload so far.</summary>
public long Loaded {
get { return loaded; }
}
}
}

View file

@ -1,7 +0,0 @@
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Moxiecode.Plupload.Page"
Width="1024" Height="1024" Background="Transparent" Cursor="Hand">
<Canvas Background="Transparent"></Canvas>
</UserControl>

View file

@ -1,207 +0,0 @@
/**
* Page.xaml.cs
*
* Copyright 2009, Moxiecode Systems AB
* Released under GPL License.
*
* License: http://www.plupload.com/license
* Contributing: http://www.plupload.com/contributing
*/
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Browser;
using System.Net;
using System.IO;
using System.Collections.Generic;
using System.Threading;
using Moxiecode.Plupload;
namespace Moxiecode.Plupload {
/// <summary>
/// Partial page class for the Silverlight page.
/// </summary>
public partial class Page : UserControl {
#region private fields
private Dictionary<string, FileReference> files;
private int idCount = 0;
private FileReference currentFile;
private string id, filter;
private bool multiselect;
#endregion
/// <summary>
/// Main constructor.
/// </summary>
/// <param name="init_params">Silverlight init params.</param>
public Page(IDictionary<string, string> init_params) {
InitializeComponent();
HtmlPage.RegisterScriptableObject("Upload", this);
this.files = new Dictionary<string, FileReference>();
this.id = init_params["id"];
this.filter = init_params["filter"];
this.multiselect = Convert.ToBoolean(init_params["multiselect"]);
this.FireEvent("Init");
this.MouseLeftButtonUp += new MouseButtonEventHandler(OnClick);
this.MouseLeftButtonDown += new MouseButtonEventHandler(OnMouseLeftButtonDown);
this.MouseEnter += new MouseEventHandler(OnMouseEnter);
this.MouseLeave += new MouseEventHandler(OnMouseLeave);
}
private void OnClick(object sender, MouseEventArgs e) {
OpenFileDialog dlg = new OpenFileDialog();
this.FireEvent("StartSelectFiles");
try {
dlg.Multiselect = this.multiselect;
dlg.Filter = this.filter;
if ((bool) dlg.ShowDialog()) {
foreach (FileInfo file in dlg.Files) {
FileReference uploadFile = new FileReference("u" + this.idCount++, file);
uploadFile.UploadChunkComplete += delegate(object up_sender, UploadEventArgs args) {
FileReference evtFile = (FileReference) up_sender;
this.FireEvent("UploadChunkSuccessful", evtFile.Id, args.Chunk, args.Chunks, args.Response);
};
uploadFile.UploadComplete += delegate(object up_sender, UploadEventArgs args) {
FileReference evtFile = (FileReference) up_sender;
this.FireEvent("UploadSuccessful", evtFile.Id, args.Response);
};
uploadFile.Error += delegate(object up_sender, ErrorEventArgs args) {
FileReference evtFile = (FileReference) up_sender;
this.FireEvent("UploadChunkError", evtFile.Id, args.Chunk, args.Chunks, args.Message);
};
uploadFile.Progress += delegate(object up_sender, ProgressEventArgs args) {
FileReference evtFile = (FileReference) up_sender;
this.FireEvent("UploadFileProgress", evtFile.Id, args.Loaded, args.Total);
};
this.FireEvent("SelectFile", uploadFile.Id, uploadFile.Name, uploadFile.Size);
this.files[uploadFile.Id] = uploadFile;
}
this.FireEvent("SelectSuccessful");
} else
this.FireEvent("SelectCancelled");
} catch (Exception ex) {
this.FireEvent("SelectError", ex.Message);
}
}
private void OnMouseLeftButtonDown(object sender, MouseEventArgs e) {
this.FireEvent("MouseLeftButtonDown");
}
private void OnMouseEnter(object sender, MouseEventArgs e) {
this.FireEvent("MouseEnter");
}
private void OnMouseLeave(object sender, MouseEventArgs e) {
this.FireEvent("MouseLeave");
}
/// <summary>
/// Reference to page level plupload.silverlight script object.
/// </summary>
public ScriptObject PluploadScriptObject {
get { return ((ScriptObject) HtmlPage.Window.Eval("plupload.silverlight")); }
}
/// <summary>
/// Fires a specific event to the page level multi upload script.
/// </summary>
/// <param name="name">Event name to fire.</param>
public void FireEvent(string name) {
this.PluploadScriptObject.Invoke("trigger", new string[] { this.id, name });
}
/// <summary>
/// Fires a specific event to the page level multi upload script.
/// </summary>
/// <param name="name">Event name to fire.</param>
/// <param name="paramlist">Numerous parameters to send.</param>
public void FireEvent(string name, params object[] paramlist) {
List<object> args = new List<object>(paramlist);
args.Insert(0, name);
args.Insert(0, this.id);
this.PluploadScriptObject.Invoke("trigger", args.ToArray());
}
[ScriptableMember]
/// <summary>
/// Uploads a specific file by id to the specific url and using a chunks.
/// </summary>
/// <param name="id">File id to upload.</param>
/// <param name="upload_url">Url to upload to.</param>
/// <param name="chunk_size">Chunk size to use.</param>
public void UploadFile(string id, string upload_url, string json_settings) {
if (this.files.ContainsKey(id)) {
FileReference file = this.files[id];
this.currentFile = file;
file.Upload(upload_url, json_settings);
}
}
[ScriptableMember]
/// <summary>
/// Removes the specified file by id.
/// </summary>
/// <param name="id">File id to remove.</param>
public void RemoveFile(string id) {
if (this.files.ContainsKey(id))
this.files[id] = null;
}
[ScriptableMember]
/// <summary>
/// Clears all files.
/// </summary>
public void ClearFiles() {
this.files = new Dictionary<string, FileReference>();
}
[ScriptableMember]
/// <summary>
/// Uploads the next chunk of the current file. Returns true/false if there is more chunks.
/// </summary>
/// <return>true/false if there is more chunks</return>
public bool UploadNextChunk() {
if (this.currentFile != null)
return this.currentFile.UploadNextChunk();
return false;
}
/// <summary>
/// Send debug message to firebug console.
/// </summary>
/// <param name="msg">Message to write.</param>
private void Debug(string msg) {
((ScriptObject) HtmlPage.Window.Eval("console")).Invoke("log", new string[] { msg });
}
}
}

View file

@ -1,223 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(MSBuildToolsVersion)' == '3.5'">
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<DefaultClrNameSpace>Plupload</DefaultClrNameSpace>
<AssemblyName>plupload.silverlight</AssemblyName>
<RootNamespace>Moxiecode.Plupload</RootNamespace>
<AlwaysCompileMarkupFilesInSeparateDomain>false</AlwaysCompileMarkupFilesInSeparateDomain>
<ExpressionBlendCreationVersion>2.1.1535.0</ExpressionBlendCreationVersion>
<ProjectGuid>{95F0DEE8-DE7A-46C5-9DCC-0570B0FC4643}</ProjectGuid>
<OutputType>Library</OutputType>
<NoStdLib>true</NoStdLib>
<TargetFrameworkVersion>v3.0</TargetFrameworkVersion>
<ProjectTypeGuids>{A1591282-1198-4647-A2B1-27E5FF5F6F3B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<StartPageUrl>Default.html</StartPageUrl>
<XapOutputs>true</XapOutputs>
<XapFilename>plupload.silverlight.xap</XapFilename>
<GenerateSilverlightManifest>true</GenerateSilverlightManifest>
<SilverlightManifestTemplate>Properties\AppManifest.xml</SilverlightManifestTemplate>
<SilverlightAppEntry>Moxiecode.Plupload.App</SilverlightAppEntry>
<CreateTestPage>true</CreateTestPage>
<TestPageFileName>Default.html</TestPageFileName>
<DefineConstants>SILVERLIGHT</DefineConstants>
<SilverlightApplication>true</SilverlightApplication>
<SourceAnalysisOverrideSettingsFile>C:\Users\spocke\AppData\Roaming\ICSharpCode/SharpDevelop3.0\Settings.SourceAnalysis</SourceAnalysisOverrideSettingsFile>
<RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
<AllowUnsafeBlocks>False</AllowUnsafeBlocks>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<FileUpgradeFlags>
</FileUpgradeFlags>
<UpgradeBackupLocation>
</UpgradeBackupLocation>
<OldToolsVersion>3.5</OldToolsVersion>
<TargetFrameworkIdentifier>Silverlight</TargetFrameworkIdentifier>
<SilverlightVersion>$(TargetFrameworkVersion)</SilverlightVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
<UsePlatformExtensions>true</UsePlatformExtensions>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;SILVERLIGHT</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>PdbOnly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\</OutputPath>
<DefineConstants>SILVERLIGHT</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DebugSymbols>false</DebugSymbols>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<CheckForOverflowUnderflow>False</CheckForOverflowUnderflow>
</PropertyGroup>
<PropertyGroup Condition=" '$(Platform)' == 'AnyCPU' ">
<RegisterForComInterop>False</RegisterForComInterop>
<GenerateSerializationAssemblies>Auto</GenerateSerializationAssemblies>
<BaseAddress>4194304</BaseAddress>
<PlatformTarget>AnyCPU</PlatformTarget>
<FileAlignment>4096</FileAlignment>
</PropertyGroup>
<ItemGroup>
<Reference Include="mscorlib" />
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Net" />
<Reference Include="System.Windows" />
<Reference Include="System.Windows.Browser" />
<Reference Include="System.Xml" />
<ApplicationDefinition Include="App.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
</Compile>
<Compile Include="FJCore\DCT.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="FJCore\DecodedJpeg.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="FJCore\Decoder\HuffmanTable.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="FJCore\Decoder\JpegHuffmanTable.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="FJCore\Decoder\JpegQuantizationTable.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="FJCore\Encoder\JpegEncoder.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="FJCore\FDCT.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="FJCore\Filter\Convolution.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="FJCore\Filter\FilterBase.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="FJCore\Filter\FilterLowpassResize.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="FJCore\Filter\FilterNNResize.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="FJCore\Filter\GrayImage.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="FJCore\Image.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="FJCore\IO\BinaryWriter.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="FJCore\JpegMarker.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="FJCore\Resize\ImageResizer.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="FJCore\YCbCr.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="FJCore\ZigZag.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Page.xaml.cs">
<DependentUpon>Page.xaml</DependentUpon>
</Compile>
<Compile Include="PngEncoder\Adler32.cs" />
<Compile Include="PngEncoder\CRC32.cs" />
<Compile Include="PngEncoder\Deflater.cs" />
<Compile Include="PngEncoder\DeflaterConstants.cs" />
<Compile Include="PngEncoder\DeflaterEngine.cs" />
<Compile Include="PngEncoder\DeflaterHuffman.cs" />
<Compile Include="PngEncoder\DeflaterOutputStream.cs" />
<Compile Include="PngEncoder\DeflaterPending.cs" />
<Compile Include="PngEncoder\IChecksum.cs" />
<Compile Include="PngEncoder\PngEncoder.cs" />
<Compile Include="PngEncoder\PendingBuffer.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Page Include="Page.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<None Include="Properties\AppManifest.xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="FileReference.cs" />
<Compile Include="Utils\JsonReader.cs" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.VisualBasic.PowerPacks.10.0">
<Visible>False</Visible>
<ProductName>Microsoft Visual Basic PowerPacks 10.0</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
<Visible>False</Visible>
<ProductName>Windows Installer 3.1</ProductName>
<Install>true</Install>
</BootstrapperPackage>
</ItemGroup>
<ItemGroup />
<ItemGroup>
<Content Include="FJCore\IJG.txt" />
<Content Include="FJCore\JAI.txt" />
<Content Include="FJCore\License.txt" />
<Content Include="FJCore\README.txt" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Silverlight\$(SilverlightVersion)\Microsoft.Silverlight.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>copy /Y plupload.silverlight.xap ..\..\..\..\js\plupload.silverlight.xap</PostBuildEvent>
</PropertyGroup>
<ProjectExtensions>
<VisualStudio>
<FlavorProperties GUID="{A1591282-1198-4647-A2B1-27E5FF5F6F3B}">
<SilverlightProjectProperties />
</FlavorProperties>
</VisualStudio>
</ProjectExtensions>
</Project>

View file

@ -1,20 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Plupload", "Plupload.csproj", "{95F0DEE8-DE7A-46C5-9DCC-0570B0FC4643}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{95F0DEE8-DE7A-46C5-9DCC-0570B0FC4643}.Debug|Any CPU.ActiveCfg = Release|Any CPU
{95F0DEE8-DE7A-46C5-9DCC-0570B0FC4643}.Debug|Any CPU.Build.0 = Release|Any CPU
{95F0DEE8-DE7A-46C5-9DCC-0570B0FC4643}.Release|Any CPU.ActiveCfg = Release|Any CPU
{95F0DEE8-DE7A-46C5-9DCC-0570B0FC4643}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View file

@ -1,216 +0,0 @@
// Adler32.cs - Computes Adler32 data checksum of a data stream
// Copyright (C) 2001 Mike Krueger
//
// This file was translated from java, it was part of the GNU Classpath
// Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
// Linking this library statically or dynamically with other modules is
// making a combined work based on this library. Thus, the terms and
// conditions of the GNU General Public License cover the whole
// combination.
//
// As a special exception, the copyright holders of this library give you
// permission to link this library with independent modules to produce an
// executable, regardless of the license terms of these independent
// modules, and to copy and distribute the resulting executable under
// terms of your choice, provided that you also meet, for each linked
// independent module, the terms and conditions of the license of that
// module. An independent module is a module which is not derived from
// or based on this library. If you modify this library, you may extend
// this exception to your version of the library, but you are not
// obligated to do so. If you do not wish to do so, delete this
// exception statement from your version.
using System;
namespace Plupload.PngEncoder {
/// <summary>
/// Computes Adler32 checksum for a stream of data. An Adler32
/// checksum is not as reliable as a CRC32 checksum, but a lot faster to
/// compute.
///
/// The specification for Adler32 may be found in RFC 1950.
/// ZLIB Compressed Data Format Specification version 3.3)
///
///
/// From that document:
///
/// "ADLER32 (Adler-32 checksum)
/// This contains a checksum value of the uncompressed data
/// (excluding any dictionary data) computed according to Adler-32
/// algorithm. This algorithm is a 32-bit extension and improvement
/// of the Fletcher algorithm, used in the ITU-T X.224 / ISO 8073
/// standard.
///
/// Adler-32 is composed of two sums accumulated per byte: s1 is
/// the sum of all bytes, s2 is the sum of all s1 values. Both sums
/// are done modulo 65521. s1 is initialized to 1, s2 to zero. The
/// Adler-32 checksum is stored as s2*65536 + s1 in most-
/// significant-byte first (network) order."
///
/// "8.2. The Adler-32 algorithm
///
/// The Adler-32 algorithm is much faster than the CRC32 algorithm yet
/// still provides an extremely low probability of undetected errors.
///
/// The modulo on unsigned long accumulators can be delayed for 5552
/// bytes, so the modulo operation time is negligible. If the bytes
/// are a, b, c, the second sum is 3a + 2b + c + 3, and so is position
/// and order sensitive, unlike the first sum, which is just a
/// checksum. That 65521 is prime is important to avoid a possible
/// large class of two-byte errors that leave the check unchanged.
/// (The Fletcher checksum uses 255, which is not prime and which also
/// makes the Fletcher check insensitive to single byte changes 0 -
/// 255.)
///
/// The sum s1 is initialized to 1 instead of zero to make the length
/// of the sequence part of s2, so that the length does not have to be
/// checked separately. (Any sequence of zeroes has a Fletcher
/// checksum of zero.)"
/// </summary>
/// <see cref="ICSharpCode.SharpZipLib.Zip.Compression.Streams.InflaterInputStream"/>
/// <see cref="ICSharpCode.SharpZipLib.Zip.Compression.Streams.DeflaterOutputStream"/>
public sealed class Adler32 : IChecksum {
/// <summary>
/// largest prime smaller than 65536
/// </summary>
const uint BASE = 65521;
/// <summary>
/// Returns the Adler32 data checksum computed so far.
/// </summary>
public long Value {
get {
return checksum;
}
}
/// <summary>
/// Creates a new instance of the Adler32 class.
/// The checksum starts off with a value of 1.
/// </summary>
public Adler32() {
Reset();
}
/// <summary>
/// Resets the Adler32 checksum to the initial value.
/// </summary>
public void Reset() {
checksum = 1;
}
/// <summary>
/// Updates the checksum with a byte value.
/// </summary>
/// <param name="value">
/// The data value to add. The high byte of the int is ignored.
/// </param>
public void Update(int value) {
// We could make a length 1 byte array and call update again, but I
// would rather not have that overhead
uint s1 = checksum & 0xFFFF;
uint s2 = checksum >> 16;
s1 = (s1 + ((uint) value & 0xFF)) % BASE;
s2 = (s1 + s2) % BASE;
checksum = (s2 << 16) + s1;
}
/// <summary>
/// Updates the checksum with an array of bytes.
/// </summary>
/// <param name="buffer">
/// The source of the data to update with.
/// </param>
public void Update(byte[] buffer) {
if (buffer == null) {
throw new ArgumentNullException("buffer");
}
Update(buffer, 0, buffer.Length);
}
/// <summary>
/// Updates the checksum with the bytes taken from the array.
/// </summary>
/// <param name="buffer">
/// an array of bytes
/// </param>
/// <param name="offset">
/// the start of the data used for this update
/// </param>
/// <param name="count">
/// the number of bytes to use for this update
/// </param>
public void Update(byte[] buffer, int offset, int count) {
if (buffer == null) {
throw new ArgumentNullException("buffer");
}
if (offset < 0) {
throw new ArgumentOutOfRangeException("offset");
}
if (count < 0) {
throw new ArgumentOutOfRangeException("count");
}
if (offset >= buffer.Length) {
throw new ArgumentOutOfRangeException("offset");
}
if (offset + count > buffer.Length) {
throw new ArgumentOutOfRangeException("count");
}
//(By Per Bothner)
uint s1 = checksum & 0xFFFF;
uint s2 = checksum >> 16;
while (count > 0) {
// We can defer the modulo operation:
// s1 maximally grows from 65521 to 65521 + 255 * 3800
// s2 maximally grows by 3800 * median(s1) = 2090079800 < 2^31
int n = 3800;
if (n > count) {
n = count;
}
count -= n;
while (--n >= 0) {
s1 = s1 + (uint) (buffer[offset++] & 0xff);
s2 = s2 + s1;
}
s1 %= BASE;
s2 %= BASE;
}
checksum = (s2 << 16) | s1;
}
#region Instance Fields
uint checksum;
#endregion
}
}

View file

@ -1,213 +0,0 @@
// CRC32.cs - Computes CRC32 data checksum of a data stream
// Copyright (C) 2001 Mike Krueger
//
// This file was translated from java, it was part of the GNU Classpath
// Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
// Linking this library statically or dynamically with other modules is
// making a combined work based on this library. Thus, the terms and
// conditions of the GNU General Public License cover the whole
// combination.
//
// As a special exception, the copyright holders of this library give you
// permission to link this library with independent modules to produce an
// executable, regardless of the license terms of these independent
// modules, and to copy and distribute the resulting executable under
// terms of your choice, provided that you also meet, for each linked
// independent module, the terms and conditions of the license of that
// module. An independent module is a module which is not derived from
// or based on this library. If you modify this library, you may extend
// this exception to your version of the library, but you are not
// obligated to do so. If you do not wish to do so, delete this
// exception statement from your version.
using System;
namespace Plupload.PngEncoder {
/// <summary>
/// Generate a table for a byte-wise 32-bit CRC calculation on the polynomial:
/// x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
///
/// Polynomials over GF(2) are represented in binary, one bit per coefficient,
/// with the lowest powers in the most significant bit. Then adding polynomials
/// is just exclusive-or, and multiplying a polynomial by x is a right shift by
/// one. If we call the above polynomial p, and represent a byte as the
/// polynomial q, also with the lowest power in the most significant bit (so the
/// byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
/// where a mod b means the remainder after dividing a by b.
///
/// This calculation is done using the shift-register method of multiplying and
/// taking the remainder. The register is initialized to zero, and for each
/// incoming bit, x^32 is added mod p to the register if the bit is a one (where
/// x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
/// x (which is shifting right by one and adding x^32 mod p if the bit shifted
/// out is a one). We start with the highest power (least significant bit) of
/// q and repeat for all eight bits of q.
///
/// The table is simply the CRC of all possible eight bit values. This is all
/// the information needed to generate CRC's on data a byte at a time for all
/// combinations of CRC register values and incoming bytes.
/// </summary>
public sealed class Crc32 : IChecksum {
const uint CrcSeed = 0xFFFFFFFF;
readonly static uint[] CrcTable = new uint[] {
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419,
0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4,
0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07,
0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856,
0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4,
0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3,
0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A,
0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599,
0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190,
0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F,
0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E,
0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED,
0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3,
0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A,
0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5,
0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010,
0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17,
0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6,
0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615,
0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344,
0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A,
0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1,
0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C,
0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF,
0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE,
0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31,
0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C,
0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B,
0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1,
0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278,
0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7,
0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66,
0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605,
0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8,
0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B,
0x2D02EF8D
};
internal static uint ComputeCrc32(uint oldCrc, byte value) {
return (uint) (Crc32.CrcTable[(oldCrc ^ value) & 0xFF] ^ (oldCrc >> 8));
}
/// <summary>
/// The crc data checksum so far.
/// </summary>
uint crc;
/// <summary>
/// Returns the CRC32 data checksum computed so far.
/// </summary>
public long Value {
get {
return (long) crc;
}
set {
crc = (uint) value;
}
}
/// <summary>
/// Resets the CRC32 data checksum as if no update was ever called.
/// </summary>
public void Reset() {
crc = 0;
}
/// <summary>
/// Updates the checksum with the int bval.
/// </summary>
/// <param name = "value">
/// the byte is taken as the lower 8 bits of value
/// </param>
public void Update(int value) {
crc ^= CrcSeed;
crc = CrcTable[(crc ^ value) & 0xFF] ^ (crc >> 8);
crc ^= CrcSeed;
}
/// <summary>
/// Updates the checksum with the bytes taken from the array.
/// </summary>
/// <param name="buffer">
/// buffer an array of bytes
/// </param>
public void Update(byte[] buffer) {
if (buffer == null) {
throw new ArgumentNullException("buffer");
}
Update(buffer, 0, buffer.Length);
}
/// <summary>
/// Adds the byte array to the data checksum.
/// </summary>
/// <param name = "buffer">
/// The buffer which contains the data
/// </param>
/// <param name = "offset">
/// The offset in the buffer where the data starts
/// </param>
/// <param name = "count">
/// The number of data bytes to update the CRC with.
/// </param>
public void Update(byte[] buffer, int offset, int count) {
if (buffer == null) {
throw new ArgumentNullException("buffer");
}
if (count < 0) {
throw new ArgumentOutOfRangeException("count");
}
if (offset < 0 || offset + count > buffer.Length) {
throw new ArgumentOutOfRangeException("offset");
}
crc ^= CrcSeed;
while (--count >= 0) {
crc = CrcTable[(crc ^ buffer[offset++]) & 0xFF] ^ (crc >> 8);
}
crc ^= CrcSeed;
}
}
}

View file

@ -1,543 +0,0 @@
// Deflater.cs
//
// Copyright (C) 2001 Mike Krueger
// Copyright (C) 2004 John Reilly
//
// This file was translated from java, it was part of the GNU Classpath
// Copyright (C) 2001 Free Software Foundation, Inc.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
// Linking this library statically or dynamically with other modules is
// making a combined work based on this library. Thus, the terms and
// conditions of the GNU General Public License cover the whole
// combination.
//
// As a special exception, the copyright holders of this library give you
// permission to link this library with independent modules to produce an
// executable, regardless of the license terms of these independent
// modules, and to copy and distribute the resulting executable under
// terms of your choice, provided that you also meet, for each linked
// independent module, the terms and conditions of the license of that
// module. An independent module is a module which is not derived from
// or based on this library. If you modify this library, you may extend
// this exception to your version of the library, but you are not
// obligated to do so. If you do not wish to do so, delete this
// exception statement from your version.
using System;
namespace Plupload.PngEncoder {
/// <summary>
/// This is the Deflater class. The deflater class compresses input
/// with the deflate algorithm described in RFC 1951. It has several
/// compression levels and three different strategies described below.
///
/// This class is <i>not</i> thread safe. This is inherent in the API, due
/// to the split of deflate and setInput.
///
/// author of the original java version : Jochen Hoenicke
/// </summary>
public class Deflater {
#region Deflater Documentation
/*
* The Deflater can do the following state transitions:
*
* (1) -> INIT_STATE ----> INIT_FINISHING_STATE ---.
* / | (2) (5) |
* / v (5) |
* (3)| SETDICT_STATE ---> SETDICT_FINISHING_STATE |(3)
* \ | (3) | ,--------'
* | | | (3) /
* v v (5) v v
* (1) -> BUSY_STATE ----> FINISHING_STATE
* | (6)
* v
* FINISHED_STATE
* \_____________________________________/
* | (7)
* v
* CLOSED_STATE
*
* (1) If we should produce a header we start in INIT_STATE, otherwise
* we start in BUSY_STATE.
* (2) A dictionary may be set only when we are in INIT_STATE, then
* we change the state as indicated.
* (3) Whether a dictionary is set or not, on the first call of deflate
* we change to BUSY_STATE.
* (4) -- intentionally left blank -- :)
* (5) FINISHING_STATE is entered, when flush() is called to indicate that
* there is no more INPUT. There are also states indicating, that
* the header wasn't written yet.
* (6) FINISHED_STATE is entered, when everything has been flushed to the
* internal pending output buffer.
* (7) At any time (7)
*
*/
#endregion
#region Public Constants
/// <summary>
/// The best and slowest compression level. This tries to find very
/// long and distant string repetitions.
/// </summary>
public const int BEST_COMPRESSION = 9;
/// <summary>
/// The worst but fastest compression level.
/// </summary>
public const int BEST_SPEED = 1;
/// <summary>
/// The default compression level.
/// </summary>
public const int DEFAULT_COMPRESSION = -1;
/// <summary>
/// This level won't compress at all but output uncompressed blocks.
/// </summary>
public const int NO_COMPRESSION = 0;
/// <summary>
/// The compression method. This is the only method supported so far.
/// There is no need to use this constant at all.
/// </summary>
public const int DEFLATED = 8;
#endregion
#region Local Constants
private const int IS_SETDICT = 0x01;
private const int IS_FLUSHING = 0x04;
private const int IS_FINISHING = 0x08;
private const int INIT_STATE = 0x00;
private const int SETDICT_STATE = 0x01;
// private static int INIT_FINISHING_STATE = 0x08;
// private static int SETDICT_FINISHING_STATE = 0x09;
private const int BUSY_STATE = 0x10;
private const int FLUSHING_STATE = 0x14;
private const int FINISHING_STATE = 0x1c;
private const int FINISHED_STATE = 0x1e;
private const int CLOSED_STATE = 0x7f;
#endregion
#region Constructors
/// <summary>
/// Creates a new deflater with default compression level.
/// </summary>
public Deflater()
: this(DEFAULT_COMPRESSION, false) {
}
/// <summary>
/// Creates a new deflater with given compression level.
/// </summary>
/// <param name="level">
/// the compression level, a value between NO_COMPRESSION
/// and BEST_COMPRESSION, or DEFAULT_COMPRESSION.
/// </param>
/// <exception cref="System.ArgumentOutOfRangeException">if lvl is out of range.</exception>
public Deflater(int level)
: this(level, false) {
}
/// <summary>
/// Creates a new deflater with given compression level.
/// </summary>
/// <param name="level">
/// the compression level, a value between NO_COMPRESSION
/// and BEST_COMPRESSION.
/// </param>
/// <param name="noZlibHeaderOrFooter">
/// true, if we should suppress the Zlib/RFC1950 header at the
/// beginning and the adler checksum at the end of the output. This is
/// useful for the GZIP/PKZIP formats.
/// </param>
/// <exception cref="System.ArgumentOutOfRangeException">if lvl is out of range.</exception>
public Deflater(int level, bool noZlibHeaderOrFooter) {
if (level == DEFAULT_COMPRESSION) {
level = 6;
} else if (level < NO_COMPRESSION || level > BEST_COMPRESSION) {
throw new ArgumentOutOfRangeException("level");
}
pending = new DeflaterPending();
engine = new DeflaterEngine(pending);
this.noZlibHeaderOrFooter = noZlibHeaderOrFooter;
SetStrategy(DeflateStrategy.Default);
SetLevel(level);
Reset();
}
#endregion
/// <summary>
/// Resets the deflater. The deflater acts afterwards as if it was
/// just created with the same compression level and strategy as it
/// had before.
/// </summary>
public void Reset() {
state = (noZlibHeaderOrFooter ? BUSY_STATE : INIT_STATE);
totalOut = 0;
pending.Reset();
engine.Reset();
}
/// <summary>
/// Gets the current adler checksum of the data that was processed so far.
/// </summary>
public int Adler {
get {
return engine.Adler;
}
}
/// <summary>
/// Gets the number of input bytes processed so far.
/// </summary>
public long TotalIn {
get {
return engine.TotalIn;
}
}
/// <summary>
/// Gets the number of output bytes so far.
/// </summary>
public long TotalOut {
get {
return totalOut;
}
}
/// <summary>
/// Flushes the current input block. Further calls to deflate() will
/// produce enough output to inflate everything in the current input
/// block. This is not part of Sun's JDK so I have made it package
/// private. It is used by DeflaterOutputStream to implement
/// flush().
/// </summary>
public void Flush() {
state |= IS_FLUSHING;
}
/// <summary>
/// Finishes the deflater with the current input block. It is an error
/// to give more input after this method was called. This method must
/// be called to force all bytes to be flushed.
/// </summary>
public void Finish() {
state |= (IS_FLUSHING | IS_FINISHING);
}
/// <summary>
/// Returns true if the stream was finished and no more output bytes
/// are available.
/// </summary>
public bool IsFinished {
get {
return (state == FINISHED_STATE) && pending.IsFlushed;
}
}
/// <summary>
/// Returns true, if the input buffer is empty.
/// You should then call setInput().
/// NOTE: This method can also return true when the stream
/// was finished.
/// </summary>
public bool IsNeedingInput {
get {
return engine.NeedsInput();
}
}
/// <summary>
/// Sets the data which should be compressed next. This should be only
/// called when needsInput indicates that more input is needed.
/// If you call setInput when needsInput() returns false, the
/// previous input that is still pending will be thrown away.
/// The given byte array should not be changed, before needsInput() returns
/// true again.
/// This call is equivalent to <code>setInput(input, 0, input.length)</code>.
/// </summary>
/// <param name="input">
/// the buffer containing the input data.
/// </param>
/// <exception cref="System.InvalidOperationException">
/// if the buffer was finished() or ended().
/// </exception>
public void SetInput(byte[] input) {
SetInput(input, 0, input.Length);
}
/// <summary>
/// Sets the data which should be compressed next. This should be
/// only called when needsInput indicates that more input is needed.
/// The given byte array should not be changed, before needsInput() returns
/// true again.
/// </summary>
/// <param name="input">
/// the buffer containing the input data.
/// </param>
/// <param name="offset">
/// the start of the data.
/// </param>
/// <param name="count">
/// the number of data bytes of input.
/// </param>
/// <exception cref="System.InvalidOperationException">
/// if the buffer was Finish()ed or if previous input is still pending.
/// </exception>
public void SetInput(byte[] input, int offset, int count) {
if ((state & IS_FINISHING) != 0) {
throw new InvalidOperationException("Finish() already called");
}
engine.SetInput(input, offset, count);
}
/// <summary>
/// Sets the compression level. There is no guarantee of the exact
/// position of the change, but if you call this when needsInput is
/// true the change of compression level will occur somewhere near
/// before the end of the so far given input.
/// </summary>
/// <param name="level">
/// the new compression level.
/// </param>
public void SetLevel(int level) {
if (level == DEFAULT_COMPRESSION) {
level = 6;
} else if (level < NO_COMPRESSION || level > BEST_COMPRESSION) {
throw new ArgumentOutOfRangeException("level");
}
if (this.level != level) {
this.level = level;
engine.SetLevel(level);
}
}
/// <summary>
/// Get current compression level
/// </summary>
/// <returns>Returns the current compression level</returns>
public int GetLevel() {
return level;
}
/// <summary>
/// Sets the compression strategy. Strategy is one of
/// DEFAULT_STRATEGY, HUFFMAN_ONLY and FILTERED. For the exact
/// position where the strategy is changed, the same as for
/// SetLevel() applies.
/// </summary>
/// <param name="strategy">
/// The new compression strategy.
/// </param>
public void SetStrategy(DeflateStrategy strategy) {
engine.Strategy = strategy;
}
/// <summary>
/// Deflates the current input block with to the given array.
/// </summary>
/// <param name="output">
/// The buffer where compressed data is stored
/// </param>
/// <returns>
/// The number of compressed bytes added to the output, or 0 if either
/// IsNeedingInput() or IsFinished returns true or length is zero.
/// </returns>
public int Deflate(byte[] output) {
return Deflate(output, 0, output.Length);
}
/// <summary>
/// Deflates the current input block to the given array.
/// </summary>
/// <param name="output">
/// Buffer to store the compressed data.
/// </param>
/// <param name="offset">
/// Offset into the output array.
/// </param>
/// <param name="length">
/// The maximum number of bytes that may be stored.
/// </param>
/// <returns>
/// The number of compressed bytes added to the output, or 0 if either
/// needsInput() or finished() returns true or length is zero.
/// </returns>
/// <exception cref="System.InvalidOperationException">
/// If Finish() was previously called.
/// </exception>
/// <exception cref="System.ArgumentOutOfRangeException">
/// If offset or length don't match the array length.
/// </exception>
public int Deflate(byte[] output, int offset, int length) {
int origLength = length;
if (state == CLOSED_STATE) {
throw new InvalidOperationException("Deflater closed");
}
if (state < BUSY_STATE) {
// output header
int header = (DEFLATED +
((DeflaterConstants.MAX_WBITS - 8) << 4)) << 8;
int level_flags = (level - 1) >> 1;
if (level_flags < 0 || level_flags > 3) {
level_flags = 3;
}
header |= level_flags << 6;
if ((state & IS_SETDICT) != 0) {
// Dictionary was set
header |= DeflaterConstants.PRESET_DICT;
}
header += 31 - (header % 31);
pending.WriteShortMSB(header);
if ((state & IS_SETDICT) != 0) {
int chksum = engine.Adler;
engine.ResetAdler();
pending.WriteShortMSB(chksum >> 16);
pending.WriteShortMSB(chksum & 0xffff);
}
state = BUSY_STATE | (state & (IS_FLUSHING | IS_FINISHING));
}
for (; ; ) {
int count = pending.Flush(output, offset, length);
offset += count;
totalOut += count;
length -= count;
if (length == 0 || state == FINISHED_STATE) {
break;
}
if (!engine.Deflate((state & IS_FLUSHING) != 0, (state & IS_FINISHING) != 0)) {
if (state == BUSY_STATE) {
// We need more input now
return origLength - length;
} else if (state == FLUSHING_STATE) {
if (level != NO_COMPRESSION) {
/* We have to supply some lookahead. 8 bit lookahead
* is needed by the zlib inflater, and we must fill
* the next byte, so that all bits are flushed.
*/
int neededbits = 8 + ((-pending.BitCount) & 7);
while (neededbits > 0) {
/* write a static tree block consisting solely of
* an EOF:
*/
pending.WriteBits(2, 10);
neededbits -= 10;
}
}
state = BUSY_STATE;
} else if (state == FINISHING_STATE) {
pending.AlignToByte();
// Compressed data is complete. Write footer information if required.
if (!noZlibHeaderOrFooter) {
int adler = engine.Adler;
pending.WriteShortMSB(adler >> 16);
pending.WriteShortMSB(adler & 0xffff);
}
state = FINISHED_STATE;
}
}
}
return origLength - length;
}
/// <summary>
/// Sets the dictionary which should be used in the deflate process.
/// This call is equivalent to <code>setDictionary(dict, 0, dict.Length)</code>.
/// </summary>
/// <param name="dictionary">
/// the dictionary.
/// </param>
/// <exception cref="System.InvalidOperationException">
/// if SetInput () or Deflate () were already called or another dictionary was already set.
/// </exception>
public void SetDictionary(byte[] dictionary) {
SetDictionary(dictionary, 0, dictionary.Length);
}
/// <summary>
/// Sets the dictionary which should be used in the deflate process.
/// The dictionary is a byte array containing strings that are
/// likely to occur in the data which should be compressed. The
/// dictionary is not stored in the compressed output, only a
/// checksum. To decompress the output you need to supply the same
/// dictionary again.
/// </summary>
/// <param name="dictionary">
/// The dictionary data
/// </param>
/// <param name="index">
/// The index where dictionary information commences.
/// </param>
/// <param name="count">
/// The number of bytes in the dictionary.
/// </param>
/// <exception cref="System.InvalidOperationException">
/// If SetInput () or Deflate() were already called or another dictionary was already set.
/// </exception>
public void SetDictionary(byte[] dictionary, int index, int count) {
if (state != INIT_STATE) {
throw new InvalidOperationException();
}
state = SETDICT_STATE;
engine.SetDictionary(dictionary, index, count);
}
#region Instance Fields
/// <summary>
/// Compression level.
/// </summary>
int level;
/// <summary>
/// If true no Zlib/RFC1950 headers or footers are generated
/// </summary>
bool noZlibHeaderOrFooter;
/// <summary>
/// The current state.
/// </summary>
int state;
/// <summary>
/// The total bytes of output written.
/// </summary>
long totalOut;
/// <summary>
/// The pending output.
/// </summary>
DeflaterPending pending;
/// <summary>
/// The deflater engine.
/// </summary>
DeflaterEngine engine;
#endregion
}
}

View file

@ -1,184 +0,0 @@
// DeflaterConstants.cs
//
// Copyright (C) 2001 Mike Krueger
// Copyright (C) 2004 John Reilly
//
// This file was translated from java, it was part of the GNU Classpath
// Copyright (C) 2001 Free Software Foundation, Inc.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
// Linking this library statically or dynamically with other modules is
// making a combined work based on this library. Thus, the terms and
// conditions of the GNU General Public License cover the whole
// combination.
//
// As a special exception, the copyright holders of this library give you
// permission to link this library with independent modules to produce an
// executable, regardless of the license terms of these independent
// modules, and to copy and distribute the resulting executable under
// terms of your choice, provided that you also meet, for each linked
// independent module, the terms and conditions of the license of that
// module. An independent module is a module which is not derived from
// or based on this library. If you modify this library, you may extend
// this exception to your version of the library, but you are not
// obligated to do so. If you do not wish to do so, delete this
// exception statement from your version.
using System;
namespace Plupload.PngEncoder {
/// <summary>
/// This class contains constants used for deflation.
/// </summary>
public class DeflaterConstants {
/// <summary>
/// Set to true to enable debugging
/// </summary>
public const bool DEBUGGING = false;
/// <summary>
/// Written to Zip file to identify a stored block
/// </summary>
public const int STORED_BLOCK = 0;
/// <summary>
/// Identifies static tree in Zip file
/// </summary>
public const int STATIC_TREES = 1;
/// <summary>
/// Identifies dynamic tree in Zip file
/// </summary>
public const int DYN_TREES = 2;
/// <summary>
/// Header flag indicating a preset dictionary for deflation
/// </summary>
public const int PRESET_DICT = 0x20;
/// <summary>
/// Sets internal buffer sizes for Huffman encoding
/// </summary>
public const int DEFAULT_MEM_LEVEL = 8;
/// <summary>
/// Internal compression engine constant
/// </summary>
public const int MAX_MATCH = 258;
/// <summary>
/// Internal compression engine constant
/// </summary>
public const int MIN_MATCH = 3;
/// <summary>
/// Internal compression engine constant
/// </summary>
public const int MAX_WBITS = 15;
/// <summary>
/// Internal compression engine constant
/// </summary>
public const int WSIZE = 1 << MAX_WBITS;
/// <summary>
/// Internal compression engine constant
/// </summary>
public const int WMASK = WSIZE - 1;
/// <summary>
/// Internal compression engine constant
/// </summary>
public const int HASH_BITS = DEFAULT_MEM_LEVEL + 7;
/// <summary>
/// Internal compression engine constant
/// </summary>
public const int HASH_SIZE = 1 << HASH_BITS;
/// <summary>
/// Internal compression engine constant
/// </summary>
public const int HASH_MASK = HASH_SIZE - 1;
/// <summary>
/// Internal compression engine constant
/// </summary>
public const int HASH_SHIFT = (HASH_BITS + MIN_MATCH - 1) / MIN_MATCH;
/// <summary>
/// Internal compression engine constant
/// </summary>
public const int MIN_LOOKAHEAD = MAX_MATCH + MIN_MATCH + 1;
/// <summary>
/// Internal compression engine constant
/// </summary>
public const int MAX_DIST = WSIZE - MIN_LOOKAHEAD;
/// <summary>
/// Internal compression engine constant
/// </summary>
public const int PENDING_BUF_SIZE = 1 << (DEFAULT_MEM_LEVEL + 8);
/// <summary>
/// Internal compression engine constant
/// </summary>
public static int MAX_BLOCK_SIZE = Math.Min(65535, PENDING_BUF_SIZE - 5);
/// <summary>
/// Internal compression engine constant
/// </summary>
public const int DEFLATE_STORED = 0;
/// <summary>
/// Internal compression engine constant
/// </summary>
public const int DEFLATE_FAST = 1;
/// <summary>
/// Internal compression engine constant
/// </summary>
public const int DEFLATE_SLOW = 2;
/// <summary>
/// Internal compression engine constant
/// </summary>
public static int[] GOOD_LENGTH = { 0, 4, 4, 4, 4, 8, 8, 8, 32, 32 };
/// <summary>
/// Internal compression engine constant
/// </summary>
public static int[] MAX_LAZY = { 0, 4, 5, 6, 4, 16, 16, 32, 128, 258 };
/// <summary>
/// Internal compression engine constant
/// </summary>
public static int[] NICE_LENGTH = { 0, 8, 16, 32, 16, 32, 128, 128, 258, 258 };
/// <summary>
/// Internal compression engine constant
/// </summary>
public static int[] MAX_CHAIN = { 0, 4, 8, 32, 16, 32, 128, 256, 1024, 4096 };
/// <summary>
/// Internal compression engine constant
/// </summary>
public static int[] COMPR_FUNC = { 0, 1, 1, 1, 1, 2, 2, 2, 2, 2 };
}
}

View file

@ -1,832 +0,0 @@
// DeflaterEngine.cs
//
// Copyright (C) 2001 Mike Krueger
// Copyright (C) 2004 John Reilly
//
// This file was translated from java, it was part of the GNU Classpath
// Copyright (C) 2001 Free Software Foundation, Inc.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
// Linking this library statically or dynamically with other modules is
// making a combined work based on this library. Thus, the terms and
// conditions of the GNU General Public License cover the whole
// combination.
//
// As a special exception, the copyright holders of this library give you
// permission to link this library with independent modules to produce an
// executable, regardless of the license terms of these independent
// modules, and to copy and distribute the resulting executable under
// terms of your choice, provided that you also meet, for each linked
// independent module, the terms and conditions of the license of that
// module. An independent module is a module which is not derived from
// or based on this library. If you modify this library, you may extend
// this exception to your version of the library, but you are not
// obligated to do so. If you do not wish to do so, delete this
// exception statement from your version.
using System;
namespace Plupload.PngEncoder {
/// <summary>
/// Strategies for deflater
/// </summary>
public enum DeflateStrategy {
/// <summary>
/// The default strategy
/// </summary>
Default = 0,
/// <summary>
/// This strategy will only allow longer string repetitions. It is
/// useful for random data with a small character set.
/// </summary>
Filtered = 1,
/// <summary>
/// This strategy will not look for string repetitions at all. It
/// only encodes with Huffman trees (which means, that more common
/// characters get a smaller encoding.
/// </summary>
HuffmanOnly = 2
}
// DEFLATE ALGORITHM:
//
// The uncompressed stream is inserted into the window array. When
// the window array is full the first half is thrown away and the
// second half is copied to the beginning.
//
// The head array is a hash table. Three characters build a hash value
// and they the value points to the corresponding index in window of
// the last string with this hash. The prev array implements a
// linked list of matches with the same hash: prev[index & WMASK] points
// to the previous index with the same hash.
//
/// <summary>
/// Low level compression engine for deflate algorithm which uses a 32K sliding window
/// with secondary compression from Huffman/Shannon-Fano codes.
/// </summary>
public class DeflaterEngine : DeflaterConstants {
#region Constants
const int TooFar = 4096;
#endregion
#region Constructors
/// <summary>
/// Construct instance with pending buffer
/// </summary>
/// <param name="pending">
/// Pending buffer to use
/// </param>>
public DeflaterEngine(DeflaterPending pending) {
this.pending = pending;
huffman = new DeflaterHuffman(pending);
adler = new Adler32();
window = new byte[2 * WSIZE];
head = new short[HASH_SIZE];
prev = new short[WSIZE];
// We start at index 1, to avoid an implementation deficiency, that
// we cannot build a repeat pattern at index 0.
blockStart = strstart = 1;
}
#endregion
/// <summary>
/// Deflate drives actual compression of data
/// </summary>
/// <param name="flush">True to flush input buffers</param>
/// <param name="finish">Finish deflation with the current input.</param>
/// <returns>Returns true if progress has been made.</returns>
public bool Deflate(bool flush, bool finish) {
bool progress;
do {
FillWindow();
bool canFlush = flush && (inputOff == inputEnd);
#if DebugDeflation
if (DeflaterConstants.DEBUGGING) {
Console.WriteLine("window: [" + blockStart + "," + strstart + ","
+ lookahead + "], " + compressionFunction + "," + canFlush);
}
#endif
switch (compressionFunction) {
case DEFLATE_STORED:
progress = DeflateStored(canFlush, finish);
break;
case DEFLATE_FAST:
progress = DeflateFast(canFlush, finish);
break;
case DEFLATE_SLOW:
progress = DeflateSlow(canFlush, finish);
break;
default:
throw new InvalidOperationException("unknown compressionFunction");
}
} while (pending.IsFlushed && progress); // repeat while we have no pending output and progress was made
return progress;
}
/// <summary>
/// Sets input data to be deflated. Should only be called when <code>NeedsInput()</code>
/// returns true
/// </summary>
/// <param name="buffer">The buffer containing input data.</param>
/// <param name="offset">The offset of the first byte of data.</param>
/// <param name="count">The number of bytes of data to use as input.</param>
public void SetInput(byte[] buffer, int offset, int count) {
if (buffer == null) {
throw new ArgumentNullException("buffer");
}
if (offset < 0) {
throw new ArgumentOutOfRangeException("offset");
}
if (count < 0) {
throw new ArgumentOutOfRangeException("count");
}
if (inputOff < inputEnd) {
throw new InvalidOperationException("Old input was not completely processed");
}
int end = offset + count;
/* We want to throw an ArrayIndexOutOfBoundsException early. The
* check is very tricky: it also handles integer wrap around.
*/
if ((offset > end) || (end > buffer.Length)) {
throw new ArgumentOutOfRangeException("count");
}
inputBuf = buffer;
inputOff = offset;
inputEnd = end;
}
/// <summary>
/// Determines if more <see cref="SetInput">input</see> is needed.
/// </summary>
/// <returns>Return true if input is needed via <see cref="SetInput">SetInput</see></returns>
public bool NeedsInput() {
return (inputEnd == inputOff);
}
/// <summary>
/// Set compression dictionary
/// </summary>
/// <param name="buffer">The buffer containing the dictionary data</param>
/// <param name="offset">The offset in the buffer for the first byte of data</param>
/// <param name="length">The length of the dictionary data.</param>
public void SetDictionary(byte[] buffer, int offset, int length) {
#if DebugDeflation
if (DeflaterConstants.DEBUGGING && (strstart != 1) )
{
throw new InvalidOperationException("strstart not 1");
}
#endif
adler.Update(buffer, offset, length);
if (length < MIN_MATCH) {
return;
}
if (length > MAX_DIST) {
offset += length - MAX_DIST;
length = MAX_DIST;
}
System.Array.Copy(buffer, offset, window, strstart, length);
UpdateHash();
--length;
while (--length > 0) {
InsertString();
strstart++;
}
strstart += 2;
blockStart = strstart;
}
/// <summary>
/// Reset internal state
/// </summary>
public void Reset() {
huffman.Reset();
adler.Reset();
blockStart = strstart = 1;
lookahead = 0;
totalIn = 0;
prevAvailable = false;
matchLen = MIN_MATCH - 1;
for (int i = 0; i < HASH_SIZE; i++) {
head[i] = 0;
}
for (int i = 0; i < WSIZE; i++) {
prev[i] = 0;
}
}
/// <summary>
/// Reset Adler checksum
/// </summary>
public void ResetAdler() {
adler.Reset();
}
/// <summary>
/// Get current value of Adler checksum
/// </summary>
public int Adler {
get {
return unchecked((int) adler.Value);
}
}
/// <summary>
/// Total data processed
/// </summary>
public long TotalIn {
get {
return totalIn;
}
}
/// <summary>
/// Get/set the <see cref="DeflateStrategy">deflate strategy</see>
/// </summary>
public DeflateStrategy Strategy {
get {
return strategy;
}
set {
strategy = value;
}
}
/// <summary>
/// Set the deflate level (0-9)
/// </summary>
/// <param name="level">The value to set the level to.</param>
public void SetLevel(int level) {
if ((level < 0) || (level > 9)) {
throw new ArgumentOutOfRangeException("level");
}
goodLength = DeflaterConstants.GOOD_LENGTH[level];
max_lazy = DeflaterConstants.MAX_LAZY[level];
niceLength = DeflaterConstants.NICE_LENGTH[level];
max_chain = DeflaterConstants.MAX_CHAIN[level];
if (DeflaterConstants.COMPR_FUNC[level] != compressionFunction) {
#if DebugDeflation
if (DeflaterConstants.DEBUGGING) {
Console.WriteLine("Change from " + compressionFunction + " to "
+ DeflaterConstants.COMPR_FUNC[level]);
}
#endif
switch (compressionFunction) {
case DEFLATE_STORED:
if (strstart > blockStart) {
huffman.FlushStoredBlock(window, blockStart,
strstart - blockStart, false);
blockStart = strstart;
}
UpdateHash();
break;
case DEFLATE_FAST:
if (strstart > blockStart) {
huffman.FlushBlock(window, blockStart, strstart - blockStart,
false);
blockStart = strstart;
}
break;
case DEFLATE_SLOW:
if (prevAvailable) {
huffman.TallyLit(window[strstart - 1] & 0xff);
}
if (strstart > blockStart) {
huffman.FlushBlock(window, blockStart, strstart - blockStart, false);
blockStart = strstart;
}
prevAvailable = false;
matchLen = MIN_MATCH - 1;
break;
}
compressionFunction = COMPR_FUNC[level];
}
}
/// <summary>
/// Fill the window
/// </summary>
public void FillWindow() {
/* If the window is almost full and there is insufficient lookahead,
* move the upper half to the lower one to make room in the upper half.
*/
if (strstart >= WSIZE + MAX_DIST) {
SlideWindow();
}
/* If there is not enough lookahead, but still some input left,
* read in the input
*/
while (lookahead < DeflaterConstants.MIN_LOOKAHEAD && inputOff < inputEnd) {
int more = 2 * WSIZE - lookahead - strstart;
if (more > inputEnd - inputOff) {
more = inputEnd - inputOff;
}
System.Array.Copy(inputBuf, inputOff, window, strstart + lookahead, more);
adler.Update(inputBuf, inputOff, more);
inputOff += more;
totalIn += more;
lookahead += more;
}
if (lookahead >= MIN_MATCH) {
UpdateHash();
}
}
void UpdateHash() {
/*
if (DEBUGGING) {
Console.WriteLine("updateHash: "+strstart);
}
*/
ins_h = (window[strstart] << HASH_SHIFT) ^ window[strstart + 1];
}
/// <summary>
/// Inserts the current string in the head hash and returns the previous
/// value for this hash.
/// </summary>
/// <returns>The previous hash value</returns>
int InsertString() {
short match;
int hash = ((ins_h << HASH_SHIFT) ^ window[strstart + (MIN_MATCH - 1)]) & HASH_MASK;
#if DebugDeflation
if (DeflaterConstants.DEBUGGING)
{
if (hash != (((window[strstart] << (2*HASH_SHIFT)) ^
(window[strstart + 1] << HASH_SHIFT) ^
(window[strstart + 2])) & HASH_MASK)) {
throw new SharpZipBaseException("hash inconsistent: " + hash + "/"
+window[strstart] + ","
+window[strstart + 1] + ","
+window[strstart + 2] + "," + HASH_SHIFT);
}
}
#endif
prev[strstart & WMASK] = match = head[hash];
head[hash] = unchecked((short) strstart);
ins_h = hash;
return match & 0xffff;
}
void SlideWindow() {
Array.Copy(window, WSIZE, window, 0, WSIZE);
matchStart -= WSIZE;
strstart -= WSIZE;
blockStart -= WSIZE;
// Slide the hash table (could be avoided with 32 bit values
// at the expense of memory usage).
for (int i = 0; i < HASH_SIZE; ++i) {
int m = head[i] & 0xffff;
head[i] = (short) (m >= WSIZE ? (m - WSIZE) : 0);
}
// Slide the prev table.
for (int i = 0; i < WSIZE; i++) {
int m = prev[i] & 0xffff;
prev[i] = (short) (m >= WSIZE ? (m - WSIZE) : 0);
}
}
/// <summary>
/// Find the best (longest) string in the window matching the
/// string starting at strstart.
///
/// Preconditions:
/// <code>
/// strstart + MAX_MATCH &lt;= window.length.</code>
/// </summary>
/// <param name="curMatch"></param>
/// <returns>True if a match greater than the minimum length is found</returns>
bool FindLongestMatch(int curMatch) {
int chainLength = this.max_chain;
int niceLength = this.niceLength;
short[] prev = this.prev;
int scan = this.strstart;
int match;
int best_end = this.strstart + matchLen;
int best_len = Math.Max(matchLen, MIN_MATCH - 1);
int limit = Math.Max(strstart - MAX_DIST, 0);
int strend = strstart + MAX_MATCH - 1;
byte scan_end1 = window[best_end - 1];
byte scan_end = window[best_end];
// Do not waste too much time if we already have a good match:
if (best_len >= this.goodLength) {
chainLength >>= 2;
}
/* Do not look for matches beyond the end of the input. This is necessary
* to make deflate deterministic.
*/
if (niceLength > lookahead) {
niceLength = lookahead;
}
#if DebugDeflation
if (DeflaterConstants.DEBUGGING && (strstart > 2 * WSIZE - MIN_LOOKAHEAD))
{
throw new InvalidOperationException("need lookahead");
}
#endif
do {
#if DebugDeflation
if (DeflaterConstants.DEBUGGING && (curMatch >= strstart) )
{
throw new InvalidOperationException("no future");
}
#endif
if (window[curMatch + best_len] != scan_end ||
window[curMatch + best_len - 1] != scan_end1 ||
window[curMatch] != window[scan] ||
window[curMatch + 1] != window[scan + 1]) {
continue;
}
match = curMatch + 2;
scan += 2;
/* We check for insufficient lookahead only every 8th comparison;
* the 256th check will be made at strstart + 258.
*/
while (
window[++scan] == window[++match] &&
window[++scan] == window[++match] &&
window[++scan] == window[++match] &&
window[++scan] == window[++match] &&
window[++scan] == window[++match] &&
window[++scan] == window[++match] &&
window[++scan] == window[++match] &&
window[++scan] == window[++match] &&
(scan < strend)) {
// Do nothing
}
if (scan > best_end) {
#if DebugDeflation
if (DeflaterConstants.DEBUGGING && (ins_h == 0) )
Console.Error.WriteLine("Found match: " + curMatch + "-" + (scan - strstart));
#endif
matchStart = curMatch;
best_end = scan;
best_len = scan - strstart;
if (best_len >= niceLength) {
break;
}
scan_end1 = window[best_end - 1];
scan_end = window[best_end];
}
scan = strstart;
} while ((curMatch = (prev[curMatch & WMASK] & 0xffff)) > limit && --chainLength != 0);
matchLen = Math.Min(best_len, lookahead);
return matchLen >= MIN_MATCH;
}
bool DeflateStored(bool flush, bool finish) {
if (!flush && (lookahead == 0)) {
return false;
}
strstart += lookahead;
lookahead = 0;
int storedLength = strstart - blockStart;
if ((storedLength >= DeflaterConstants.MAX_BLOCK_SIZE) || // Block is full
(blockStart < WSIZE && storedLength >= MAX_DIST) || // Block may move out of window
flush) {
bool lastBlock = finish;
if (storedLength > DeflaterConstants.MAX_BLOCK_SIZE) {
storedLength = DeflaterConstants.MAX_BLOCK_SIZE;
lastBlock = false;
}
#if DebugDeflation
if (DeflaterConstants.DEBUGGING)
{
Console.WriteLine("storedBlock[" + storedLength + "," + lastBlock + "]");
}
#endif
huffman.FlushStoredBlock(window, blockStart, storedLength, lastBlock);
blockStart += storedLength;
return !lastBlock;
}
return true;
}
bool DeflateFast(bool flush, bool finish) {
if (lookahead < MIN_LOOKAHEAD && !flush) {
return false;
}
while (lookahead >= MIN_LOOKAHEAD || flush) {
if (lookahead == 0) {
// We are flushing everything
huffman.FlushBlock(window, blockStart, strstart - blockStart, finish);
blockStart = strstart;
return false;
}
if (strstart > 2 * WSIZE - MIN_LOOKAHEAD) {
/* slide window, as FindLongestMatch needs this.
* This should only happen when flushing and the window
* is almost full.
*/
SlideWindow();
}
int hashHead;
if (lookahead >= MIN_MATCH &&
(hashHead = InsertString()) != 0 &&
strategy != DeflateStrategy.HuffmanOnly &&
strstart - hashHead <= MAX_DIST &&
FindLongestMatch(hashHead)) {
// longestMatch sets matchStart and matchLen
#if DebugDeflation
if (DeflaterConstants.DEBUGGING)
{
for (int i = 0 ; i < matchLen; i++) {
if (window[strstart + i] != window[matchStart + i]) {
throw new SharpZipBaseException("Match failure");
}
}
}
#endif
bool full = huffman.TallyDist(strstart - matchStart, matchLen);
lookahead -= matchLen;
if (matchLen <= max_lazy && lookahead >= MIN_MATCH) {
while (--matchLen > 0) {
++strstart;
InsertString();
}
++strstart;
} else {
strstart += matchLen;
if (lookahead >= MIN_MATCH - 1) {
UpdateHash();
}
}
matchLen = MIN_MATCH - 1;
if (!full) {
continue;
}
} else {
// No match found
huffman.TallyLit(window[strstart] & 0xff);
++strstart;
--lookahead;
}
if (huffman.IsFull()) {
bool lastBlock = finish && (lookahead == 0);
huffman.FlushBlock(window, blockStart, strstart - blockStart, lastBlock);
blockStart = strstart;
return !lastBlock;
}
}
return true;
}
bool DeflateSlow(bool flush, bool finish) {
if (lookahead < MIN_LOOKAHEAD && !flush) {
return false;
}
while (lookahead >= MIN_LOOKAHEAD || flush) {
if (lookahead == 0) {
if (prevAvailable) {
huffman.TallyLit(window[strstart - 1] & 0xff);
}
prevAvailable = false;
// We are flushing everything
#if DebugDeflation
if (DeflaterConstants.DEBUGGING && !flush)
{
throw new SharpZipBaseException("Not flushing, but no lookahead");
}
#endif
huffman.FlushBlock(window, blockStart, strstart - blockStart,
finish);
blockStart = strstart;
return false;
}
if (strstart >= 2 * WSIZE - MIN_LOOKAHEAD) {
/* slide window, as FindLongestMatch needs this.
* This should only happen when flushing and the window
* is almost full.
*/
SlideWindow();
}
int prevMatch = matchStart;
int prevLen = matchLen;
if (lookahead >= MIN_MATCH) {
int hashHead = InsertString();
if (strategy != DeflateStrategy.HuffmanOnly &&
hashHead != 0 &&
strstart - hashHead <= MAX_DIST &&
FindLongestMatch(hashHead)) {
// longestMatch sets matchStart and matchLen
// Discard match if too small and too far away
if (matchLen <= 5 && (strategy == DeflateStrategy.Filtered || (matchLen == MIN_MATCH && strstart - matchStart > TooFar))) {
matchLen = MIN_MATCH - 1;
}
}
}
// previous match was better
if ((prevLen >= MIN_MATCH) && (matchLen <= prevLen)) {
#if DebugDeflation
if (DeflaterConstants.DEBUGGING)
{
for (int i = 0 ; i < matchLen; i++) {
if (window[strstart-1+i] != window[prevMatch + i])
throw new SharpZipBaseException();
}
}
#endif
huffman.TallyDist(strstart - 1 - prevMatch, prevLen);
prevLen -= 2;
do {
strstart++;
lookahead--;
if (lookahead >= MIN_MATCH) {
InsertString();
}
} while (--prevLen > 0);
strstart++;
lookahead--;
prevAvailable = false;
matchLen = MIN_MATCH - 1;
} else {
if (prevAvailable) {
huffman.TallyLit(window[strstart - 1] & 0xff);
}
prevAvailable = true;
strstart++;
lookahead--;
}
if (huffman.IsFull()) {
int len = strstart - blockStart;
if (prevAvailable) {
len--;
}
bool lastBlock = (finish && (lookahead == 0) && !prevAvailable);
huffman.FlushBlock(window, blockStart, len, lastBlock);
blockStart += len;
return !lastBlock;
}
}
return true;
}
#region Instance Fields
// Hash index of string to be inserted
int ins_h;
/// <summary>
/// Hashtable, hashing three characters to an index for window, so
/// that window[index]..window[index+2] have this hash code.
/// Note that the array should really be unsigned short, so you need
/// to and the values with 0xffff.
/// </summary>
short[] head;
/// <summary>
/// <code>prev[index &amp; WMASK]</code> points to the previous index that has the
/// same hash code as the string starting at index. This way
/// entries with the same hash code are in a linked list.
/// Note that the array should really be unsigned short, so you need
/// to and the values with 0xffff.
/// </summary>
short[] prev;
int matchStart;
// Length of best match
int matchLen;
// Set if previous match exists
bool prevAvailable;
int blockStart;
/// <summary>
/// Points to the current character in the window.
/// </summary>
int strstart;
/// <summary>
/// lookahead is the number of characters starting at strstart in
/// window that are valid.
/// So window[strstart] until window[strstart+lookahead-1] are valid
/// characters.
/// </summary>
int lookahead;
/// <summary>
/// This array contains the part of the uncompressed stream that
/// is of relevance. The current character is indexed by strstart.
/// </summary>
byte[] window;
DeflateStrategy strategy;
int max_chain, max_lazy, niceLength, goodLength;
/// <summary>
/// The current compression function.
/// </summary>
int compressionFunction;
/// <summary>
/// The input data for compression.
/// </summary>
byte[] inputBuf;
/// <summary>
/// The total bytes of input read.
/// </summary>
long totalIn;
/// <summary>
/// The offset into inputBuf, where input data starts.
/// </summary>
int inputOff;
/// <summary>
/// The end offset of the input data.
/// </summary>
int inputEnd;
DeflaterPending pending;
DeflaterHuffman huffman;
/// <summary>
/// The adler checksum
/// </summary>
Adler32 adler;
#endregion
}
}

View file

@ -1,881 +0,0 @@
// DeflaterHuffman.cs
//
// Copyright (C) 2001 Mike Krueger
// Copyright (C) 2004 John Reilly
//
// This file was translated from java, it was part of the GNU Classpath
// Copyright (C) 2001 Free Software Foundation, Inc.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
// Linking this library statically or dynamically with other modules is
// making a combined work based on this library. Thus, the terms and
// conditions of the GNU General Public License cover the whole
// combination.
//
// As a special exception, the copyright holders of this library give you
// permission to link this library with independent modules to produce an
// executable, regardless of the license terms of these independent
// modules, and to copy and distribute the resulting executable under
// terms of your choice, provided that you also meet, for each linked
// independent module, the terms and conditions of the license of that
// module. An independent module is a module which is not derived from
// or based on this library. If you modify this library, you may extend
// this exception to your version of the library, but you are not
// obligated to do so. If you do not wish to do so, delete this
// exception statement from your version.
using System;
namespace Plupload.PngEncoder {
/// <summary>
/// This is the DeflaterHuffman class.
///
/// This class is <i>not</i> thread safe. This is inherent in the API, due
/// to the split of Deflate and SetInput.
///
/// author of the original java version : Jochen Hoenicke
/// </summary>
public class DeflaterHuffman {
const int BUFSIZE = 1 << (DeflaterConstants.DEFAULT_MEM_LEVEL + 6);
const int LITERAL_NUM = 286;
// Number of distance codes
const int DIST_NUM = 30;
// Number of codes used to transfer bit lengths
const int BITLEN_NUM = 19;
// repeat previous bit length 3-6 times (2 bits of repeat count)
const int REP_3_6 = 16;
// repeat a zero length 3-10 times (3 bits of repeat count)
const int REP_3_10 = 17;
// repeat a zero length 11-138 times (7 bits of repeat count)
const int REP_11_138 = 18;
const int EOF_SYMBOL = 256;
// The lengths of the bit length codes are sent in order of decreasing
// probability, to avoid transmitting the lengths for unused bit length codes.
static readonly int[] BL_ORDER = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
static readonly byte[] bit4Reverse = {
0,
8,
4,
12,
2,
10,
6,
14,
1,
9,
5,
13,
3,
11,
7,
15
};
static short[] staticLCodes;
static byte[] staticLLength;
static short[] staticDCodes;
static byte[] staticDLength;
class Tree {
#region Instance Fields
public short[] freqs;
public byte[] length;
public int minNumCodes;
public int numCodes;
short[] codes;
int[] bl_counts;
int maxLength;
DeflaterHuffman dh;
#endregion
#region Constructors
public Tree(DeflaterHuffman dh, int elems, int minCodes, int maxLength) {
this.dh = dh;
this.minNumCodes = minCodes;
this.maxLength = maxLength;
freqs = new short[elems];
bl_counts = new int[maxLength];
}
#endregion
/// <summary>
/// Resets the internal state of the tree
/// </summary>
public void Reset() {
for (int i = 0; i < freqs.Length; i++) {
freqs[i] = 0;
}
codes = null;
length = null;
}
public void WriteSymbol(int code) {
// if (DeflaterConstants.DEBUGGING) {
// freqs[code]--;
// // Console.Write("writeSymbol("+freqs.length+","+code+"): ");
// }
dh.pending.WriteBits(codes[code] & 0xffff, length[code]);
}
/// <summary>
/// Check that all frequencies are zero
/// </summary>
/// <exception cref="SharpZipBaseException">
/// At least one frequency is non-zero
/// </exception>
public void CheckEmpty() {
bool empty = true;
for (int i = 0; i < freqs.Length; i++) {
if (freqs[i] != 0) {
//Console.WriteLine("freqs[" + i + "] == " + freqs[i]);
empty = false;
}
}
if (!empty) {
throw new Exception("!Empty");
}
}
/// <summary>
/// Set static codes and length
/// </summary>
/// <param name="staticCodes">new codes</param>
/// <param name="staticLengths">length for new codes</param>
public void SetStaticCodes(short[] staticCodes, byte[] staticLengths) {
codes = staticCodes;
length = staticLengths;
}
/// <summary>
/// Build dynamic codes and lengths
/// </summary>
public void BuildCodes() {
int numSymbols = freqs.Length;
int[] nextCode = new int[maxLength];
int code = 0;
codes = new short[freqs.Length];
// if (DeflaterConstants.DEBUGGING) {
// //Console.WriteLine("buildCodes: "+freqs.Length);
// }
for (int bits = 0; bits < maxLength; bits++) {
nextCode[bits] = code;
code += bl_counts[bits] << (15 - bits);
// if (DeflaterConstants.DEBUGGING) {
// //Console.WriteLine("bits: " + ( bits + 1) + " count: " + bl_counts[bits]
// +" nextCode: "+code);
// }
}
#if DebugDeflation
if ( DeflaterConstants.DEBUGGING && (code != 65536) )
{
throw new SharpZipBaseException("Inconsistent bl_counts!");
}
#endif
for (int i = 0; i < numCodes; i++) {
int bits = length[i];
if (bits > 0) {
// if (DeflaterConstants.DEBUGGING) {
// //Console.WriteLine("codes["+i+"] = rev(" + nextCode[bits-1]+"),
// +bits);
// }
codes[i] = BitReverse(nextCode[bits - 1]);
nextCode[bits - 1] += 1 << (16 - bits);
}
}
}
public void BuildTree() {
int numSymbols = freqs.Length;
/* heap is a priority queue, sorted by frequency, least frequent
* nodes first. The heap is a binary tree, with the property, that
* the parent node is smaller than both child nodes. This assures
* that the smallest node is the first parent.
*
* The binary tree is encoded in an array: 0 is root node and
* the nodes 2*n+1, 2*n+2 are the child nodes of node n.
*/
int[] heap = new int[numSymbols];
int heapLen = 0;
int maxCode = 0;
for (int n = 0; n < numSymbols; n++) {
int freq = freqs[n];
if (freq != 0) {
// Insert n into heap
int pos = heapLen++;
int ppos;
while (pos > 0 && freqs[heap[ppos = (pos - 1) / 2]] > freq) {
heap[pos] = heap[ppos];
pos = ppos;
}
heap[pos] = n;
maxCode = n;
}
}
/* We could encode a single literal with 0 bits but then we
* don't see the literals. Therefore we force at least two
* literals to avoid this case. We don't care about order in
* this case, both literals get a 1 bit code.
*/
while (heapLen < 2) {
int node = maxCode < 2 ? ++maxCode : 0;
heap[heapLen++] = node;
}
numCodes = Math.Max(maxCode + 1, minNumCodes);
int numLeafs = heapLen;
int[] childs = new int[4 * heapLen - 2];
int[] values = new int[2 * heapLen - 1];
int numNodes = numLeafs;
for (int i = 0; i < heapLen; i++) {
int node = heap[i];
childs[2 * i] = node;
childs[2 * i + 1] = -1;
values[i] = freqs[node] << 8;
heap[i] = i;
}
/* Construct the Huffman tree by repeatedly combining the least two
* frequent nodes.
*/
do {
int first = heap[0];
int last = heap[--heapLen];
// Propagate the hole to the leafs of the heap
int ppos = 0;
int path = 1;
while (path < heapLen) {
if (path + 1 < heapLen && values[heap[path]] > values[heap[path + 1]]) {
path++;
}
heap[ppos] = heap[path];
ppos = path;
path = path * 2 + 1;
}
/* Now propagate the last element down along path. Normally
* it shouldn't go too deep.
*/
int lastVal = values[last];
while ((path = ppos) > 0 && values[heap[ppos = (path - 1) / 2]] > lastVal) {
heap[path] = heap[ppos];
}
heap[path] = last;
int second = heap[0];
// Create a new node father of first and second
last = numNodes++;
childs[2 * last] = first;
childs[2 * last + 1] = second;
int mindepth = Math.Min(values[first] & 0xff, values[second] & 0xff);
values[last] = lastVal = values[first] + values[second] - mindepth + 1;
// Again, propagate the hole to the leafs
ppos = 0;
path = 1;
while (path < heapLen) {
if (path + 1 < heapLen && values[heap[path]] > values[heap[path + 1]]) {
path++;
}
heap[ppos] = heap[path];
ppos = path;
path = ppos * 2 + 1;
}
// Now propagate the new element down along path
while ((path = ppos) > 0 && values[heap[ppos = (path - 1) / 2]] > lastVal) {
heap[path] = heap[ppos];
}
heap[path] = last;
} while (heapLen > 1);
if (heap[0] != childs.Length / 2 - 1) {
throw new Exception("Heap invariant violated");
}
BuildLength(childs);
}
/// <summary>
/// Get encoded length
/// </summary>
/// <returns>Encoded length, the sum of frequencies * lengths</returns>
public int GetEncodedLength() {
int len = 0;
for (int i = 0; i < freqs.Length; i++) {
len += freqs[i] * length[i];
}
return len;
}
/// <summary>
/// Scan a literal or distance tree to determine the frequencies of the codes
/// in the bit length tree.
/// </summary>
public void CalcBLFreq(Tree blTree) {
int max_count; /* max repeat count */
int min_count; /* min repeat count */
int count; /* repeat count of the current code */
int curlen = -1; /* length of current code */
int i = 0;
while (i < numCodes) {
count = 1;
int nextlen = length[i];
if (nextlen == 0) {
max_count = 138;
min_count = 3;
} else {
max_count = 6;
min_count = 3;
if (curlen != nextlen) {
blTree.freqs[nextlen]++;
count = 0;
}
}
curlen = nextlen;
i++;
while (i < numCodes && curlen == length[i]) {
i++;
if (++count >= max_count) {
break;
}
}
if (count < min_count) {
blTree.freqs[curlen] += (short) count;
} else if (curlen != 0) {
blTree.freqs[REP_3_6]++;
} else if (count <= 10) {
blTree.freqs[REP_3_10]++;
} else {
blTree.freqs[REP_11_138]++;
}
}
}
/// <summary>
/// Write tree values
/// </summary>
/// <param name="blTree">Tree to write</param>
public void WriteTree(Tree blTree) {
int max_count; // max repeat count
int min_count; // min repeat count
int count; // repeat count of the current code
int curlen = -1; // length of current code
int i = 0;
while (i < numCodes) {
count = 1;
int nextlen = length[i];
if (nextlen == 0) {
max_count = 138;
min_count = 3;
} else {
max_count = 6;
min_count = 3;
if (curlen != nextlen) {
blTree.WriteSymbol(nextlen);
count = 0;
}
}
curlen = nextlen;
i++;
while (i < numCodes && curlen == length[i]) {
i++;
if (++count >= max_count) {
break;
}
}
if (count < min_count) {
while (count-- > 0) {
blTree.WriteSymbol(curlen);
}
} else if (curlen != 0) {
blTree.WriteSymbol(REP_3_6);
dh.pending.WriteBits(count - 3, 2);
} else if (count <= 10) {
blTree.WriteSymbol(REP_3_10);
dh.pending.WriteBits(count - 3, 3);
} else {
blTree.WriteSymbol(REP_11_138);
dh.pending.WriteBits(count - 11, 7);
}
}
}
void BuildLength(int[] childs) {
this.length = new byte[freqs.Length];
int numNodes = childs.Length / 2;
int numLeafs = (numNodes + 1) / 2;
int overflow = 0;
for (int i = 0; i < maxLength; i++) {
bl_counts[i] = 0;
}
// First calculate optimal bit lengths
int[] lengths = new int[numNodes];
lengths[numNodes - 1] = 0;
for (int i = numNodes - 1; i >= 0; i--) {
if (childs[2 * i + 1] != -1) {
int bitLength = lengths[i] + 1;
if (bitLength > maxLength) {
bitLength = maxLength;
overflow++;
}
lengths[childs[2 * i]] = lengths[childs[2 * i + 1]] = bitLength;
} else {
// A leaf node
int bitLength = lengths[i];
bl_counts[bitLength - 1]++;
this.length[childs[2 * i]] = (byte) lengths[i];
}
}
// if (DeflaterConstants.DEBUGGING) {
// //Console.WriteLine("Tree "+freqs.Length+" lengths:");
// for (int i=0; i < numLeafs; i++) {
// //Console.WriteLine("Node "+childs[2*i]+" freq: "+freqs[childs[2*i]]
// + " len: "+length[childs[2*i]]);
// }
// }
if (overflow == 0) {
return;
}
int incrBitLen = maxLength - 1;
do {
// Find the first bit length which could increase:
while (bl_counts[--incrBitLen] == 0)
;
// Move this node one down and remove a corresponding
// number of overflow nodes.
do {
bl_counts[incrBitLen]--;
bl_counts[++incrBitLen]++;
overflow -= 1 << (maxLength - 1 - incrBitLen);
} while (overflow > 0 && incrBitLen < maxLength - 1);
} while (overflow > 0);
/* We may have overshot above. Move some nodes from maxLength to
* maxLength-1 in that case.
*/
bl_counts[maxLength - 1] += overflow;
bl_counts[maxLength - 2] -= overflow;
/* Now recompute all bit lengths, scanning in increasing
* frequency. It is simpler to reconstruct all lengths instead of
* fixing only the wrong ones. This idea is taken from 'ar'
* written by Haruhiko Okumura.
*
* The nodes were inserted with decreasing frequency into the childs
* array.
*/
int nodePtr = 2 * numLeafs;
for (int bits = maxLength; bits != 0; bits--) {
int n = bl_counts[bits - 1];
while (n > 0) {
int childPtr = 2 * childs[nodePtr++];
if (childs[childPtr + 1] == -1) {
// We found another leaf
length[childs[childPtr]] = (byte) bits;
n--;
}
}
}
// if (DeflaterConstants.DEBUGGING) {
// //Console.WriteLine("*** After overflow elimination. ***");
// for (int i=0; i < numLeafs; i++) {
// //Console.WriteLine("Node "+childs[2*i]+" freq: "+freqs[childs[2*i]]
// + " len: "+length[childs[2*i]]);
// }
// }
}
}
#region Instance Fields
/// <summary>
/// Pending buffer to use
/// </summary>
public DeflaterPending pending;
Tree literalTree;
Tree distTree;
Tree blTree;
// Buffer for distances
short[] d_buf;
byte[] l_buf;
int last_lit;
int extra_bits;
#endregion
static DeflaterHuffman() {
// See RFC 1951 3.2.6
// Literal codes
staticLCodes = new short[LITERAL_NUM];
staticLLength = new byte[LITERAL_NUM];
int i = 0;
while (i < 144) {
staticLCodes[i] = BitReverse((0x030 + i) << 8);
staticLLength[i++] = 8;
}
while (i < 256) {
staticLCodes[i] = BitReverse((0x190 - 144 + i) << 7);
staticLLength[i++] = 9;
}
while (i < 280) {
staticLCodes[i] = BitReverse((0x000 - 256 + i) << 9);
staticLLength[i++] = 7;
}
while (i < LITERAL_NUM) {
staticLCodes[i] = BitReverse((0x0c0 - 280 + i) << 8);
staticLLength[i++] = 8;
}
// Distance codes
staticDCodes = new short[DIST_NUM];
staticDLength = new byte[DIST_NUM];
for (i = 0; i < DIST_NUM; i++) {
staticDCodes[i] = BitReverse(i << 11);
staticDLength[i] = 5;
}
}
/// <summary>
/// Construct instance with pending buffer
/// </summary>
/// <param name="pending">Pending buffer to use</param>
public DeflaterHuffman(DeflaterPending pending) {
this.pending = pending;
literalTree = new Tree(this, LITERAL_NUM, 257, 15);
distTree = new Tree(this, DIST_NUM, 1, 15);
blTree = new Tree(this, BITLEN_NUM, 4, 7);
d_buf = new short[BUFSIZE];
l_buf = new byte[BUFSIZE];
}
/// <summary>
/// Reset internal state
/// </summary>
public void Reset() {
last_lit = 0;
extra_bits = 0;
literalTree.Reset();
distTree.Reset();
blTree.Reset();
}
/// <summary>
/// Write all trees to pending buffer
/// </summary>
/// <param name="blTreeCodes">The number/rank of treecodes to send.</param>
public void SendAllTrees(int blTreeCodes) {
blTree.BuildCodes();
literalTree.BuildCodes();
distTree.BuildCodes();
pending.WriteBits(literalTree.numCodes - 257, 5);
pending.WriteBits(distTree.numCodes - 1, 5);
pending.WriteBits(blTreeCodes - 4, 4);
for (int rank = 0; rank < blTreeCodes; rank++) {
pending.WriteBits(blTree.length[BL_ORDER[rank]], 3);
}
literalTree.WriteTree(blTree);
distTree.WriteTree(blTree);
#if DebugDeflation
if (DeflaterConstants.DEBUGGING) {
blTree.CheckEmpty();
}
#endif
}
/// <summary>
/// Compress current buffer writing data to pending buffer
/// </summary>
public void CompressBlock() {
for (int i = 0; i < last_lit; i++) {
int litlen = l_buf[i] & 0xff;
int dist = d_buf[i];
if (dist-- != 0) {
// if (DeflaterConstants.DEBUGGING) {
// Console.Write("["+(dist+1)+","+(litlen+3)+"]: ");
// }
int lc = Lcode(litlen);
literalTree.WriteSymbol(lc);
int bits = (lc - 261) / 4;
if (bits > 0 && bits <= 5) {
pending.WriteBits(litlen & ((1 << bits) - 1), bits);
}
int dc = Dcode(dist);
distTree.WriteSymbol(dc);
bits = dc / 2 - 1;
if (bits > 0) {
pending.WriteBits(dist & ((1 << bits) - 1), bits);
}
} else {
// if (DeflaterConstants.DEBUGGING) {
// if (litlen > 32 && litlen < 127) {
// Console.Write("("+(char)litlen+"): ");
// } else {
// Console.Write("{"+litlen+"}: ");
// }
// }
literalTree.WriteSymbol(litlen);
}
}
#if DebugDeflation
if (DeflaterConstants.DEBUGGING) {
Console.Write("EOF: ");
}
#endif
literalTree.WriteSymbol(EOF_SYMBOL);
#if DebugDeflation
if (DeflaterConstants.DEBUGGING) {
literalTree.CheckEmpty();
distTree.CheckEmpty();
}
#endif
}
/// <summary>
/// Flush block to output with no compression
/// </summary>
/// <param name="stored">Data to write</param>
/// <param name="storedOffset">Index of first byte to write</param>
/// <param name="storedLength">Count of bytes to write</param>
/// <param name="lastBlock">True if this is the last block</param>
public void FlushStoredBlock(byte[] stored, int storedOffset, int storedLength, bool lastBlock) {
#if DebugDeflation
// if (DeflaterConstants.DEBUGGING) {
// //Console.WriteLine("Flushing stored block "+ storedLength);
// }
#endif
pending.WriteBits((DeflaterConstants.STORED_BLOCK << 1) + (lastBlock ? 1 : 0), 3);
pending.AlignToByte();
pending.WriteShort(storedLength);
pending.WriteShort(~storedLength);
pending.WriteBlock(stored, storedOffset, storedLength);
Reset();
}
/// <summary>
/// Flush block to output with compression
/// </summary>
/// <param name="stored">Data to flush</param>
/// <param name="storedOffset">Index of first byte to flush</param>
/// <param name="storedLength">Count of bytes to flush</param>
/// <param name="lastBlock">True if this is the last block</param>
public void FlushBlock(byte[] stored, int storedOffset, int storedLength, bool lastBlock) {
literalTree.freqs[EOF_SYMBOL]++;
// Build trees
literalTree.BuildTree();
distTree.BuildTree();
// Calculate bitlen frequency
literalTree.CalcBLFreq(blTree);
distTree.CalcBLFreq(blTree);
// Build bitlen tree
blTree.BuildTree();
int blTreeCodes = 4;
for (int i = 18; i > blTreeCodes; i--) {
if (blTree.length[BL_ORDER[i]] > 0) {
blTreeCodes = i + 1;
}
}
int opt_len = 14 + blTreeCodes * 3 + blTree.GetEncodedLength() +
literalTree.GetEncodedLength() + distTree.GetEncodedLength() +
extra_bits;
int static_len = extra_bits;
for (int i = 0; i < LITERAL_NUM; i++) {
static_len += literalTree.freqs[i] * staticLLength[i];
}
for (int i = 0; i < DIST_NUM; i++) {
static_len += distTree.freqs[i] * staticDLength[i];
}
if (opt_len >= static_len) {
// Force static trees
opt_len = static_len;
}
if (storedOffset >= 0 && storedLength + 4 < opt_len >> 3) {
// Store Block
// if (DeflaterConstants.DEBUGGING) {
// //Console.WriteLine("Storing, since " + storedLength + " < " + opt_len
// + " <= " + static_len);
// }
FlushStoredBlock(stored, storedOffset, storedLength, lastBlock);
} else if (opt_len == static_len) {
// Encode with static tree
pending.WriteBits((DeflaterConstants.STATIC_TREES << 1) + (lastBlock ? 1 : 0), 3);
literalTree.SetStaticCodes(staticLCodes, staticLLength);
distTree.SetStaticCodes(staticDCodes, staticDLength);
CompressBlock();
Reset();
} else {
// Encode with dynamic tree
pending.WriteBits((DeflaterConstants.DYN_TREES << 1) + (lastBlock ? 1 : 0), 3);
SendAllTrees(blTreeCodes);
CompressBlock();
Reset();
}
}
/// <summary>
/// Get value indicating if internal buffer is full
/// </summary>
/// <returns>true if buffer is full</returns>
public bool IsFull() {
return last_lit >= BUFSIZE;
}
/// <summary>
/// Add literal to buffer
/// </summary>
/// <param name="literal">Literal value to add to buffer.</param>
/// <returns>Value indicating internal buffer is full</returns>
public bool TallyLit(int literal) {
// if (DeflaterConstants.DEBUGGING) {
// if (lit > 32 && lit < 127) {
// //Console.WriteLine("("+(char)lit+")");
// } else {
// //Console.WriteLine("{"+lit+"}");
// }
// }
d_buf[last_lit] = 0;
l_buf[last_lit++] = (byte) literal;
literalTree.freqs[literal]++;
return IsFull();
}
/// <summary>
/// Add distance code and length to literal and distance trees
/// </summary>
/// <param name="distance">Distance code</param>
/// <param name="length">Length</param>
/// <returns>Value indicating if internal buffer is full</returns>
public bool TallyDist(int distance, int length) {
// if (DeflaterConstants.DEBUGGING) {
// //Console.WriteLine("[" + distance + "," + length + "]");
// }
d_buf[last_lit] = (short) distance;
l_buf[last_lit++] = (byte) (length - 3);
int lc = Lcode(length - 3);
literalTree.freqs[lc]++;
if (lc >= 265 && lc < 285) {
extra_bits += (lc - 261) / 4;
}
int dc = Dcode(distance - 1);
distTree.freqs[dc]++;
if (dc >= 4) {
extra_bits += dc / 2 - 1;
}
return IsFull();
}
/// <summary>
/// Reverse the bits of a 16 bit value.
/// </summary>
/// <param name="toReverse">Value to reverse bits</param>
/// <returns>Value with bits reversed</returns>
public static short BitReverse(int toReverse) {
return (short) (bit4Reverse[toReverse & 0xF] << 12 |
bit4Reverse[(toReverse >> 4) & 0xF] << 8 |
bit4Reverse[(toReverse >> 8) & 0xF] << 4 |
bit4Reverse[toReverse >> 12]);
}
static int Lcode(int length) {
if (length == 255) {
return 285;
}
int code = 257;
while (length >= 8) {
code += 4;
length >>= 1;
}
return code + length;
}
static int Dcode(int distance) {
int code = 0;
while (distance >= 4) {
code += 2;
distance >>= 1;
}
return code + distance;
}
}
}

View file

@ -1,469 +0,0 @@
// DeflaterOutputStream.cs
//
// Copyright (C) 2001 Mike Krueger
//
// This file was translated from java, it was part of the GNU Classpath
// Copyright (C) 2001 Free Software Foundation, Inc.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
// Linking this library statically or dynamically with other modules is
// making a combined work based on this library. Thus, the terms and
// conditions of the GNU General Public License cover the whole
// combination.
//
// As a special exception, the copyright holders of this library give you
// permission to link this library with independent modules to produce an
// executable, regardless of the license terms of these independent
// modules, and to copy and distribute the resulting executable under
// terms of your choice, provided that you also meet, for each linked
// independent module, the terms and conditions of the license of that
// module. An independent module is a module which is not derived from
// or based on this library. If you modify this library, you may extend
// this exception to your version of the library, but you are not
// obligated to do so. If you do not wish to do so, delete this
// exception statement from your version.
using System;
using System.IO;
namespace Plupload.PngEncoder {
/// <summary>
/// A special stream deflating or compressing the bytes that are
/// written to it. It uses a Deflater to perform actual deflating.<br/>
/// Authors of the original java version : Tom Tromey, Jochen Hoenicke
/// </summary>
public class DeflaterOutputStream : Stream {
#region Constructors
/// <summary>
/// Creates a new DeflaterOutputStream with a default Deflater and default buffer size.
/// </summary>
/// <param name="baseOutputStream">
/// the output stream where deflated output should be written.
/// </param>
public DeflaterOutputStream(Stream baseOutputStream)
: this(baseOutputStream, new Deflater(), 512) {
}
/// <summary>
/// Creates a new DeflaterOutputStream with the given Deflater and
/// default buffer size.
/// </summary>
/// <param name="baseOutputStream">
/// the output stream where deflated output should be written.
/// </param>
/// <param name="deflater">
/// the underlying deflater.
/// </param>
public DeflaterOutputStream(Stream baseOutputStream, Deflater deflater)
: this(baseOutputStream, deflater, 512) {
}
/// <summary>
/// Creates a new DeflaterOutputStream with the given Deflater and
/// buffer size.
/// </summary>
/// <param name="baseOutputStream">
/// The output stream where deflated output is written.
/// </param>
/// <param name="deflater">
/// The underlying deflater to use
/// </param>
/// <param name="bufferSize">
/// The buffer size to use when deflating
/// </param>
/// <exception cref="ArgumentOutOfRangeException">
/// bufsize is less than or equal to zero.
/// </exception>
/// <exception cref="ArgumentException">
/// baseOutputStream does not support writing
/// </exception>
/// <exception cref="ArgumentNullException">
/// deflater instance is null
/// </exception>
public DeflaterOutputStream(Stream baseOutputStream, Deflater deflater, int bufferSize) {
if (baseOutputStream == null) {
throw new ArgumentNullException("baseOutputStream");
}
if (baseOutputStream.CanWrite == false) {
throw new ArgumentException("Must support writing", "baseOutputStream");
}
if (deflater == null) {
throw new ArgumentNullException("deflater");
}
if (bufferSize <= 0) {
throw new ArgumentOutOfRangeException("bufferSize");
}
baseOutputStream_ = baseOutputStream;
buffer_ = new byte[bufferSize];
deflater_ = deflater;
}
#endregion
#region Public API
/// <summary>
/// Finishes the stream by calling finish() on the deflater.
/// </summary>
/// <exception cref="SharpZipBaseException">
/// Not all input is deflated
/// </exception>
public virtual void Finish() {
deflater_.Finish();
while (!deflater_.IsFinished) {
int len = deflater_.Deflate(buffer_, 0, buffer_.Length);
if (len <= 0) {
break;
}
if (keys != null) {
EncryptBlock(buffer_, 0, len);
}
baseOutputStream_.Write(buffer_, 0, len);
}
if (!deflater_.IsFinished) {
throw new Exception("Can't deflate all input?");
}
baseOutputStream_.Flush();
if (keys != null) {
keys = null;
}
}
/// <summary>
/// Get/set flag indicating ownership of the underlying stream.
/// When the flag is true <see cref="Close"></see> will close the underlying stream also.
/// </summary>
public bool IsStreamOwner {
get { return isStreamOwner_; }
set { isStreamOwner_ = value; }
}
/// <summary>
/// Allows client to determine if an entry can be patched after its added
/// </summary>
public bool CanPatchEntries {
get {
return baseOutputStream_.CanSeek;
}
}
#endregion
#region Encryption
string password;
uint[] keys;
/// <summary>
/// Get/set the password used for encryption.
/// </summary>
/// <remarks>When set to null or if the password is empty no encryption is performed</remarks>
public string Password {
get {
return password;
}
set {
if ((value != null) && (value.Length == 0)) {
password = null;
} else {
password = value;
}
}
}
/// <summary>
/// Encrypt a block of data
/// </summary>
/// <param name="buffer">
/// Data to encrypt. NOTE the original contents of the buffer are lost
/// </param>
/// <param name="offset">
/// Offset of first byte in buffer to encrypt
/// </param>
/// <param name="length">
/// Number of bytes in buffer to encrypt
/// </param>
protected void EncryptBlock(byte[] buffer, int offset, int length) {
for (int i = offset; i < offset + length; ++i) {
byte oldbyte = buffer[i];
buffer[i] ^= EncryptByte();
UpdateKeys(oldbyte);
}
}
/// <summary>
/// Encrypt a single byte
/// </summary>
/// <returns>
/// The encrypted value
/// </returns>
protected byte EncryptByte() {
uint temp = ((keys[2] & 0xFFFF) | 2);
return (byte) ((temp * (temp ^ 1)) >> 8);
}
/// <summary>
/// Update encryption keys
/// </summary>
protected void UpdateKeys(byte ch) {
keys[0] = Crc32.ComputeCrc32(keys[0], ch);
keys[1] = keys[1] + (byte) keys[0];
keys[1] = keys[1] * 134775813 + 1;
keys[2] = Crc32.ComputeCrc32(keys[2], (byte) (keys[1] >> 24));
}
#endregion
#region Deflation Support
/// <summary>
/// Deflates everything in the input buffers. This will call
/// <code>def.deflate()</code> until all bytes from the input buffers
/// are processed.
/// </summary>
protected void Deflate() {
while (!deflater_.IsNeedingInput) {
int deflateCount = deflater_.Deflate(buffer_, 0, buffer_.Length);
if (deflateCount <= 0) {
break;
}
if (keys != null) {
EncryptBlock(buffer_, 0, deflateCount);
}
baseOutputStream_.Write(buffer_, 0, deflateCount);
}
if (!deflater_.IsNeedingInput) {
throw new Exception("DeflaterOutputStream can't deflate all input?");
}
}
#endregion
#region Stream Overrides
/// <summary>
/// Gets value indicating stream can be read from
/// </summary>
public override bool CanRead {
get {
return false;
}
}
/// <summary>
/// Gets a value indicating if seeking is supported for this stream
/// This property always returns false
/// </summary>
public override bool CanSeek {
get {
return false;
}
}
/// <summary>
/// Get value indicating if this stream supports writing
/// </summary>
public override bool CanWrite {
get {
return baseOutputStream_.CanWrite;
}
}
/// <summary>
/// Get current length of stream
/// </summary>
public override long Length {
get {
return baseOutputStream_.Length;
}
}
/// <summary>
/// Gets the current position within the stream.
/// </summary>
/// <exception cref="NotSupportedException">Any attempt to set position</exception>
public override long Position {
get {
return baseOutputStream_.Position;
}
set {
throw new NotSupportedException("Position property not supported");
}
}
/// <summary>
/// Sets the current position of this stream to the given value. Not supported by this class!
/// </summary>
/// <param name="offset">The offset relative to the <paramref name="origin"/> to seek.</param>
/// <param name="origin">The <see cref="SeekOrigin"/> to seek from.</param>
/// <returns>The new position in the stream.</returns>
/// <exception cref="NotSupportedException">Any access</exception>
public override long Seek(long offset, SeekOrigin origin) {
throw new NotSupportedException("DeflaterOutputStream Seek not supported");
}
/// <summary>
/// Sets the length of this stream to the given value. Not supported by this class!
/// </summary>
/// <param name="value">The new stream length.</param>
/// <exception cref="NotSupportedException">Any access</exception>
public override void SetLength(long value) {
throw new NotSupportedException("DeflaterOutputStream SetLength not supported");
}
/// <summary>
/// Read a byte from stream advancing position by one
/// </summary>
/// <returns>The byte read cast to an int. THe value is -1 if at the end of the stream.</returns>
/// <exception cref="NotSupportedException">Any access</exception>
public override int ReadByte() {
throw new NotSupportedException("DeflaterOutputStream ReadByte not supported");
}
/// <summary>
/// Read a block of bytes from stream
/// </summary>
/// <param name="buffer">The buffer to store read data in.</param>
/// <param name="offset">The offset to start storing at.</param>
/// <param name="count">The maximum number of bytes to read.</param>
/// <returns>The actual number of bytes read. Zero if end of stream is detected.</returns>
/// <exception cref="NotSupportedException">Any access</exception>
public override int Read(byte[] buffer, int offset, int count) {
throw new NotSupportedException("DeflaterOutputStream Read not supported");
}
/// <summary>
/// Asynchronous reads are not supported a NotSupportedException is always thrown
/// </summary>
/// <param name="buffer">The buffer to read into.</param>
/// <param name="offset">The offset to start storing data at.</param>
/// <param name="count">The number of bytes to read</param>
/// <param name="callback">The async callback to use.</param>
/// <param name="state">The state to use.</param>
/// <returns>Returns an <see cref="IAsyncResult"/></returns>
/// <exception cref="NotSupportedException">Any access</exception>
public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state) {
throw new NotSupportedException("DeflaterOutputStream BeginRead not currently supported");
}
/// <summary>
/// Asynchronous writes arent supported, a NotSupportedException is always thrown
/// </summary>
/// <param name="buffer">The buffer to write.</param>
/// <param name="offset">The offset to begin writing at.</param>
/// <param name="count">The number of bytes to write.</param>
/// <param name="callback">The <see cref="AsyncCallback"/> to use.</param>
/// <param name="state">The state object.</param>
/// <returns>Returns an IAsyncResult.</returns>
/// <exception cref="NotSupportedException">Any access</exception>
public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) {
throw new NotSupportedException("BeginWrite is not supported");
}
/// <summary>
/// Flushes the stream by calling <see cref="DeflaterOutputStream.Flush">Flush</see> on the deflater and then
/// on the underlying stream. This ensures that all bytes are flushed.
/// </summary>
public override void Flush() {
deflater_.Flush();
Deflate();
baseOutputStream_.Flush();
}
/// <summary>
/// Calls <see cref="Finish"/> and closes the underlying
/// stream when <see cref="IsStreamOwner"></see> is true.
/// </summary>
public override void Close() {
if (!isClosed_) {
isClosed_ = true;
try {
Finish();
keys = null;
} finally {
if (isStreamOwner_) {
baseOutputStream_.Close();
}
}
}
}
/// <summary>
/// Writes a single byte to the compressed output stream.
/// </summary>
/// <param name="value">
/// The byte value.
/// </param>
public override void WriteByte(byte value) {
byte[] b = new byte[1];
b[0] = value;
Write(b, 0, 1);
}
/// <summary>
/// Writes bytes from an array to the compressed stream.
/// </summary>
/// <param name="buffer">
/// The byte array
/// </param>
/// <param name="offset">
/// The offset into the byte array where to start.
/// </param>
/// <param name="count">
/// The number of bytes to write.
/// </param>
public override void Write(byte[] buffer, int offset, int count) {
deflater_.SetInput(buffer, offset, count);
Deflate();
}
#endregion
#region Instance Fields
/// <summary>
/// This buffer is used temporarily to retrieve the bytes from the
/// deflater and write them to the underlying output stream.
/// </summary>
byte[] buffer_;
/// <summary>
/// The deflater which is used to deflate the stream.
/// </summary>
protected Deflater deflater_;
/// <summary>
/// Base stream the deflater depends on.
/// </summary>
protected Stream baseOutputStream_;
bool isClosed_;
bool isStreamOwner_ = true;
#endregion
}
}

View file

@ -1,55 +0,0 @@
// DeflaterPending.cs
//
// Copyright (C) 2001 Mike Krueger
// Copyright (C) 2004 John Reilly
//
// This file was translated from java, it was part of the GNU Classpath
// Copyright (C) 2001 Free Software Foundation, Inc.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
// Linking this library statically or dynamically with other modules is
// making a combined work based on this library. Thus, the terms and
// conditions of the GNU General Public License cover the whole
// combination.
//
// As a special exception, the copyright holders of this library give you
// permission to link this library with independent modules to produce an
// executable, regardless of the license terms of these independent
// modules, and to copy and distribute the resulting executable under
// terms of your choice, provided that you also meet, for each linked
// independent module, the terms and conditions of the license of that
// module. An independent module is a module which is not derived from
// or based on this library. If you modify this library, you may extend
// this exception to your version of the library, but you are not
// obligated to do so. If you do not wish to do so, delete this
// exception statement from your version.
namespace Plupload.PngEncoder {
/// <summary>
/// This class stores the pending output of the Deflater.
///
/// author of the original java version : Jochen Hoenicke
/// </summary>
public class DeflaterPending : PendingBuffer {
/// <summary>
/// Construct instance with default buffer size
/// </summary>
public DeflaterPending()
: base(DeflaterConstants.PENDING_BUF_SIZE) {
}
}
}

View file

@ -1,90 +0,0 @@
// IChecksum.cs - Interface to compute a data checksum
// Copyright (C) 2001 Mike Krueger
//
// This file was translated from java, it was part of the GNU Classpath
// Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
// Linking this library statically or dynamically with other modules is
// making a combined work based on this library. Thus, the terms and
// conditions of the GNU General Public License cover the whole
// combination.
//
// As a special exception, the copyright holders of this library give you
// permission to link this library with independent modules to produce an
// executable, regardless of the license terms of these independent
// modules, and to copy and distribute the resulting executable under
// terms of your choice, provided that you also meet, for each linked
// independent module, the terms and conditions of the license of that
// module. An independent module is a module which is not derived from
// or based on this library. If you modify this library, you may extend
// this exception to your version of the library, but you are not
// obligated to do so. If you do not wish to do so, delete this
// exception statement from your version.
namespace Plupload.PngEncoder {
/// <summary>
/// Interface to compute a data checksum used by checked input/output streams.
/// A data checksum can be updated by one byte or with a byte array. After each
/// update the value of the current checksum can be returned by calling
/// <code>getValue</code>. The complete checksum object can also be reset
/// so it can be used again with new data.
/// </summary>
public interface IChecksum {
/// <summary>
/// Returns the data checksum computed so far.
/// </summary>
long Value {
get;
}
/// <summary>
/// Resets the data checksum as if no update was ever called.
/// </summary>
void Reset();
/// <summary>
/// Adds one byte to the data checksum.
/// </summary>
/// <param name = "value">
/// the data value to add. The high byte of the int is ignored.
/// </param>
void Update(int value);
/// <summary>
/// Updates the data checksum with the bytes taken from the array.
/// </summary>
/// <param name="buffer">
/// buffer an array of bytes
/// </param>
void Update(byte[] buffer);
/// <summary>
/// Adds the byte array to the data checksum.
/// </summary>
/// <param name = "buffer">
/// The buffer which contains the data
/// </param>
/// <param name = "offset">
/// The offset in the buffer where the data starts
/// </param>
/// <param name = "count">
/// the number of data bytes to add.
/// </param>
void Update(byte[] buffer, int offset, int count);
}
}

View file

@ -1,281 +0,0 @@
// PendingBuffer.cs
//
// Copyright (C) 2001 Mike Krueger
// Copyright (C) 2004 John Reilly
//
// This file was translated from java, it was part of the GNU Classpath
// Copyright (C) 2001 Free Software Foundation, Inc.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
// Linking this library statically or dynamically with other modules is
// making a combined work based on this library. Thus, the terms and
// conditions of the GNU General Public License cover the whole
// combination.
//
// As a special exception, the copyright holders of this library give you
// permission to link this library with independent modules to produce an
// executable, regardless of the license terms of these independent
// modules, and to copy and distribute the resulting executable under
// terms of your choice, provided that you also meet, for each linked
// independent module, the terms and conditions of the license of that
// module. An independent module is a module which is not derived from
// or based on this library. If you modify this library, you may extend
// this exception to your version of the library, but you are not
// obligated to do so. If you do not wish to do so, delete this
// exception statement from your version.
using System;
namespace Plupload.PngEncoder {
/// <summary>
/// This class is general purpose class for writing data to a buffer.
///
/// It allows you to write bits as well as bytes
/// Based on DeflaterPending.java
///
/// author of the original java version : Jochen Hoenicke
/// </summary>
public class PendingBuffer {
#region Instance Fields
/// <summary>
/// Internal work buffer
/// </summary>
byte[] buffer_;
int start;
int end;
uint bits;
int bitCount;
#endregion
#region Constructors
/// <summary>
/// construct instance using default buffer size of 4096
/// </summary>
public PendingBuffer()
: this(4096) {
}
/// <summary>
/// construct instance using specified buffer size
/// </summary>
/// <param name="bufferSize">
/// size to use for internal buffer
/// </param>
public PendingBuffer(int bufferSize) {
buffer_ = new byte[bufferSize];
}
#endregion
/// <summary>
/// Clear internal state/buffers
/// </summary>
public void Reset() {
start = end = bitCount = 0;
}
/// <summary>
/// Write a byte to buffer
/// </summary>
/// <param name="value">
/// The value to write
/// </param>
public void WriteByte(int value) {
#if DebugDeflation
if (DeflaterConstants.DEBUGGING && (start != 0) )
{
throw new SharpZipBaseException("Debug check: start != 0");
}
#endif
buffer_[end++] = unchecked((byte) value);
}
/// <summary>
/// Write a short value to buffer LSB first
/// </summary>
/// <param name="value">
/// The value to write.
/// </param>
public void WriteShort(int value) {
#if DebugDeflation
if (DeflaterConstants.DEBUGGING && (start != 0) )
{
throw new SharpZipBaseException("Debug check: start != 0");
}
#endif
buffer_[end++] = unchecked((byte) value);
buffer_[end++] = unchecked((byte) (value >> 8));
}
/// <summary>
/// write an integer LSB first
/// </summary>
/// <param name="value">The value to write.</param>
public void WriteInt(int value) {
#if DebugDeflation
if (DeflaterConstants.DEBUGGING && (start != 0) )
{
throw new SharpZipBaseException("Debug check: start != 0");
}
#endif
buffer_[end++] = unchecked((byte) value);
buffer_[end++] = unchecked((byte) (value >> 8));
buffer_[end++] = unchecked((byte) (value >> 16));
buffer_[end++] = unchecked((byte) (value >> 24));
}
/// <summary>
/// Write a block of data to buffer
/// </summary>
/// <param name="block">data to write</param>
/// <param name="offset">offset of first byte to write</param>
/// <param name="length">number of bytes to write</param>
public void WriteBlock(byte[] block, int offset, int length) {
#if DebugDeflation
if (DeflaterConstants.DEBUGGING && (start != 0) )
{
throw new SharpZipBaseException("Debug check: start != 0");
}
#endif
System.Array.Copy(block, offset, buffer_, end, length);
end += length;
}
/// <summary>
/// The number of bits written to the buffer
/// </summary>
public int BitCount {
get {
return bitCount;
}
}
/// <summary>
/// Align internal buffer on a byte boundary
/// </summary>
public void AlignToByte() {
#if DebugDeflation
if (DeflaterConstants.DEBUGGING && (start != 0) )
{
throw new SharpZipBaseException("Debug check: start != 0");
}
#endif
if (bitCount > 0) {
buffer_[end++] = unchecked((byte) bits);
if (bitCount > 8) {
buffer_[end++] = unchecked((byte) (bits >> 8));
}
}
bits = 0;
bitCount = 0;
}
/// <summary>
/// Write bits to internal buffer
/// </summary>
/// <param name="b">source of bits</param>
/// <param name="count">number of bits to write</param>
public void WriteBits(int b, int count) {
#if DebugDeflation
if (DeflaterConstants.DEBUGGING && (start != 0) )
{
throw new SharpZipBaseException("Debug check: start != 0");
}
// if (DeflaterConstants.DEBUGGING) {
// //Console.WriteLine("writeBits("+b+","+count+")");
// }
#endif
bits |= (uint) (b << bitCount);
bitCount += count;
if (bitCount >= 16) {
buffer_[end++] = unchecked((byte) bits);
buffer_[end++] = unchecked((byte) (bits >> 8));
bits >>= 16;
bitCount -= 16;
}
}
/// <summary>
/// Write a short value to internal buffer most significant byte first
/// </summary>
/// <param name="s">value to write</param>
public void WriteShortMSB(int s) {
#if DebugDeflation
if (DeflaterConstants.DEBUGGING && (start != 0) )
{
throw new SharpZipBaseException("Debug check: start != 0");
}
#endif
buffer_[end++] = unchecked((byte) (s >> 8));
buffer_[end++] = unchecked((byte) s);
}
/// <summary>
/// Indicates if buffer has been flushed
/// </summary>
public bool IsFlushed {
get {
return end == 0;
}
}
/// <summary>
/// Flushes the pending buffer into the given output array. If the
/// output array is to small, only a partial flush is done.
/// </summary>
/// <param name="output">The output array.</param>
/// <param name="offset">The offset into output array.</param>
/// <param name="length">The maximum number of bytes to store.</param>
/// <returns>The number of bytes flushed.</returns>
public int Flush(byte[] output, int offset, int length) {
if (bitCount >= 8) {
buffer_[end++] = unchecked((byte) bits);
bits >>= 8;
bitCount -= 8;
}
if (length > end - start) {
length = end - start;
System.Array.Copy(buffer_, start, output, offset, length);
start = 0;
end = 0;
} else {
System.Array.Copy(buffer_, start, output, offset, length);
start += length;
}
return length;
}
/// <summary>
/// Convert internal buffer to byte array.
/// Buffer is empty on completion
/// </summary>
/// <returns>
/// The internal buffer contents converted to a byte array.
/// </returns>
public byte[] ToByteArray() {
byte[] result = new byte[end - start];
System.Array.Copy(buffer_, start, result, 0, result.Length);
start = 0;
end = 0;
return result;
}
}
}

View file

@ -1,467 +0,0 @@
/**
* PngEncoder takes a pixel data byte array and creates a byte string which can be saved as a PNG file.
*
* <p>Thanks to Jay Denny at KeyPoint Software
* http://www.keypoint.com/
* who let me develop this code on company time.</p>
*
* <p>You may contact me with (probably very-much-needed) improvements,
* comments, and bug fixes at:</p>
*
* <p><code>david@catcode.com</code></p>
*
* <p>This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.</p>
*
* <p>This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.</p>
*
* <p>You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* A copy of the GNU LGPL may be found at
* <code>http://www.gnu.org/copyleft/lesser.html</code></p>
*
* @author J. David Eisenberg
* @version 1.5, 19 Oct 2003
*
* CHANGES:
* --------
* 19-Nov-2002 : CODING STYLE CHANGES ONLY (by David Gilbert for Object Refinery Limited);
* 19-Sep-2003 : Fix for platforms using EBCDIC (contributed by Paulo Soares);
* 19-Oct-2003 : Change private fields to protected fields so that
* PngEncoderB can inherit them (JDE)
* Fixed bug with calculation of nRows
* 2009-12-22 : Ported Java version over to C#.
*/
using System;
using System.IO;
namespace Plupload.PngEncoder {
public class PngEncoder {
/** Constant specifying that alpha channel should be encoded. */
public const bool ENCODE_ALPHA = true;
/** Constant specifying that alpha channel should not be encoded. */
public const bool NO_ALPHA = false;
/** Constants for filter (NONE) */
public const int FILTER_NONE = 0;
/** Constants for filter (SUB) */
public const int FILTER_SUB = 1;
/** Constants for filter (UP) */
public const int FILTER_UP = 2;
/** Constants for filter (LAST) */
public const int FILTER_LAST = 2;
/** IHDR tag. */
protected static byte[] IHDR = new byte[] { 73, 72, 68, 82 };
/** IDAT tag. */
protected static byte[] IDAT = new byte[] { 73, 68, 65, 84 };
/** IEND tag. */
protected static byte[] IEND = new byte[] { 73, 69, 78, 68 };
/** The png bytes. */
protected byte[] pngBytes;
/** The prior row. */
protected byte[] priorRow;
/** The left bytes. */
protected byte[] leftBytes;
/** The width. */
protected int width, height;
/** The byte position. */
protected int bytePos, maxPos;
/** CRC. */
protected Crc32 crc = new Crc32();
/** The CRC value. */
protected long crcValue;
/** Encode alpha? */
protected bool encodeAlpha;
/** The filter type. */
protected int filter;
/** The bytes-per-pixel. */
protected int bytesPerPixel;
/** The compression level. */
protected int compressionLevel;
/** PixelData array to encode */
protected int[] pixelData;
/**
* Class constructor specifying Image source to encode, whether to encode alpha, filter to use,
* and compression level.
*
* @param pixel_data A Java Image object
* @param encodeAlpha Encode the alpha channel? false=no; true=yes
* @param whichFilter 0=none, 1=sub, 2=up
* @param compLevel 0..9
* @see java.awt.Image
*/
public PngEncoder(int[] pixel_data, int width, int height, bool encodeAlpha, int whichFilter, int compLevel) {
this.pixelData = pixel_data;
this.width = width;
this.height = height;
this.encodeAlpha = encodeAlpha;
this.filter = FILTER_NONE;
if (whichFilter <= FILTER_LAST) {
this.filter = whichFilter;
}
if (compLevel >= 0 && compLevel <= 9) {
this.compressionLevel = compLevel;
}
}
/**
* Creates an array of bytes that is the PNG equivalent of the current image, specifying
* whether to encode alpha or not.
*
* @param encodeAlpha boolean false=no alpha, true=encode alpha
* @return an array of bytes, or null if there was a problem
*/
public byte[] Encode(bool encodeAlpha) {
byte[] pngIdBytes = { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A };
/*
* start with an array that is big enough to hold all the pixels
* (plus filter bytes), and an extra 200 bytes for header info
*/
pngBytes = new byte[((width + 1) * height * 3) + 200];
/*
* keep track of largest byte written to the array
*/
maxPos = 0;
bytePos = WriteBytes(pngIdBytes, 0);
//hdrPos = bytePos;
writeHeader();
//dataPos = bytePos;
if (WriteImageData()) {
writeEnd();
pngBytes = ResizeByteArray(pngBytes, maxPos);
} else {
pngBytes = null;
}
return pngBytes;
}
/**
* Creates an array of bytes that is the PNG equivalent of the current image.
* Alpha encoding is determined by its setting in the constructor.
*
* @return an array of bytes, or null if there was a problem
*/
public byte[] pngEncode() {
return Encode(encodeAlpha);
}
/**
* Increase or decrease the length of a byte array.
*
* @param array The original array.
* @param newLength The length you wish the new array to have.
* @return Array of newly desired length. If shorter than the
* original, the trailing elements are truncated.
*/
protected byte[] ResizeByteArray(byte[] array, int newLength) {
byte[] newArray = new byte[newLength];
int oldLength = array.Length;
Array.Copy(array, 0, newArray, 0, Math.Min(oldLength, newLength));
return newArray;
}
/**
* Write an array of bytes into the pngBytes array.
* Note: This routine has the side effect of updating
* maxPos, the largest element written in the array.
* The array is resized by 1000 bytes or the length
* of the data to be written, whichever is larger.
*
* @param data The data to be written into pngBytes.
* @param offset The starting point to write to.
* @return The next place to be written to in the pngBytes array.
*/
protected int WriteBytes(byte[] data, int offset) {
maxPos = Math.Max(maxPos, offset + data.Length);
if (data.Length + offset > pngBytes.Length)
pngBytes = ResizeByteArray(pngBytes, pngBytes.Length + Math.Max(1000, data.Length));
Array.Copy(data, 0, pngBytes, offset, data.Length);
return offset + data.Length;
}
/**
* Write an array of bytes into the pngBytes array, specifying number of bytes to write.
* Note: This routine has the side effect of updating
* maxPos, the largest element written in the array.
* The array is resized by 1000 bytes or the length
* of the data to be written, whichever is larger.
*
* @param data The data to be written into pngBytes.
* @param nBytes The number of bytes to be written.
* @param offset The starting point to write to.
* @return The next place to be written to in the pngBytes array.
*/
protected int WriteBytes(byte[] data, int nBytes, int offset) {
maxPos = Math.Max(maxPos, offset + nBytes);
if (nBytes + offset > pngBytes.Length)
pngBytes = ResizeByteArray(pngBytes, pngBytes.Length + Math.Max(1000, nBytes));
Array.Copy(data, 0, pngBytes, offset, nBytes);
return offset + nBytes;
}
/**
* Write a two-byte integer into the pngBytes array at a given position.
*
* @param n The integer to be written into pngBytes.
* @param offset The starting point to write to.
* @return The next place to be written to in the pngBytes array.
*/
protected int WriteInt2(int n, int offset) {
byte[] temp = { (byte) ((n >> 8) & 0xff), (byte) (n & 0xff) };
return WriteBytes(temp, offset);
}
/**
* Write a four-byte integer into the pngBytes array at a given position.
*
* @param n The integer to be written into pngBytes.
* @param offset The starting point to write to.
* @return The next place to be written to in the pngBytes array.
*/
protected int WriteInt4(int n, int offset) {
byte[] temp = {(byte) ((n >> 24) & 0xff),
(byte) ((n >> 16) & 0xff),
(byte) ((n >> 8) & 0xff),
(byte) (n & 0xff)};
return WriteBytes(temp, offset);
}
/**
* Write a single byte into the pngBytes array at a given position.
*
* @param b The integer to be written into pngBytes.
* @param offset The starting point to write to.
* @return The next place to be written to in the pngBytes array.
*/
protected int WriteByte(int b, int offset) {
byte[] temp = { (byte) b };
return WriteBytes(temp, offset);
}
/**
* Write a PNG "IHDR" chunk into the pngBytes array.
*/
protected void writeHeader() {
int startPos;
startPos = bytePos = WriteInt4(13, bytePos);
bytePos = WriteBytes(IHDR, bytePos);
bytePos = WriteInt4(width, bytePos);
bytePos = WriteInt4(height, bytePos);
bytePos = WriteByte(8, bytePos); // bit depth
bytePos = WriteByte((encodeAlpha) ? 6 : 2, bytePos); // direct model
bytePos = WriteByte(0, bytePos); // compression method
bytePos = WriteByte(0, bytePos); // filter method
bytePos = WriteByte(0, bytePos); // no interlace
crc.Reset();
crc.Update(pngBytes, startPos, bytePos - startPos);
crcValue = crc.Value;
bytePos = WriteInt4((int) crcValue, bytePos);
}
/**
* Perform "sub" filtering on the given row.
* Uses temporary array leftBytes to store the original values
* of the previous pixels. The array is 16 bytes long, which
* will easily hold two-byte samples plus two-byte alpha.
*
* @param pixels The array holding the scan lines being built
* @param startPos Starting position within pixels of bytes to be filtered.
* @param width Width of a scanline in pixels.
*/
protected void FilterSub(byte[] pixels, int startPos, int width) {
int i;
int offset = bytesPerPixel;
int actualStart = startPos + offset;
int nBytes = width * bytesPerPixel;
int leftInsert = offset;
int leftExtract = 0;
for (i = actualStart; i < startPos + nBytes; i++) {
leftBytes[leftInsert] = pixels[i];
pixels[i] = (byte) ((pixels[i] - leftBytes[leftExtract]) % 256);
leftInsert = (leftInsert + 1) % 0x0f;
leftExtract = (leftExtract + 1) % 0x0f;
}
}
/**
* Perform "up" filtering on the given row.
* Side effect: refills the prior row with current row
*
* @param pixels The array holding the scan lines being built
* @param startPos Starting position within pixels of bytes to be filtered.
* @param width Width of a scanline in pixels.
*/
protected void FilterUp(byte[] pixels, int startPos, int width) {
int i, nBytes;
byte currentByte;
nBytes = width * bytesPerPixel;
for (i = 0; i < nBytes; i++) {
currentByte = pixels[startPos + i];
pixels[startPos + i] = (byte) ((pixels[startPos + i] - priorRow[i]) % 256);
priorRow[i] = currentByte;
}
}
/**
* Write the image data into the pngBytes array.
* This will write one or more PNG "IDAT" chunks. In order
* to conserve memory, this method grabs as many rows as will
* fit into 32K bytes, or the whole image; whichever is less.
*
*
* @return true if no errors; false if error grabbing pixels
*/
protected bool WriteImageData() {
int rowsLeft = height; // number of rows remaining to write
int startRow = 0; // starting row to process this time through
int nRows; // how many rows to grab at a time
byte[] scanLines; // the scan lines to be compressed
int scanPos; // where we are in the scan lines
int startPos; // where this line's actual pixels start (used for filtering)
byte[] compressedLines; // the resultant compressed lines
int nCompressed; // how big is the compressed area?
//int depth; // color depth ( handle only 8 or 32 )
bytesPerPixel = (encodeAlpha) ? 4 : 3;
Deflater scrunch = new Deflater(compressionLevel);
MemoryStream outBytes = new MemoryStream(1024);
DeflaterOutputStream compBytes = new DeflaterOutputStream(outBytes, scrunch);
try {
while (rowsLeft > 0) {
nRows = Math.Min(32767 / (width * (bytesPerPixel + 1)), rowsLeft);
nRows = Math.Max(nRows, 1);
int[] pixels = new int[width * nRows];
Array.Copy(this.pixelData, width * startRow, pixels, 0, width * nRows);
/*
* Create a data chunk. scanLines adds "nRows" for
* the filter bytes.
*/
scanLines = new byte[width * nRows * bytesPerPixel + nRows];
if (filter == FILTER_SUB) {
leftBytes = new byte[16];
}
if (filter == FILTER_UP) {
priorRow = new byte[width * bytesPerPixel];
}
scanPos = 0;
startPos = 1;
for (int i = 0; i < width * nRows; i++) {
if (i % width == 0) {
scanLines[scanPos++] = (byte) filter;
startPos = scanPos;
}
scanLines[scanPos++] = (byte) ((pixels[i] >> 16) & 0xff);
scanLines[scanPos++] = (byte) ((pixels[i] >> 8) & 0xff);
scanLines[scanPos++] = (byte) ((pixels[i]) & 0xff);
if (encodeAlpha) {
scanLines[scanPos++] = (byte) ((pixels[i] >> 24) & 0xff);
}
if ((i % width == width - 1) && (filter != FILTER_NONE)) {
if (filter == FILTER_SUB) {
FilterSub(scanLines, startPos, width);
}
if (filter == FILTER_UP) {
FilterUp(scanLines, startPos, width);
}
}
}
/*
* Write these lines to the output area
*/
compBytes.Write(scanLines, 0, scanPos);
startRow += nRows;
rowsLeft -= nRows;
}
compBytes.Close();
/*
* Write the compressed bytes
*/
compressedLines = outBytes.ToArray();
nCompressed = compressedLines.Length;
crc.Reset();
bytePos = WriteInt4(nCompressed, bytePos);
bytePos = WriteBytes(IDAT, bytePos);
crc.Update(IDAT);
bytePos = WriteBytes(compressedLines, nCompressed, bytePos);
crc.Update(compressedLines, 0, nCompressed);
crcValue = crc.Value;
bytePos = WriteInt4((int) crcValue, bytePos);
scrunch.Finish();
return true;
} catch {
return false;
}
}
/**
* Write a PNG "IEND" chunk into the pngBytes array.
*/
protected void writeEnd() {
bytePos = WriteInt4(0, bytePos);
bytePos = WriteBytes(IEND, bytePos);
crc.Reset();
crc.Update(IEND);
crcValue = crc.Value;
bytePos = WriteInt4((int) crcValue, bytePos);
}
}
}

View file

@ -1,6 +0,0 @@
<Deployment xmlns="http://schemas.microsoft.com/client/2007/deployment"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
ExternalCallersFromCrossDomain="ScriptableOnly">
<Deployment.Parts>
</Deployment.Parts>
</Deployment>

View file

@ -1,45 +0,0 @@
/**
* $Id: AssemblyInfo.cs 480 2008-10-20 15:37:42Z spocke $
*
* @package MCManagerCore
* @author Moxiecode
* @copyright Copyright © 2007, Moxiecode Systems AB, All rights reserved.
*/
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Plupload")]
[assembly: AssemblyDescription("Multiple upload component.")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Moxiecode Systems AB")]
[assembly: AssemblyProduct("Upload")]
[assembly: AssemblyCopyright("Copyright © 2009")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("95f0dee8-de7a-46c5-9dcc-0570b0fc4643")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View file

@ -1,486 +0,0 @@
/*
* $Id: JSONReader.cs 9 2007-05-27 10:47:07Z spocke $
*
* Copyright © 2007, Moxiecode Systems AB, All rights reserved.
*/
using System;
using System.IO;
using System.Text;
using System.Collections;
using System.Collections.Generic;
namespace Moxiecode.Plupload.Utils {
class Stack {
private List<object> items;
public Stack() {
items = new List<object>();
}
public void Push(object item) {
items.Add(item);
}
public object Pop() {
object item = items[items.Count - 1];
items.RemoveAt(items.Count - 1);
return item;
}
}
/// <summary>
///
/// </summary>
public enum JsonLocation {
/// <summary> </summary>
InArray,
/// <summary> </summary>
InObject,
/// <summary> </summary>
Normal
}
/// <summary>
///
/// </summary>
public enum JsonToken {
/// <summary> </summary>
Boolean,
/// <summary> </summary>
Integer,
/// <summary> </summary>
String,
/// <summary> </summary>
Null,
/// <summary> </summary>
Float,
/// <summary> </summary>
StartArray,
/// <summary> </summary>
EndArray,
/// <summary> </summary>
PropertyName,
/// <summary> </summary>
StartObject,
/// <summary> </summary>
EndObject
}
/// <summary>
/// Description of JSONReader.
/// </summary>
public class JsonReader {
private TextReader reader;
private JsonToken token;
private object val;
private JsonLocation location;
private Stack lastLocations;
private bool needProp;
/// <summary>
///
/// </summary>
/// <param name="reader"></param>
public JsonReader(TextReader reader) {
this.reader = reader;
this.val = null;
this.token = JsonToken.Null;
this.location = JsonLocation.Normal;
this.lastLocations = new Stack();
this.needProp = false;
}
public static object ParseJson(String json) {
JsonReader reader = new JsonReader(new StringReader(json));
return reader.ReadValue();
}
/// <summary>
///
/// </summary>
public JsonLocation Location {
get { return location; }
}
/// <summary>
///
/// </summary>
public JsonToken TokenType {
get {
return this.token;
}
}
/// <summary>
///
/// </summary>
public object Value {
get {
return this.val;
}
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public bool Read() {
int chr = this.reader.Read();
if (chr != -1) {
switch ((char) chr) {
case '[':
this.lastLocations.Push(this.location);
this.location = JsonLocation.InArray;
this.token = JsonToken.StartArray;
this.val = null;
this.ReadAway();
return true;
case ']':
this.location = (JsonLocation)this.lastLocations.Pop();
this.token = JsonToken.EndArray;
this.val = null;
this.ReadAway();
if (this.location == JsonLocation.InObject)
this.needProp = true;
return true;
case '{':
this.lastLocations.Push(this.location);
this.location = JsonLocation.InObject;
this.needProp = true;
this.token = JsonToken.StartObject;
this.val = null;
this.ReadAway();
return true;
case '}':
this.location = (JsonLocation) this.lastLocations.Pop();
this.token = JsonToken.EndObject;
this.val = null;
this.ReadAway();
if (this.location == JsonLocation.InObject)
this.needProp = true;
return true;
// String
case '"':
case '\'':
return this.ReadString((char) chr);
// Null
case 'n':
return this.ReadNull();
// Bool
case 't':
case 'f':
return this.ReadBool((char) chr);
default:
// Is number
if (Char.IsNumber((char) chr) || (char) chr == '-' || (char) chr == '.')
return this.ReadNumber((char) chr);
return true;
}
}
return false;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public override string ToString() {
switch (this.token) {
case JsonToken.Boolean:
return "[Boolean] = " + ((bool) this.Value ? "true" : "false");
case JsonToken.EndArray:
return "[EndArray]";
case JsonToken.EndObject:
return "[EndObject]";
case JsonToken.Float:
return "[Float] = " + Convert.ToDouble(this.Value);
case JsonToken.Integer:
return "[Integer] = " + ((int) this.Value);
case JsonToken.Null:
return "[Null]";
case JsonToken.StartArray:
return "[StartArray]";
case JsonToken.StartObject:
return "[StartObject]";
case JsonToken.String:
return "[String]" + (string) this.Value;
case JsonToken.PropertyName:
return "[PropertyName]" + (string) this.Value;
}
return base.ToString();
}
#region private methods
private bool ReadString(char quote) {
StringBuilder buff = new StringBuilder();
this.token = JsonToken.String;
bool endString = false;
int chr;
while ((chr = this.reader.Peek()) != -1) {
switch (chr) {
case '\\':
// Read away slash
chr = this.reader.Read();
// Read escape code
chr = this.reader.Read();
switch (chr) {
case 't':
buff.Append('\t');
break;
case 'b':
buff.Append('\b');
break;
case 'f':
buff.Append('\f');
break;
case 'r':
buff.Append('\r');
break;
case 'n':
buff.Append('\n');
break;
case 'u':
buff.Append((char) Convert.ToInt32(ReadLen(4), 16));
break;
default:
buff.Append((char) chr);
break;
}
break;
case '\'':
case '"':
if (chr == quote)
endString = true;
chr = this.reader.Read();
if (chr != -1 && chr != quote)
buff.Append((char) chr);
break;
default:
buff.Append((char) this.reader.Read());
break;
}
// String terminated
if (endString)
break;
}
this.ReadAway();
this.val = buff.ToString();
// Needed a property
if (this.needProp) {
this.token = JsonToken.PropertyName;
this.needProp = false;
return true;
}
if (this.location == JsonLocation.InObject && !this.needProp)
this.needProp = true;
return true;
}
private bool ReadNull() {
this.token = JsonToken.Null;
this.val = null;
this.ReadAway(3); // ull
this.ReadAway();
if (this.location == JsonLocation.InObject && !this.needProp)
this.needProp = true;
return true;
}
private bool ReadNumber(char start) {
StringBuilder buff = new StringBuilder();
int chr;
bool isFloat = false;
this.token = JsonToken.Integer;
buff.Append(start);
while ((chr = this.reader.Peek()) != -1) {
if (Char.IsNumber((char) chr) || (char) chr == '-' || (char) chr == '.') {
if (((char) chr) == '.')
isFloat = true;
buff.Append((char) this.reader.Read());
} else
break;
}
this.ReadAway();
if (isFloat) {
this.token = JsonToken.Float;
this.val = Convert.ToDouble(buff.ToString().Replace('.', ','));
} else
this.val = Convert.ToInt32(buff.ToString());
if (this.location == JsonLocation.InObject && !this.needProp)
this.needProp = true;
return true;
}
private bool ReadBool(char chr) {
this.token = JsonToken.Boolean;
this.val = chr == 't';
if (chr == 't')
this.ReadAway(3); // rue
else
this.ReadAway(4); // alse
this.ReadAway();
if (this.location == JsonLocation.InObject && !this.needProp)
this.needProp = true;
return true;
}
private void ReadAway() {
int chr;
while ((chr = this.reader.Peek()) != -1) {
if (chr != ':' && chr != ',' && !Char.IsWhiteSpace((char) chr))
break;
this.reader.Read();
}
}
private string ReadLen(int num) {
StringBuilder buff = new StringBuilder();
int chr;
for (int i=0; i<num && (chr = this.reader.Read()) != -1; i++)
buff.Append((char) chr);
return buff.ToString();
}
private void ReadAway(int num) {
for (int i=0; i<num && this.reader.Read() != -1; i++) ;
}
private object ReadValue() {
Stack parents = new Stack();
object cur = null;
string key = null;
object obj;
while (this.Read()) {
switch (this.TokenType) {
case JsonToken.Boolean:
case JsonToken.Integer:
case JsonToken.String:
case JsonToken.Float:
case JsonToken.Null:
if (cur is Dictionary<string, object>) {
((Dictionary<string, object>)cur)[key] = this.Value;
} else if (cur is List<object>)
((List<object>) cur).Add(this.Value);
else
return this.Value;
break;
case JsonToken.PropertyName:
key = (string) this.Value;
break;
case JsonToken.StartArray:
case JsonToken.StartObject:
if (this.TokenType == JsonToken.StartObject) {
obj = new Dictionary<string, object>();
} else {
obj = new List<object>();
}
if (cur is Dictionary<string, object>) {
((Dictionary<string, object>)cur)[key] = obj;
} else if (cur is List<object>) {
((List<object>)cur).Add(obj);
}
parents.Push(cur);
cur = obj;
break;
case JsonToken.EndArray:
case JsonToken.EndObject:
obj = parents.Pop();
if (obj != null)
cur = obj;
break;
}
}
return cur;
}
#endregion
}
}

View file

@ -1,85 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<project>
<!-- Output SWF options -->
<output>
<movie disabled="False" />
<movie input="" />
<movie path="..\..\..\js\plupload.flash.swf" />
<movie fps="30" />
<movie width="800" />
<movie height="600" />
<movie version="10" />
<movie background="#FFFFFF" />
</output>
<!-- Other classes to be compiled into your SWF -->
<classpaths>
<class path="src" />
</classpaths>
<!-- Build options -->
<build>
<option accessible="False" />
<option allowSourcePathOverlap="False" />
<option benchmark="False" />
<option es="False" />
<option locale="" />
<option loadConfig="" />
<option optimize="True" />
<option showActionScriptWarnings="True" />
<option showBindingWarnings="True" />
<option showInvalidCSS="True" />
<option showDeprecationWarnings="True" />
<option showUnusedTypeSelectorWarnings="True" />
<option strict="True" />
<option useNetwork="True" />
<option useResourceBundleMetadata="True" />
<option warnings="True" />
<option verboseStackTraces="False" />
<option linkReport="" />
<option loadExterns="" />
<option staticLinkRSL="True" />
<option additional="" />
<option compilerConstants="" />
<option customSDK="" />
</build>
<!-- SWC Include Libraries -->
<includeLibraries>
<!-- example: <element path="..." /> -->
</includeLibraries>
<!-- SWC Libraries -->
<libraryPaths>
<!-- example: <element path="..." /> -->
</libraryPaths>
<!-- External Libraries -->
<externalLibraryPaths>
<!-- example: <element path="..." /> -->
</externalLibraryPaths>
<!-- Runtime Shared Libraries -->
<rslPaths>
<!-- example: <element path="..." /> -->
</rslPaths>
<!-- Intrinsic Libraries -->
<intrinsics>
<!-- example: <element path="..." /> -->
</intrinsics>
<!-- Assets to embed into the output SWF -->
<library>
<!-- example: <asset path="..." id="..." update="..." glyphs="..." mode="..." place="..." sharepoint="..." /> -->
</library>
<!-- Class files to compile (other referenced classes will automatically be included) -->
<compileTargets>
<compile path="src\com\plupload\Plupload.as" />
</compileTargets>
<!-- Paths to exclude from the Project Explorer tree -->
<hiddenPaths>
<!-- example: <hidden path="..." /> -->
</hiddenPaths>
<!-- Executed before build -->
<preBuildCommand />
<!-- Executed after build -->
<postBuildCommand alwaysRun="False" />
<!-- Other project options -->
<options>
<option showHiddenPaths="False" />
<option testMovie="Default" />
</options>
</project>

View file

@ -1,21 +0,0 @@
#!/bin/sh
if [ -z "$FLEX_HOME" ]; then
FLEX_HOME=/opt/flex/flex
fi
export FLEX_HOME
$FLEX_HOME/bin/mxmlc \
-compiler.source-path src \
-compiler.optimize \
-compiler.use-resource-bundle-metadata \
-compiler.show-actionscript-warnings \
-compiler.show-binding-warnings \
-compiler.show-unused-type-selector-warnings \
-compiler.strict \
-compiler.accessible=false \
-use-network \
-static-link-runtime-shared-libraries \
-output ../../../js/plupload.flash.swf \
src/com/plupload/Plupload.as

View file

@ -1,291 +0,0 @@
/*
Copyright (c) 2008 Martin Raedlinger (mr@formatlos.de)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
package com.formatlos
{
import com.formatlos.events.BitmapDataUnlimitedEvent;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.DisplayObject;
import flash.display.IBitmapDrawable;
import flash.display.Loader;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.IEventDispatcher;
import flash.geom.ColorTransform;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
/**
* Dispatched when the BitmapData is ready
*
* @eventType com.formatlos.events.BitmapDataUnlimitedEvent
*/
[Event(name='COMPLETE', type='com.formatlos.events.BitmapDataUnlimitedEvent')]
/**
* Dispatched when the BitmapData can't be created due to memory issues.
* watch your system memory and/or System.totalMemory
*
* @eventType com.formatlos.events.BitmapDataUnlimitedEvent
*/
[Event(name='ERROR', type='com.formatlos.events.BitmapDataUnlimitedEvent')]
// ---------------------------------------------------------------------------
/**
* The BitmapDataUnlimited Class creates an empty gif image
*
* @author Martin Raedlinger
*
* @example
* The example shows how to use the BitmapDataUnlimited
* <div class="listing">
* <pre>
*
* var bdu:BitmapDataUnlimited = new BitmapDataUnlimited();
* bdu.addEventListener(BitmapDataUnlimitedEvent.COMPLETE, onBmpReady);
* bdu.create(5000, 5000, true);
*
* var hugeBitmapData : BitmapData;
*
* function onBmpReady(event : BitmapDataUnlimitedEvent) : void
* {
* hugeBitmapData = bdu.bitmapData;
*
* var rect : Rectangle = new Rectangle(10, 10, 10, 10);
*
* hugeBitmapData.fillRect(rect, 0xffff0000);
* addChild(new Bitmap(hugeBitmapData));
*
* trace("BitmapData: w=" + hugeBitmapData.width + " h=" + hugeBitmapData.height);
* }
*
* </pre>
* </div>
*
*/
public class BitmapDataUnlimited implements IEventDispatcher
{
// basically this value is 4096, but take 4000 to have some buffer
static private const DRAW_LIMIT : uint = 4000;
protected var _eventDispatcher : EventDispatcher;
private var _loader : Loader;
private var _gif : Gif;
private var _fillColor : uint;
private var _transparent : Boolean;
// created bitmapData
private var _bitmapData : BitmapData;
/**
* Returns the created BitmapData Object
*
* @return Huge BitmapData
*/
public function get bitmapData() : BitmapData
{
return _bitmapData;
}
/**
* Creates a new BitmapDataUnlimited object.
*/
public function BitmapDataUnlimited()
{
_eventDispatcher = new EventDispatcher(this);
}
/**
* Creates a huge BitmapData object.
*
* @param width The width of the huge BitmapData
* @param height The height of the huge BitmapData
* @param transparent transparent BitmapData or not
* @param fillColor Fill the BitmapData with color
*/
public function create(width_ : int, height_ : int, transparent_ : Boolean = true, fillColor_ : uint = 0xFFFFFF) : void
{
try
{
_bitmapData = new BitmapData(width_, height_, transparent_, fillColor_);
dispatchComplete();
}
catch(error : ArgumentError)
{
if(width_ <= 0 || height_ <= 0)
{
throw error;
}
else
{
_transparent = transparent_;
_fillColor = fillColor_;
_gif = new Gif(width_, height_, transparent_, fillColor_);
_loader = new Loader();
_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoaderComplete);
_loader.loadBytes(_gif.bytes);
}
}
}
/**
* Bypasses the 4096px limit in BitmapData.draw() and draws the source display object onto the bitmap image.
*
* @see http://blog.formatlos.de/2008/12/11/bitmapdatadraw-is-limited-to-4096px/
*
* @param source_ The display object or BitmapData object to draw to the BitmapData object. (The DisplayObject and BitmapData classes implement the IBitmapDrawable interface.)
* @param colorTransform_ A ColorTransform object that you use to adjust the color values of the bitmap. If no object is supplied, the bitmap image's colors are not transformed
* @param blendMode_ A string value, from the flash.display.BlendMode class, specifying the blend mode to be applied to the resulting bitmap.
* @param clipRect_ A Rectangle object that defines the area of the source object to draw. If you do not supply this value, no clipping occurs and the entire source object is drawn.
* @param smoothing_ A Boolean value that determines whether a BitmapData object is smoothed
*/
public function draw(source_ : IBitmapDrawable, matrix_ : Matrix = null, colorTransform_ : ColorTransform = null, blendMode_ : String = null, clipRect_:Rectangle = null, smoothing_ : Boolean = false) : void
{
var srcRect : Rectangle;
if (source_ is BitmapData) srcRect = (source_ as BitmapData).rect.clone();
else if (source_ is DisplayObject) srcRect = (source_ as DisplayObject).getBounds(source_ as DisplayObject);
if(srcRect)
{
var x : int = (clipRect_) ? clipRect_.x : 0;
var y : int = (clipRect_) ? clipRect_.y : 0;
var clipWidth : int = (clipRect_) ? clipRect_.right : _bitmapData.width;
var clipHeight : int = (clipRect_) ? clipRect_.bottom : _bitmapData.height;
var xMax : int = Math.min(srcRect.right, clipWidth);
var yMax : int = Math.min(srcRect.bottom, clipHeight);
var matrix : Matrix;
var chunk : BitmapData;
var clip : Rectangle = new Rectangle();
if(matrix_) {
xMax *= matrix_.a;
yMax *= matrix_.d;
}
while(x < xMax)
{
while(y < yMax)
{
matrix = new Matrix();
if(matrix_) {
matrix.a = matrix_.a;
matrix.d = matrix_.d;
}
matrix.translate(-x, -y);
clip.width = (xMax - x >= DRAW_LIMIT) ? DRAW_LIMIT : xMax - x;
clip.height = (yMax - y >= DRAW_LIMIT) ? DRAW_LIMIT : yMax - y ;
// use source
if(x == 0 && y == 0)
{
_bitmapData.draw(source_, matrix, colorTransform_, blendMode_, clip, smoothing_);
}
// copy to chunk first
else
{
if(!chunk) chunk = _bitmapData.clone();
chunk.fillRect(chunk.rect, (!_transparent) ? _fillColor : 0x00000000 );
chunk.draw(source_, matrix, colorTransform_, blendMode_, clip, smoothing_);
_bitmapData.copyPixels(chunk, chunk.rect, new Point(x, y), null, null, true);
}
y += DRAW_LIMIT;
}
x += DRAW_LIMIT;
y = 0;
}
if(chunk)
{
chunk.dispose();
chunk = null;
}
}
}
private function onLoaderComplete(event : Event) : void
{
var ok:Boolean = true;
try
{
_bitmapData = Bitmap(_loader.content).bitmapData.clone();
if(!_transparent) _bitmapData.fillRect(_bitmapData.rect, _fillColor);
}
catch(error : ArgumentError)
{
ok = false;
dispatchEvent(new BitmapDataUnlimitedEvent(BitmapDataUnlimitedEvent.ERROR));
}
_loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, onLoaderComplete);
_loader = null;
if(ok) dispatchComplete();
}
private function dispatchComplete() : void
{
dispatchEvent(new BitmapDataUnlimitedEvent(BitmapDataUnlimitedEvent.COMPLETE));
}
public function addEventListener(type : String, listener : Function, useCapture : Boolean = false, priority : int = 0, useWeakReference : Boolean = true) : void
{
_eventDispatcher.addEventListener(type, listener, useCapture, priority, useWeakReference);
}
public function dispatchEvent(event : Event) : Boolean
{
return _eventDispatcher.dispatchEvent(event);
}
public function hasEventListener(type : String) : Boolean
{
return _eventDispatcher.hasEventListener(type);
}
public function removeEventListener(type : String, listener : Function, useCapture : Boolean = false) : void
{
_eventDispatcher.removeEventListener(type, listener, useCapture);
}
public function willTrigger(type : String) : Boolean
{
return _eventDispatcher.willTrigger(type);
}
}
}

View file

@ -1,197 +0,0 @@
/*
Copyright (c) 2008 Martin Raedlinger (mr@formatlos.de)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
package com.formatlos
{
import flash.utils.ByteArray;
/**
* The Gif Class creates an empty gif image
*
* @author Martin Raedlinger
*/
public class Gif
{
private var _width : int;
private var _height : int;
private var _colorTable : ByteArray;
private var _colorTableSize : int = 7;
private var _transparent : Boolean;
private var _transparentIndex : int = 0;
private var _fillColor : uint;
// binary gif data
private var _binaryGif : ByteArray;
/**
* Returns the created binary gif data
*
* @return binary gif data
*/
public function get bytes() : ByteArray
{
return _binaryGif;
}
public function Gif(width_ : int, height_ : int, transparent_ : Boolean = false, fillColor_ : uint = 4.294967295E9)
{
_width = width_;
_height = height_;
_transparent = transparent_;
_fillColor = fillColor_;
initialize();
}
private function initialize() : void
{
_binaryGif = new ByteArray();
writeHeader();
writeLogicalScreenDescriptor();
writeColorTable();
writeGraphicControlExtensionBlock();
writeImageBlock();
writeTrailer();
}
private function writeHeader() : void
{
_binaryGif.writeUTFBytes("GIF89a");
}
private function writeLogicalScreenDescriptor() : void
{
// size
writeShort(_width);
writeShort(_height);
// Packed Fields
// bit 0: Global Color Table Flag (GCTF)
// bit 1..3: Color Resolution
// bit 4: Sort Flag to Global Color Table
// bit 5..7: Size of Global Color Table: 2^(1+n)
_binaryGif.writeByte((0x80 | 0x70 | 0x00 | _colorTableSize));
// Background Color Index
_binaryGif.writeByte(0);
// Pixel Aspect Ratio
_binaryGif.writeByte(0); //
}
private function writeColorTable() : void
{
_colorTable = new ByteArray();
//_colorTable[0] = 0xFF0000 >> 16;
//_colorTable[1] = 0x00FF00 >> 8;
//_colorTable[2] = 0x0000FF;
_colorTable[0] = _fillColor >> 16 & 0xFF;
_colorTable[1] = _fillColor >> 8 & 0xFF;
_colorTable[2] = _fillColor & 0xFF;
_binaryGif.writeBytes(_colorTable, 0, _colorTable.length);
var i : int = 0;
var n : int = (3 * 256) - _colorTable.length;
while(i < n)
{
_binaryGif.writeByte(0);
++i;
}
}
private function writeGraphicControlExtensionBlock() : void
{
// Extension Introducer
_binaryGif.writeByte(0x21);
// Graphic Control Label
_binaryGif.writeByte(0xf9);
// Block Size
_binaryGif.writeByte(4);
var transparent : int;
var dispose : int;
if (_transparent)
{
transparent = 1;
dispose = 2;
}
else
{
transparent = 0;
dispose = 0;
}
dispose <<= 2;
// Packed Fields
// bit 0..2: Reserved
// bit 3..5: Disposal Method
// bit 6: User Input Flag
// bit 7: Transparent Color Flag
_binaryGif.writeByte(0 | dispose | 0 | transparent);
// Delay Time
writeShort(0);
// Transparent Color Index
_binaryGif.writeByte(_transparentIndex);
// Block Terminator
_binaryGif.writeByte(0);
}
private function writeImageBlock() : void
{
//Image Separator
_binaryGif.writeByte(0x2c);
// Image Left Position
writeShort(0);
// image position x,y = 0,0
// Image Top Position
writeShort(0);
// Image Width
writeShort(_width);
// Image Height
writeShort(_height);
// Packed Fields
_binaryGif.writeByte(0);
}
private function writeTrailer() : void
{
_binaryGif.writeByte(0x3b);
}
private function writeShort(pValue : int) : void
{
_binaryGif.writeByte(pValue & 0xFF);
_binaryGif.writeByte((pValue >> 8) & 0xFF);
}
}
}

View file

@ -1 +0,0 @@
/* Copyright (c) 2008 Martin Raedlinger (mr@formatlos.de) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package com.formatlos.events { import flash.events.Event; /** * @author Martin Raedlinger */ public class BitmapDataUnlimitedEvent extends Event { public static const COMPLETE : String = "bitmapDataComplete"; public static const ERROR : String = "bitmapDataError"; public function BitmapDataUnlimitedEvent(type : String, bubbles : Boolean = false, cancelable : Boolean = false) { super(type, bubbles, cancelable); } override public function clone() : Event { return new BitmapDataUnlimitedEvent(type, bubbles, cancelable); } } }

View file

@ -1,84 +0,0 @@
/**
*
* Copyright 2011, Moxiecode Systems AB
* Released under GPL License.
*
* License: http://www.plupload.com/license
* Contributing: http://www.plupload.com/contributing
*/
package com.mxi {
import flash.utils.ByteArray;
import flash.utils.Endian;
public class BinaryReader extends ByteArray {
public function init(binData:ByteArray):void {
clear();
writeBytes(binData);
}
public function II(... args):* {
if (!args.length)
return endian == Endian.LITTLE_ENDIAN ? true : false;
else
endian = args[0] == true ? Endian.LITTLE_ENDIAN : Endian.BIG_ENDIAN;
}
public function SEGMENT(... args):ByteArray {
var seg:ByteArray = new ByteArray();
if (!args.length) {
position = 0;
readBytes(seg, 0, length);
} else if (typeof(args[1]) == 'number') {
position = args[0];
readBytes(seg, 0, args[1]);
} else {
position = args[0];
if (args[2] === true) {
writeBytes(args[1]);
} else {
readBytes(seg);
position = args[0];
writeBytes(args[1]);
writeBytes(seg);
}
}
return seg;
}
public function BYTE(idx:int):uint {
position = idx;
return readUnsignedByte();
}
public function SHORT(idx:int):uint {
position = idx;
return readUnsignedShort();
}
public function LONG(idx:int, ... args):* {
position = idx;
if (!args.length)
return readUnsignedInt();
else
writeUnsignedInt(args[0]);
}
public function SLONG(idx:uint):int {
position = idx;
return readInt();
}
public function STRING(idx:uint, size:uint):String {
position = idx;
return readUTFBytes(size);
}
}
}

View file

@ -1,401 +0,0 @@
/**
* Copyright 2011, Moxiecode Systems AB
* Released under GPL License.
*
* License: http://www.plupload.com/license
* Contributing: http://www.plupload.com/contributing
*/
package com.mxi.image {
import flash.events.EventDispatcher;
import flash.utils.ByteArray;
import com.mxi.BinaryReader;
public class ExifParser extends EventDispatcher {
private var TIFFHeader_offset:int = 10;
private var IFD0_offset:int, gpsIFD_offset:int, exifIFD_offset:int;
private var Tiff:Object, Exif:Object, Gps:Object;
private var app0:ByteArray, app1:ByteArray;
private var app0_offset:int, app0_length:int, app1_offset:int, app1_length:int;
private var data:BinaryReader = new BinaryReader();
private var tiffTags:Object = {
0x0112: 'Orientation',
0x8769: 'ExifIFDPointer',
0x8825: 'GPSInfoIFDPointer'
},
exifTags:Object = {
0x9000: 'ExifVersion',
0xA001: 'ColorSpace',
0xA002: 'PixelXDimension',
0xA003: 'PixelYDimension',
0x9003: 'DateTimeOriginal',
0x829A: 'ExposureTime',
0x829D: 'FNumber',
0x8827: 'ISOSpeedRatings',
0x9201: 'ShutterSpeedValue',
0x9202: 'ApertureValue' ,
0x9207: 'MeteringMode',
0x9208: 'LightSource',
0x9209: 'Flash',
0xA402: 'ExposureMode',
0xA403: 'WhiteBalance',
0xA406: 'SceneCaptureType',
0xA404: 'DigitalZoomRatio',
0xA408: 'Contrast',
0xA409: 'Saturation',
0xA40A: 'Sharpness'
},
gpsTags:Object = {
0x0000: 'GPSVersionID',
0x0001: 'GPSLatitudeRef',
0x0002: 'GPSLatitude',
0x0003: 'GPSLongitudeRef',
0x0004: 'GPSLongitude'
},
tagDescs:Object = {
'ColorSpace': {
1: 'sRGB',
0: 'Uncalibrated'
},
'MeteringMode': {
0: 'Unknown',
1: 'Average',
2: 'CenterWeightedAverage',
3: 'Spot',
4: 'MultiSpot',
5: 'Pattern',
6: 'Partial',
255: 'Other'
},
'LightSource': {
1: 'Daylight',
2: 'Fliorescent',
3: 'Tungsten',
4: 'Flash',
9: 'Fine weather',
10: 'Cloudy weather',
11: 'Shade',
12: 'Daylight fluorescent (D 5700 - 7100K)',
13: 'Day white fluorescent (N 4600 -5400K)',
14: 'Cool white fluorescent (W 3900 - 4500K)',
15: 'White fluorescent (WW 3200 - 3700K)',
17: 'Standard light A',
18: 'Standard light B',
19: 'Standard light C',
20: 'D55',
21: 'D65',
22: 'D75',
23: 'D50',
24: 'ISO studio tungsten',
255: 'Other'
},
'Flash': {
0x0000: 'Flash did not fire.',
0x0001: 'Flash fired.',
0x0005: 'Strobe return light not detected.',
0x0007: 'Strobe return light detected.',
0x0009: 'Flash fired, compulsory flash mode',
0x000D: 'Flash fired, compulsory flash mode, return light not detected',
0x000F: 'Flash fired, compulsory flash mode, return light detected',
0x0010: 'Flash did not fire, compulsory flash mode',
0x0018: 'Flash did not fire, auto mode',
0x0019: 'Flash fired, auto mode',
0x001D: 'Flash fired, auto mode, return light not detected',
0x001F: 'Flash fired, auto mode, return light detected',
0x0020: 'No flash function',
0x0041: 'Flash fired, red-eye reduction mode',
0x0045: 'Flash fired, red-eye reduction mode, return light not detected',
0x0047: 'Flash fired, red-eye reduction mode, return light detected',
0x0049: 'Flash fired, compulsory flash mode, red-eye reduction mode',
0x004D: 'Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected',
0x004F: 'Flash fired, compulsory flash mode, red-eye reduction mode, return light detected',
0x0059: 'Flash fired, auto mode, red-eye reduction mode',
0x005D: 'Flash fired, auto mode, return light not detected, red-eye reduction mode',
0x005F: 'Flash fired, auto mode, return light detected, red-eye reduction mode'
},
'ExposureMode': {
0: 'Auto exposure',
1: 'Manual exposure',
2: 'Auto bracket'
},
'WhiteBalance': {
0: 'Auto white balance',
1: 'Manual white balance'
},
'SceneCaptureType': {
0: 'Standard',
1: 'Landscape',
2: 'Portrait',
3: 'Night scene'
},
'Contrast': {
0: 'Normal',
1: 'Soft',
2: 'Hard'
},
'Saturation': {
0: 'Normal',
1: 'Low saturation',
2: 'High saturation'
},
'Sharpness': {
0: 'Normal',
1: 'Soft',
2: 'Hard'
},
// GPS related
'GPSLatitudeRef': {
N: 'North latitude',
S: 'South latitude'
},
'GPSLongitudeRef': {
E: 'East longitude',
W: 'West longitude'
}
};
public function init(jpegData:ByteArray):Boolean {
TIFFHeader_offset = 10;
Tiff = Exif = Gps = new Object();
app0 = app1 = new ByteArray();
app0_offset = app0_length = app1_offset = app1_length = IFD0_offset = exifIFD_offset = gpsIFD_offset = -1;
data.init(jpegData);
if (!isJPEG()) return false;
switch (data.SHORT(2)) {
// app0
case 0xFFE0:
app0_offset = 2;
app0_length = data.SHORT(4) + 2;
// check if app1 follows
if (data.SHORT(app0_length) == 0xFFE1) {
app1_offset = app0_length;
app1_length = data.SHORT(app0_length + 2) + 2;
}
break;
// app1
case 0xFFE1:
app1_offset = 2;
app1_length = data.SHORT(4) + 2;
break;
default: return false;
}
(app1_length !== -1 && getIFDOffsets());
return true;
}
public function APP1(args:Object = null):ByteArray {
if (app1_offset === -1 && app1_length === -1)
return new ByteArray();
app1 = data.SEGMENT(app1_offset, app1_length, false);
// if requested alter width/height tags in app1
(args !== null && args.hasOwnProperty('width') && args.hasOwnProperty('height') && setNewWxH(args.width, args.height));
return app1;
}
public function EXIF():Object {
// populate EXIF hash
if (exifIFD_offset === -1) return {};
Exif = extractTags(exifIFD_offset, exifTags);
// fix formatting of some tags
if (Exif.hasOwnProperty('ExifVersion'))
Exif.ExifVersion = String.fromCharCode(
Exif.ExifVersion[0],
Exif.ExifVersion[1],
Exif.ExifVersion[2],
Exif.ExifVersion[3]
);
return Exif;
}
public function GPS():Object {
if (gpsIFD_offset === -1) return {};
Gps = extractTags(gpsIFD_offset, gpsTags);
if (Gps.hasOwnProperty('GPSVersionID'))
Gps.GPSVersionID = Gps.GPSVersionID.join('.');
return Gps;
}
public function setAPP1(data_app1:ByteArray):Boolean {
if (app1_offset !== -1)
return false;
data.SEGMENT((app0_offset !== -1 ? app0_offset + app0_length : 2), data_app1);
return true;
}
public function getBinary():ByteArray {
return data.SEGMENT();
}
private function isJPEG():Boolean {
return data.SHORT(0) == 0xFFD8;
}
private function getIFDOffsets():Boolean {
// fix TIFF header offset
TIFFHeader_offset+= app1_offset;
var idx:int = app1_offset + 4;
// check if that's EXIF we are reading
if (data.STRING(idx, 4).toUpperCase() != 'EXIF' || data.SHORT(idx+=4) != 0) return false;
// set read order of multi-byte data
data.II(data.SHORT(idx+=2) == 0x4949);
// check if always present bytes are indeed present
if (data.SHORT(idx+=2) != 0x002A) return false;
IFD0_offset = TIFFHeader_offset + data.LONG(idx+=2);
Tiff = extractTags(IFD0_offset, tiffTags);
exifIFD_offset = (Tiff.hasOwnProperty('ExifIFDPointer') ?
TIFFHeader_offset + Tiff.ExifIFDPointer : null);
gpsIFD_offset = (Tiff.hasOwnProperty('GPSInfoIFDPointer') ?
TIFFHeader_offset + Tiff.GPSInfoIFDPointer : null);
return true;
}
private function extractTags(IFD_offset:int, tags2extract:Object):Object {
var length:int = data.SHORT(IFD_offset),
tag:int, tagName:String, type:int, count:int, tagOffset:int, offset:int, values:Array, tags:Object = {},
ii:uint;
for (var i:uint = 0; i < length; i++) {
// set binary reader pointer to beginning of the next tag
offset = tagOffset = IFD_offset + 12*i + 2;
tag = data.SHORT(offset);
if (!tags2extract.hasOwnProperty(tag)) continue; // not the tag we requested
tagName = tags2extract[tag];
type = data.SHORT(offset+=2);
count = data.LONG(offset+=2);
offset +=4;
values = new Array();
switch (type) {
case 1: // BYTE
case 7: // UNDEFINED
if (count > 4) offset = data.LONG(offset) + TIFFHeader_offset;
for (ii = 0; ii < count; ii++)
values[ii] = data.BYTE(offset + ii);
break;
case 2: // STRING
if (count > 4) offset = data.LONG(offset) + TIFFHeader_offset;
tags[tagName] = data.STRING(offset, count - 1);
continue;
case 3: // SHORT
if (count > 2) offset = data.LONG(offset) + TIFFHeader_offset;
for (ii = 0; ii < count; ii++)
values[ii] = data.SHORT(offset + ii*2);
break;
case 4: // LONG
if (count > 1) offset = data.LONG(offset) + TIFFHeader_offset;
for (ii = 0; ii < count; ii++)
values[ii] = data.LONG(offset + ii*4);
break;
case 5: // RATIONAL
offset = data.LONG(offset) + TIFFHeader_offset;
for (ii = 0; ii < count; ii++)
values[ii] = data.LONG(offset + ii*4) / data.LONG(offset + ii*4 + 4);
break;
case 9: // SLONG
offset = data.LONG(offset) + TIFFHeader_offset;
for (ii = 0; ii < count; ii++)
values[ii] = data.SLONG(offset + ii*4);
break;
case 10: // SRATIONAL
offset = data.LONG(offset) + TIFFHeader_offset;
for (ii = 0; ii < count; ii++)
values[ii] = data.SLONG(offset + ii*4) / data.SLONG(offset + ii*4 + 4);
break;
default: continue;
}
if (tagDescs.hasOwnProperty(tagName) && typeof(values[0]) != 'object')
tags[tagName] = tagDescs[tagName][values[0]];
else
tags[tagName] = (count == 1 ? values[0] : values);
}
return tags;
}
private function setNewWxH(width:int, height:int):Boolean {
var w_offset:uint, h_offset:uint,
offset:uint = exifIFD_offset !== -1 ? exifIFD_offset - app1_offset : -1,
data_app1:BinaryReader = new BinaryReader();
data_app1.init(app1);
data_app1.II(data.II());
if (offset === -1) return false;
// find offset for PixelXDimension tag
w_offset = findTagValueOffset(data_app1, 0xA002, offset);
if (w_offset !== -1)
data_app1.LONG(w_offset, width);
// find offset for PixelYDimension tag
h_offset = findTagValueOffset(data_app1, 0xA003, offset);
if (h_offset !== -1)
data_app1.LONG(h_offset, height);
app1 = data_app1.SEGMENT();
return true;
}
private function findTagValueOffset(data_app1:BinaryReader, tegHex:int, offset:int):int {
var length:uint = data_app1.SHORT(offset),
tagOffset:uint;
for (var i:uint = 0; i < length; i++) {
tagOffset = offset + 12*i + 2;
if (data_app1.SHORT(tagOffset) == tegHex)
return tagOffset + 8;
}
return -1;
}
}
}

View file

@ -1,175 +0,0 @@
/**
* Copyright 2011, Moxiecode Systems AB
* Released under GPL License.
*
* License: http://www.plupload.com/license
* Contributing: http://www.plupload.com/contributing
*/
package com.mxi.image
{
import com.formatlos.BitmapDataUnlimited;
import com.formatlos.events.BitmapDataUnlimitedEvent;
import flash.display.BitmapData;
import flash.display.IBitmapDrawable;
import flash.display.Loader;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.geom.Matrix;
import flash.utils.ByteArray;
import mx.graphics.codec.JPEGEncoder;
import mx.graphics.codec.PNGEncoder;
import flash.external.ExternalInterface;
import com.mxi.image.events.ImageEvent;
import flash.system.System;
public class Image extends EventDispatcher
{
private var _source:ByteArray;
private var _info:Object = null;
private var _width:Number;
private var _height:Number;
private var _quality:Number;
public static const MAX_WIDTH:uint = 8191;
public static const MAX_HEIGHT:uint = 8191;
public var imageData:ByteArray;
public function Image(source:ByteArray)
{
_source = source;
super();
}
public function scale(width:Number, height:Number, quality:Number = 90) : void
{
var loader:Loader, info:Object, scale:Number;
info = _getImageInfo();
if (!info) {
dispatchEvent(new ImageEvent(ImageEvent.ERROR, ImageEvent.WRONG_FORMAT));
return;
}
if (info.width > Image.MAX_WIDTH || info.height > Image.MAX_HEIGHT) {
dispatchEvent(new ImageEvent(ImageEvent.ERROR, ImageEvent.OUT_OF_DIMENSIONS));
return;
}
// we might not need to scale
scale = Math.min(width / info.width, height / info.height);
if (scale >= 1) {
dispatchEvent(new ImageEvent(ImageEvent.COMPLETE));
return;
}
_width = width;
_height = height;
_quality = quality;
// scale
loader = new Loader;
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onBitmapDataReady);
loader.loadBytes(_source);
}
protected function _getImageInfo() : Object
{
if (_info) return _info;
if (JPEG.test(_source)) {
var jpeg:JPEG = new JPEG(_source);
_info = jpeg.info();
if (_info) {
_info['type'] = 'JPEG';
}
}
else if (PNG.test(_source)) {
var png:PNG = new PNG(_source);
_info = png.info();
if (_info) {
_info['type'] = 'PNG';
}
}
return _info;
}
protected function onBitmapDataReady(e:Event) : void
{
var bitmapSource:IBitmapDrawable, output:BitmapData, width:Number, height:Number, scale:Number;
bitmapSource = e.target.content as IBitmapDrawable;
width = _info.width;
height = _info.height;
// re-calculate width/height proportionally
scale = Math.min(_width / width, _height / height);
_width = Math.round(width * scale);
_height = Math.round(height * scale);
var prepareBitmap:Function = function(width:Number, height:Number, callback:Function) : void
{
var bitmapCreator:BitmapDataUnlimited = new BitmapDataUnlimited;
bitmapCreator.addEventListener(BitmapDataUnlimitedEvent.COMPLETE, function(e:BitmapDataUnlimitedEvent) : void
{
callback(bitmapCreator.bitmapData);
});
bitmapCreator.addEventListener(BitmapDataUnlimitedEvent.ERROR, function(e:BitmapDataUnlimitedEvent) : void
{
dispatchEvent(new ImageEvent(ImageEvent.ERROR, ImageEvent.OUT_OF_MEMORY));
});
bitmapCreator.create(width, height, true);
};
var outputScale:Function = function(width:Number, height:Number) : void
{
prepareBitmap(width, height, function(bitmapData:BitmapData) : void
{
var scale:Number, matrix:Matrix;
scale = Math.min(width / output.width, height / output.height);
matrix = new Matrix;
matrix.scale(scale, scale);
bitmapData.draw(output, matrix, null, null, null, true);
output.dispose();
output = bitmapData;
});
};
prepareBitmap(width, height, function(bitmapData:BitmapData) : void
{
output = bitmapData;
output.draw(bitmapSource, null, null, null, null, true);
while (output.width / 2 > _width) {
outputScale(output.width / 2, output.height / 2); // modifies output internally
}
// finalize
outputScale(_width, _height);
// encode
if (_info.type == "JPEG")
imageData = new JPEGEncoder(_quality).encode(output);
else
imageData = new PNGEncoder().encode(output);
dispatchEvent(new ImageEvent(ImageEvent.COMPLETE));
});
}
}
}

Some files were not shown because too many files have changed in this diff Show more