跟 UMU 一起玩 OpenWRT(高级篇2):不拆机刷不死 U-Boot

在上一篇《跟 UMU 一起玩 OpenWRT(高级篇1):编译不死 U-Boot》介绍了如何编译不死 U-Boot,但是不死 U-Boot 的作者只介绍了用 TTL 线刷方法,UMU 可不想拆机,毕竟拆机感觉并不好……

第一个思路是刷上 DD-WRT 固件,但是找了一下 DD-WRT 木有支持 DIR-505,只好继续蛋疼地编译 OpenWRT。

第一遍在虚拟机从 12:20 编译到 23:56,花费将近 12 小时……刚开始时,有一个下载过程,不断失败,想想是因为公司的网络太烂,于是把下载脚本改了一下:

<openwrt-svn-dir>/trunk/scripts/download.pl 中的 wget -t5 --timeout=20 --no-check-certificate 改为 wget -t5 --timeout=120 --no-check-certificate

第二天来,刷上,没问题,于是开始改代码去掉 U-Boot 写保护,参考这篇《Openwrt 中刷写 uboot ARThttp://see.sl088.com/wiki/Openwrt_%E4%B8%AD%E5%88%B7%E5%86%99_uboot_art,但结果很不幸,型号不同嘛!

接下来,凭自己的编程水平了,尝试改 <openwrt-svn-dir>/trunk/target/linux/ar71xx/files/arch/mips/ath79/mach-dir-505-a1.c,加入下面两个结构体:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
static struct mtd_partition dir505_partitions[] = {
{
.name = "u-boot",
.offset = 0,
.size = 0x010000,
.mask_flags = 0,
}, {
.name = "art",
.offset = 0x010000,
.size = 0x010000,
}, {
.name = "mac",
.offset = 0x020000,
.size = 0x010000,
}, {
.name = "nvram",
.offset = 0x030000,
.size = 0x010000,
}, {
.name = "language",
.offset = 0x040000,
.size = 0x040000,
}, {
.name = "firmware",
.offset = 0x080000,
.size = 0x780000,
.mask_flags = 0,
}
};

static struct flash_platform_data dir505_flash_data = {
.parts = dir505_partitions,
.nr_parts = ARRAY_SIZE(dir505_partitions),
};

并将 dir_505_a1_setup 函数里的 ath79_register_m25p80(NULL); 改为 ath79_register_m25p80(&dir505_flash_data);

测试还是无效……看来必须在源头上使 MTD_WRITEABLE 无效掉,grep -r MTD_WRITEABLE <openwrt-svn-dir>/trunk/build_dir/target-mips_34kc_uClibc-0.9.33.2/linux-ar71xx_generic/linux-3.10.36/drivers/mtd,看到几处关键的地方:

1
if (!(ubi->mtd->flags & MTD_WRITEABLE)) {

1
if (!mtd->_write || !(mtd->flags & MTD_WRITEABLE))

主要在 mtd_erase、mtd_write 等函数,很明显,C 语言不管在什么平台都是很好懂,看几眼就搞定了,原理是使 MTD_WRITEABLE 这个标志无用掉,您可以设置,但是我把判断这个标志的代码全干掉了,设了也是白设!

最后编译好的 openwrt-ar71xx-generic-dir-505-a1-squashfs-sysupgrade.bin,用 sysupgrade 刷一下,reboot 后再用 mtd 刷不死 U-Boot,一切顺利,成功刷上不死 U-Boot!

跟 UMU 一起玩 OpenWRT(高级篇1):编译不死 U-Boot

UMU 2010 年初就玩 OpenWRT/DD-WRT 了,蛋似编译东西还是初学者,本文纯属蛋疼的过程,欢迎批评教育,谢谢……

首先到 https://github.com/pepe2k/u-boot_mod 看明白作者的说明。这里简单说一下原理:固件(firmware)刷坏,但 U-Boot 没坏,这是半砖,可以用 TTL 线连路由器,通过 U-Boot 的功能刷好 firmware。如果两者都坏了,叫全砖,只能把 Flash 拆下来,用编程器刷好 U-Boot 和 firmware。不死 U-Boot 就是修改了 U-Boot 的实现,使我们可以用 RJ-45 网线来救砖,省去拆机搭 TTL 线的麻烦。

本质上说,这东西并非真的不死,只要 U-Boot 被刷坏,还是会死,不过几率不大,因为 OpenWRT 官方发行的 ROM 全都是保护 U-Boot 区域的,根据 UMU 的经验,只有三个情况会不小心或故意刷坏:

  1. 从原厂固件刷不良固件;
  2. 在 DD-WRT 下搞破坏(DD-WRT 没有保护 U-Boot);
  3. 自制固件去掉 U-Boot 写保护后搞破坏……

如果您真的这么蛋疼,还是准备编程器吧,只要是软件问题,在编程器面前没有砖的概念。(JTAG 也是救砖神器,但不是每台路由器都有,比如 DIR-505 就没有!)

由于 UMU 是 Windows 程序员,平时没有安装 Linux 桌面的习惯,蛋似由于做快游项目,买了不少服务器,都是 CentOS,所以第一步就是在 CentOS 上尝试编译,后来,您们懂的,爆出各种 213 码!服务器系统还是不适合开发!

不得已就在 Hyper-V Server 2012 上安装了 Ubuntu 12.04.1-desktop-i386,本来是想安装 x64 版本的,但又怕这些嵌入式的东西对 x64 可能支持不够好,算了,不要装 13 了。

接下来是选择编译环境了,按照 UMU 对 OpenWRT 的好感,明显是选择 OpenWrt Toolchain for AR71xx MIPS,然后开始编译,哗哗哗,编译好了……最后编译出来的 bin 却是 64KB+110B,尼玛,这 size 超标了,刷进去不是不死,是立刻死!

试验 Sourcery CodeBench Lite Edition for MIPS GNU/Linux 可行。推测作者其实并没有用 OpenWrt Toolchain 编译过,而是用 Sourcery CodeBench,所以……为了节省时间,还是用后者吧!吐槽一下,这是商业软件,虽然有免费的 Lite 版本……

make dlink_dir505 一下,顺利编译出来,UMU 还小修改了一下 Web 界面,加入了自己的特色,不过要提醒一下,不要加太多,会爆……只有 64KB 的空间!

卸载 LSP 并重启系统依然有服务加载它

发现问题,2012-12-11 18:16:00

  快游(网游加速器)包含一个 LSP,属于加速核心组件,在测试 LSP 期间,发现一个奇怪的现象:反注册它,并 netsh winsock reset 加重启好几次……依然有程序加载它。用 Process Explorer 查看是:IpOverUsbSvc.exe 和 daemonu.exe。把 LSP 的 DLL 文件删掉,再重启,可以消灭这个奇怪的现象。但后来想重现这个怪现象时,却无法重现。

重现和解决问题,2012-12-25 15:38:00

  问题自然重现,继续研究。这两个进程对应的服务名是:IpOverUsbSvc 和 nvUpdatusService。手动重启这两个服务后,即不再加载 LSP。推理:这两个服务很可能每次重启机器时都没有正常关闭,系统提供了某种机制让他们在下一次重启后快速恢复了运行现场(保留了有 LSP 注册时的环境)。

分析问题,2013-03-26 23:24:30

  时隔三个月,偶然看到介绍”混合式关机”的文章,恍然大悟,原来是这货引发的八哥!

在安装 Win8 后,很多人都体验到了其开关机惊人的速度,尤其是开机速度,相比 Win7 之下,它提升的不止是一点半点。在某些超极本和配备了 SSD 的机器上,其开关机速度可以在数秒以内。例如 Surface Pro,其实测系统引导速度为2秒,从启动到自动登录到开始屏幕只要6秒。

究竟是什么技术提升了 Win8 的开关机速度呢?如果要用最简单的一句话概括,那应该是”系统会话休眠”,或者更简单的,”混合式关机”。

在 以往的 Windows OS 中,典型的关机顺序为:

  1. 单击”关机”。

  2. Windows 广播运行应用程序关机信息,让应用程序可以保存数据和设置。应用程序也可以要求一些额外的时间以结束其当前工作。

  3. Windows 为每个登录用户关闭用户会话。

  4. Windows 向服务发送关机信息,通知已开始关机,接着关闭服务。如果服务未响应,系统将强制关闭。

  5. Windows 向设备广播信息,示意设备进行关闭。

  6. Windows 关闭系统会话(也称为”会话 0”)。

  7. Windows 刷新系统驱动器待决数据,以确保完全保存。

  8. Windows 通过 ACPI 界面向系统发送信号以给计算机断电。

看着以上的典型关机步骤,你是不是也有想到一些步骤对应的屏幕上的 UI 表现呢~

再来看看 Windows 8 采用的混合式关机主要步骤:

  1. 单击”关机”。

  2. Windows 广播运行应用程序关机信息,让应用程序可以保存数据和设置。应用程序也可以要求取得一些额外的时间以结束其当前工作。

  3. Windows 为每个登录用户关闭用户会话。

  4. 系统会话休眠,并掉电。

可见,Windows 8 只关闭用户会话而不像以前那样完全关闭计算机。此时, Windows 不再等待并结束系统服务和关闭会话 0,而是让其进入休眠。这种关闭用户会话+休眠系统服务和系统会话的做法,被称为”混合式关机”,也就不难理解了。

或者说得通俗点,就好比你之前打扫卫生时,需要先组装专业的拖布,组装好了以后,才能开始打扫卫生。而现在,你可以拿起拖布直接开始打扫,因为你上次打扫完之后,并没有将拖布这一工具像以往那样拆卸下来收好。

开机在结构上是关机的逆过程,所以有了混合式关机,开机自然也就快了。但是,除了 RAID 卡外,一般硬盘的读取速度会比写入速度略快,加上关机的时候,系统会通知并等待应用程序退出,所以从感官上,开机过程会比关机过程显得要快一些。

枚举物理网卡

  其实目的是获取靠谱的 MAC 地址,但这个任务真蛋疼!不信您看看搜索出来的乐射……

  神马 GetAdaptersInfo、GetIfEntry、GetAdaptersAddresses、NetWkstaTransportEnum,还有读取注册表 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkCards。这些都会枚举到虚拟网卡,给您举个例子“VirtualBox Host-Only Ethernet Adapter”,读取神马 NetCfgInstanceId、MediaSubType,都不靠谱,没有平台移植性!

  用 Setup API 枚举 Interface,匹配 PCI 和 USB 类型是比较靠谱的。

  蛋似,虚拟机的网卡也是虚拟的,为了方便在虚拟机测试,您要注意放开一些特例……很抱歉,领导说代码要保密,自己搜吧,关键字:SetupDiGetDeviceInterfaceDetail、OID_802_3_PERMANENT_ADDRESS。

  给个蛋碎的例子:\\.\pci#ven_10ec&dev_8168&subsys_050e1028&rev_06#4&224db6dd&0&00e5#{ad498944-762f-11d0-8dcb-00c04fc3358c}\{4cc0ea76-88b7-40e1-8b4b-6339f8dd49bf} 可以简称为 \\.\{4cc0ea76-88b7-40e1-8b4b-6339f8dd49bf} 或者 \\.\Global\{4cc0ea76-88b7-40e1-8b4b-6339f8dd49bf}

拯救 TL-WR941N V4.1 路由器

死因:在官方 ROM 上 刷不了 Tomato,试着刷了 DD-WRT 后,再刷 Tomato,结果刷完 213 了……

TTL 线拯救,网络是强大的,关键字:WR941N 短路 C278 电容

本文只为发几张图,如果有人不幸和 UMU 一样壮烈地撸死了这款路由器,可以参考之。

TL-WR941N V4.1

用树莓派 + USB 无线网卡做了一个蛋疼的 AP Client

需求

两个困境:

  • 有个只有 RJ45 接口的旧设备要上网,它的位置离路由器很远,家里的网线不够长……

  • UMU 买了一个支持 AP Client 的无线路由器(TP-Link TL-WR800N)每次把这个 AP Client 断电时,提供网络的主路由器都会被这个 AP Client 搞死掉,原因未知……

还没有树莓派的时候,UMU 用笔记本上的 Windows 的 ICS 功能给它提供网络,当然这方法很不好,于是有了现在的方案。

解决

仔细查看了树莓派支持的 USB WiFi Adapters 列表,挑选了 TP-LINK TL-WN823N(RT8192CU 芯片),这个在 Raspbian 上是 Work out-of-box。Mercury 150Mbps MW150U(Realtek RTL8188CU 芯片)也可以。

硬件准备好后,第一步,配置 Wifi,连上主路由器,假定,此步将 wlan0 的 IP 配置为 192.168.1.2,/etc/network/interfaces 的内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
auto lo

iface lo inet loopback
iface eth0 inet static
address 192.168.24.51
netmask 255.255.255.0

auto wlan0
iface wlan0 inet static
address 192.168.1.2
netmask 255.255.255.0
gateway 192.168.1.1
wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf

iface default inet dhcp

192.168.24.51 这个 IP 可以改为别的,UMU 习惯用这个当网关地址。/etc/wpa_supplicant/wpa_supplicant.conf 的内容这里就忽略了,参考 http://elinux.org/RPi_Peripherals#Wireless:_TP-Link_TL-WN722N_USB_wireless_adapter_.28Debian_6.29。设置完,ifdown wlan0ifup wlan0,看看 USB 无线网卡的指示灯应该闪起来了……

第二步,配置 RJ45 网口的 NAT。首先,修改 /etc/sysctl.conf,增加以下两行:

1
2
net.ipv4.ip_forward=1
net.ipv4.conf.all.accept_source_route = 1

运行 echo 1 > /proc/sys/net/ipv4/ip_forwardiptables -t nat -A POSTROUTING -s 192.168.24.0/24 -o wlan0 -j SNAT --to 192.168.1.2,并将这条命令写到 /etc/rc.local 中的 exit 前。

最后,reboot 一下试试。可以用网线把 PC 和树莓派连起来,PC 的网卡设为 24 段地址,网关 192.168.24.51,试一下 PC 通过树莓派的网口上网吧!

图像格式转换之 Jpeg2Jxr

为什么转?因为 JXR 格式在同等质量的情况下,存储空间比 JPEG 节约了 45-50%。

之前在《从 Windows 8 新功能推理某产品的八哥》提到过现在手机上的省流量 App,其原理就是压缩图片,但为了提高效果,这个压缩基本都是有损的,流量减少了,但是图片质量下降了,有的下降可以忍受,有的则令人发指!比如,长微博,文字转图片,这种图片线条分明,相邻像素值对比可能很大(黑白分明),这类图片采用高压缩比的 JPEG 压缩后,图片质量往往很差。

再举个例子:QR 码图片,您可以做一下试验,为了说明 JPEG 不适合存储线条型图片,哥采用一张蛋疼的 1290*1290 像素的 QR 码图片,保存为 JPEG 大小是 4.76MB,但保存为 PNG 格式时只有 52.4KB,请注意单位,前者是后者大小的将近 100 倍!!

大家可能比较少关注 WP,也许您没听过 DataSense,简单地说,它就是微软做的节省流量的 App。号称可以节约 45% 的流量,这么大的压缩率,除了优化 HTML 相关的文本之外,对图片的压缩肯定是必须的!推测 DataSense 可能使用了 JPEG XR 格式来转化其他格式的图片。

JPEG XR 虽然已经成为一种标准,但目前依然只有微软支持,所以,如果您想把这个技术应用到 iOS、Android 的节省流量 App 中,那很抱歉,此路暂时还不通。

根据实测,IE9@PC、IE10@PC、IE10@WP8 都是支持 JXR 格式的。下面是用 C++/CLI 写的很简单的一个格式转化程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
using namespace System;
using namespace System::IO;
using namespace System::Windows::Media;
using namespace System::Windows::Media::Imaging;

bool ConvertToJxr(System::String^ source_name)
{

//try {
Stream^ stream = gcnew FileStream(source_name, FileMode::Open, FileAccess::Read, FileShare::Read);
BitmapDecoder^ jpeg_decoder = BitmapDecoder::Create(stream, BitmapCreateOptions::PreservePixelFormat, BitmapCacheOption::None);
//JpegBitmapDecoder^ jpeg_decoder = gcnew JpegBitmapDecoder(gcnew Uri(source_name, UriKind::RelativeOrAbsolute), BitmapCreateOptions::PreservePixelFormat, BitmapCacheOption::None);
//Console::WriteLine(L"Author: `{0}'", jpeg_decoder->Metadata->Title);
FileStream^ jxr_file_stream = gcnew FileStream(source_name + L".jxr", FileMode::Create);
WmpBitmapEncoder^ jxr_encoder = gcnew WmpBitmapEncoder;
//BitmapMetadata^ metadata = gcnew BitmapMetadata(L"wmphoto");

for each (BitmapFrame ^ frame in jpeg_decoder->Frames) {
jxr_encoder->Frames->Add(BitmapFrame::Create(frame, jpeg_decoder->Thumbnail, (BitmapMetadata^)frame->Metadata, jpeg_decoder->ColorContexts));
}
//jxr_encoder->Metadata = metadata;
jxr_encoder->Save(jxr_file_stream);
//} catch (...) {
// return false;
//}
return true;
}

int main(array<System::String ^> ^args)
{

for each (auto arg in args) {
if (File::Exists(arg)) {
if (ConvertToJxr(arg)) {
Console::WriteLine(L"Converted: `{0}'", arg);
}
} else {
Console::WriteLine(L"NOT Exists: `{0}'", arg);
}
}
return 0;
}

文末是一些搜索到的关于 JPEG XR 的资料,可供参考:

http://jpeg.org/newsrel26.html

JPEG XR (ISO/IEC 29199-2) is now an International Standard and also an ITU-T Recommendation (T.832).

JPEG XR(旧称 HD Photo 及 Windows Media Photo)是一种连续色调静止图像压缩算法和文件格式,由Microsoft开发,属于Windows Media家族的一部分。它支持有损数据压缩以及无损数据压缩,并且是微软的XPS文档的首选图像格式。目前支持的软件包括.NET Framework(3.0 or newer),Windows Vista/Windows 7、Internet Explorer 9,Flashplayer 11等。

JPEG XR(微软HD Photo格式)2009 年,成为 ITU-T 推荐的国际标准(ISO/IEC 29199-2)。JPEG XR 的标准化确保数码相机、打印机、显示器和软件公司能够在开发其新产品的时候兼容互通。其核心技术由微软核心媒体开发团队开发完成,针对当前和将来的数字图像发展需求以提供了许多新的优势和特点。

在 Vista 操作系统中已经支持了这种新的文件格式,JPEG XR 相比其它技术更有优势,其中包括更好的压缩技术,以一半的文件大小保存与 JPEG 相同质量的图像,或以相同大小的文件保存质量相当于 JPEG 两倍的图像。JPEG 组织还对微软开放与 JPEG XR 相关的专利的决策表示了赞扬,称微软免许可费政策将有助于JPEG推动 JPEG XR 普及,有助于确保它能够被更多的用户所采用。JPEG 组织还鼓励其它公司向微软学习。

从 Windows 8 新功能推理马头流量的八哥

  Windows 8 确实是个不错的系统,DP、CP、RC、RTM,UMU 一路追过来。

  在开始讲故事之前,要先介绍一下马头流量,http://www.matocloud.com/,同类产品:上网快鸟、飞速流量、瓦力流量、彩虹流量……当然,这些都是设设 APN 而已,马头的 Android 版本有更高深的技术。想了解更多,请研究一下 EnoVPN、VPN Service。

  再来是流量压缩原理简介:主要是压缩图片。APN 就是一个 HTTP 代理,只不过这个代理有点不标准,会将原图压缩后交给用户,用户下载的是一张小图,自然就省流量。但这是有副作用的,有的图片必须是有损压缩才会变小,所以必然会降低图片质量。知道这个原理后,可能会有人会纠结了……至于您用不用,就看您在图片质量和流量之间的取舍了。

  故事开始了!UMU 用 HTC Titan 拍过不少图片,当然其中不少是横屏拍的。这个手机有重力感应功能,拍的照片会带 Orientation 信息,这是 Exif 的一个字段,专业知识请另行搜索“Exif Orientation”。简单讲,无论您拍照时手机是横是竖,在手机看时,照片都会自动旋转,使景物是正立的。如果您没注意过,可以先在就做这个实验,把 iPhone 倒立拍照,正立过来看,景也会跟着自动转……

  当 UMU 把图片同步到电脑上时,情况就不同了。Windows 7 自带的画图、图片查看器都不支持对 Orientation 自动校正,IE9、IE10、Chrome 22.0.1229.94 m、Paint.NET 也都不支持。所以,UMU 经常看到横屏拍的照片,在 Windows 7 上是歪 90 度显示的。

  到 Windows 8 上,自带的画图、图片查看器都支持 Orientation 校正了!有一天,UMU 在看以前拍的图片时,突然发现,所有的图片都正立了……

  蛋似,前面有提到 IE10 是不支持的,所以……UMU 特地上传了一张横拍的图片到腾讯微博上,果然这图就是歪 90 度的,缩略图和原图都是。然后再用 iPhone 看,缩略图是歪 90 度,这说明腾讯微博的缩略图也没考虑 Orientation 信息,点击查看原图,终于正立了,因为 iPhone 基本到处都支持 Orientation 自动旋转校正。

  把这个发现,和马头流量结合起来思考——APN 服务器上的图片压缩程序会不会也没考虑 Orientation 信息?UMU 猜想是很有可能的,腾讯就没考虑到……然后开始测试!用 WiFi 看原图,是正立的,因为 WiFi 下,马头流量不会压缩图片;改用 3G,马头流量开始起作用,再去看原图,发生了两件事,大家应该猜到了——图片质量下降、图片歪了 90 度!八哥!这就是八哥啊!

mif2png(QQGame 专用 mif 格式转 png 格式)

2011-11-26 00:27 发布于百度空间,由于百度空间停运,搬到此处。

大学时代的作品《UMU 游戏之争上游》的副产品,mif2bmp 改进版,用 GdiPlus 来产生 png 格式图片。

mif2png.exe 下载:http://download.csdn.net/detail/umu/3843545

以前 UMU 有写过文章分析 mif 格式,不过很早了,懒得找,直接上代码吧,先看头部结构体:

1
2
3
4
5
6
7
8
9
10
#pragma pack(1)
struct MifHeader
{
DWORD version;
DWORD width;
DWORD height;
DWORD type;
DWORD frame_count;
};
#pragma pack()

以下代码是 C# 写的 Paint.NET 文件类型插件 MifFileType.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
using System;
using System.Collections.Generic;
using System.Text;
using PaintDotNet;
using PaintDotNet.Data;
using System.IO;
using System.Drawing;
using System.Windows.Forms;
using System.Drawing.Imaging;

namespace MifFileType
{
public class MifFileType : FileType
{
public MifFileType()
: base("MIF Files", FileTypeFlags.SupportsLoading | FileTypeFlags.SupportsLayers, new String[] { ".mif" })
{

}

protected override Document OnLoad(Stream input)
{

if (input.Length < 20)
{
MessageBox.Show("Invalid MIF File", "UMU Corporation - MifFileTypePlugIn", MessageBoxButtons.OK, MessageBoxIcon.Error);

Bitmap b = new Bitmap(800, 600);
return Document.FromImage(b);
}

try
{
BinaryReader br = new BinaryReader(input);

int MifVersion = br.ReadInt32();
int FrameWidth = br.ReadInt32();
int FrameHeight = br.ReadInt32();
int MifType = br.ReadInt32();
int FrameCount = br.ReadInt32();

int ImageWidth = FrameWidth;
int ImageHeight = FrameHeight * FrameCount;

bool Valid = true;
long Prefix;

if (MifType == 3)
{
Prefix = 20;
}
else if (MifType == 7)
{

Prefix = 20 + 4 * FrameCount;
}
else
{
MessageBox.Show("Invalid MIF File", "UMU Corporation - MifFileTypePlugIn", MessageBoxButtons.OK, MessageBoxIcon.Error);

Bitmap b = new Bitmap(800, 600);
return Document.FromImage(b);
}

if (MifVersion == 0)
{
if (Prefix + ImageWidth * ImageHeight * 3 != input.Length)
{
Valid = false;
}
}
else if (MifVersion == 1)
{

if (Prefix + ImageWidth * ImageHeight * 3 > input.Length)
{
Valid = false;
}
}

if (!Valid)
{
MessageBox.Show("Invalid MIF File", "UMU Corporation - MifFileTypePlugIn", MessageBoxButtons.OK, MessageBoxIcon.Error);

Bitmap b = new Bitmap(800, 600);
return Document.FromImage(b);
}

Bitmap bmp = new Bitmap(ImageWidth, ImageHeight);

for (int CurrentFrame = 0; CurrentFrame < FrameCount; ++CurrentFrame)
{
if (MifType == 7)
{
input.Seek(4, SeekOrigin.Current);
}

UInt16[] rgb16 = new UInt16[FrameWidth * FrameHeight];

for (int i = 0; i < FrameHeight * FrameWidth; ++i)
{
rgb16[i] = br.ReadUInt16();
}

Byte[] a8 = new Byte[FrameWidth * FrameHeight];

for (int i = 0; i < FrameHeight * FrameWidth; ++i)
{
a8[i] = br.ReadByte();
}

for (int y = 0; y < FrameHeight; ++y)
{
for (int x = 0; x < FrameWidth; ++x)
{
int a = a8[x + y * FrameWidth];
int r = (rgb16[x + y * FrameWidth] & 0xF800) >> 8;
int g = (rgb16[x + y * FrameWidth] & 0x07E0) >> 3;
int b = (rgb16[x + y * FrameWidth] & 0x001F) << 3;

if (a == 32)
{
a = 255;
}
else if (a > 0)
{

a <<= 3;
}

bmp.SetPixel(x, FrameHeight * CurrentFrame + y, Color.FromArgb(a, r, g, b));
}
}
}

br.Close();
return Document.FromImage(bmp);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "UMU Corporation - MifFileTypePlugIn", MessageBoxButtons.OK, MessageBoxIcon.Warning);

Bitmap bmp = new Bitmap(800, 600);
//Document doc = Document.FromImage(bmp);
//doc.Tag = "UMU Corporation - MifFileTypePlugIn";
//return doc;
return Document.FromImage(bmp);
}
}
}

public class MifFileTypeFactory : IFileTypeFactory
{
public FileType[] GetFileTypeInstances()
{
return new FileType[] { new MifFileType() };
}
}
}