00,01,10,11......



XML



搜索关键词:





>>More



















    分页共3页 1 2 3 下一页 最后一页


    关于PDF排版
    -  [电子书 ]

      

    原文地址 http://lycoder.javaeye.com/blog/609989

    “PDFBox看起来非常的方便,它的API功能强大。甚至能和Lucene进行无缝的结合。但是它有一个致命的弱点,就是它不支持中文。要提取中文的文本,可以采用另一个非常出色的工具xpdf。”

    于是我决定自己比较一下这两种方法处理中文pdf文档时在时间性能、读取效果等各个方面的效果。

    一、关于XPDF和PDFBOX
    1.xpdf
    xpdf只是一个软件,通过java采用命令行调用,并获取输出结果,如此来说使用简单,但是相当受限,如:无法跨平台,无法处理特定格式(表格等),无法处理图片和其他附件。这种调用必定限制了它的灵活性。

    2.pdfbox
    pdfbox(一个BSD许可下的源码开放项目)是一个为开发人员读取和创建PDF文档而准备的纯Java类库。
    二、XPDF的配置
    1.工具包下载
    点这里 下载
    我下载的是: xpdf-3.02pl4-win32.zip
    另外还需要一个语言包: xpdf-chinese-simplified.tar.gz

    2.工作路径设置
    参考资料点这里
    在本文中以 c:\xpdftest\xpdf 作为xpdf的工作路径。
    将 xpdf-3.02p14-win32.zip 解压到 c:\xpdftest\xpdf 下。
    将 xpdf-chinese-simplified.tar.gz 解压到 c:\xpdftest\xpdf\xpdf-chinese-simplified 下。

    解压后的目录结构如图1所示:






    3.修改配置文件
    为了启用中文简体语言包,必须将 xpdf-chinese-simplified 目录下的 sample-xpdfrc 文件进行如下配置,并将其另存为
    xpdfrc 文件 。
    注意:此文件为配置文件,而且名称必须是 xpdfrc 。如果是别的名字,即使调用 pdftotext.exe 时,传入 ” -cfg xpdfrc2 ” 来告诉
    xpdf 配置文件的名字,好像 pdftotext.exe 也并没有使用这个配置文件。所以为了减少误解,请您将配置文件直接命名为 xpdfrc 。

    修改 sample-xpdfrc 文件之一
    在文件后面 加上一段话 :

    Txt代码
    #----- begin Chinese Simplified support package (2004-jul-27)

    cidToUnicode Adobe-GB1
    C:/xpdftest/xpdf/xpdf-chinese-simplified/Adobe-GB1.cidToUnicode

    unicodeMap ISO-2022-CN
    C:/xpdftest/xpdf/xpdf-chinese-simplified/ISO-2022-CN.unicodeMap

    unicodeMap EUC-CN
    C:/xpdftest/xpdf/xpdf-chinese-simplified/EUC-CN.unicodeMap

    unicodeMap GBK C:/xpdftest/xpdf/xpdf-chinese-simplified/GBK.unicodeMap

    cMapDir Adobe-GB1 C:/xpdftest/xpdf/xpdf-chinese-simplified/CMap

    toUnicodeDir C:/xpdf/chinese-simplified/CMap

    #displayCIDFontTT Adobe-GB1 /usr/..../gkai00mp.ttf

    #----- end Chinese Simplified support package

    #----- begin Chinese Simplified support package (2004-jul-27)

    cidToUnicode Adobe-GB1 C:/xpdftest/xpdf/xpdf-chinese-simplified/Adobe-GB1.cidToUnicode

    unicodeMap ISO-2022-CN C:/xpdftest/xpdf/xpdf-chinese-simplified/ISO-2022-CN.unicodeMap

    unicodeMap EUC-CN C:/xpdftest/xpdf/xpdf-chinese-simplified/EUC-CN.unicodeMap

    unicodeMap GBK C:/xpdftest/xpdf/xpdf-chinese-simplified/GBK.unicodeMap

    cMapDir Adobe-GB1 C:/xpdftest/xpdf/xpdf-chinese-simplified/CMap

    toUnicodeDir C:/xpdf/chinese-simplified/CMap

    #displayCIDFontTT Adobe-GB1 /usr/..../gkai00mp.ttf

    #----- end Chinese Simplified support package 注意:路径要跟自己配置的一样。


    修改 sample-xpdfrc 文件之二
    另外,配置文件中原先没有加上一个“ textPageBreaks ”控制。为了避免这个分页符号,我们需要在 sample-xpdfrc 文件 “ text
    output control ”下面 加上一段话 :
    Txt代码
    # If set to "yes", text extraction will insert page
    # breaks (form feed characters) between pages. This
    # defaults to "yes".
    textPageBreaks no

    # If set to "yes", text extraction will insert page
    # breaks (form feed characters) between pages. This
    # defaults to "yes".
    textPageBreaks no 设置 textPageBreaks 为 no 的意思是:在 PDF 文档的两页之间不加入分页符号。 之所以这样,是因为这个符号有时候会引起 SAX 解析
    XML 上的困难。


    修改 sample-xpdfrc 文件之三
    配置文件中原先把 textEncoding 注释了。这样默认的字符集是 Latin1 。我们必须打开它,并且就是指定 textEncoding 为 UTF-8
    ,而不是 GB2312 。即修改这句话 :
    Txt代码
    textEncoding UTF-8

    textEncoding UTF-8
    三、PDFBOX的配置

    请点这里 查看PDFBOX的配置。

    四、工程调用示范
    在自己的常用工作环境下新建一个工程PdfTest,并在此工程下新建一个包pdfToText。
    此包包括三个类:
    TestPdfToText.java 包括Main函数,调用并测试xpdf和pdfbox对PDF文档的处理效果。
    PdfboxToText.java 用pdfbox来处理PDF文档。
    XpdfToText.java 用xpdf来处理PDF文档。
    目录结构如图2所示:



    在C盘根目录下有061231.pdf,在工程中相应设置路径进行测试,以下是源代码 :
    TestPdfToText.java
    Java代码
    package pdfToText;
    /**
    * 功能描述:测试用XPDF和PDFBOX来读取中文PDF文件生成TXT文件的效果
    * @author Emily
    * @Create 2010-03-07
    */
    public class TestPdfToText {

    /**
    * @param args
    */
    public static void main(String[] args) {
    String rootPath = "c:\\061231";
    //pdf文件路径
    String pdffile = rootPath + ".pdf";
    //用xpdf生成的txt文件路径
    String xpdfToTxtfile = rootPath + "_xpdf.txt";
    //用pdfbox生成的txt文件路径
    String pdfboxToTxtfile = rootPath + "_pdfbox.txt";
    //XPDF
    try{
    long begin = System.currentTimeMillis();
    XpdfToText xpToTxt = new XpdfToText(pdffile);
    xpToTxt.toTextFile(xpdfToTxtfile);
    long end = System.currentTimeMillis();
    System.out.println("xpdf\t cost:\t" + (end - begin) + " ms");
    }catch(Exception e){
    e.printStackTrace();
    }
    //PDFBOX
    try{
    long begin = System.currentTimeMillis();
    PdfboxToText pbToTxt = new PdfboxToText(pdffile);
    pbToTxt.toTextFile(pdfboxToTxtfile);
    long end = System.currentTimeMillis();
    System.out.println("pdfbox\t cost:\t" + (end - begin) + " ms");
    }catch(Exception e){
    e.printStackTrace();
    }

    }
    }

    package pdfToText;
    /**
    * 功能描述:测试用XPDF和PDFBOX来读取中文PDF文件生成TXT文件的效果
    * @author Emily
    * @Create 2010-03-07
    */
    public class TestPdfToText {

    /**
    * @param args
    */
    public static void main(String[] args) {
    String rootPath = "c:\\061231";
    //pdf文件路径
    String pdffile = rootPath + ".pdf";
    //用xpdf生成的txt文件路径
    String xpdfToTxtfile = rootPath + "_xpdf.txt";
    //用pdfbox生成的txt文件路径
    String pdfboxToTxtfile = rootPath + "_pdfbox.txt";
    //XPDF
    try{
    long begin = System.currentTimeMillis();
    XpdfToText xpToTxt = new XpdfToText(pdffile);
    xpToTxt.toTextFile(xpdfToTxtfile);
    long end = System.currentTimeMillis();
    System.out.println("xpdf\t cost:\t" + (end - begin) + " ms");
    }catch(Exception e){
    e.printStackTrace();
    }
    //PDFBOX
    try{
    long begin = System.currentTimeMillis();
    PdfboxToText pbToTxt = new PdfboxToText(pdffile);
    pbToTxt.toTextFile(pdfboxToTxtfile);
    long end = System.currentTimeMillis();
    System.out.println("pdfbox\t cost:\t" + (end - begin) + " ms");
    }catch(Exception e){
    e.printStackTrace();
    }

    }
    } PdfboxToText.java
    Java代码
    package pdfToText;

    import java.io.BufferedWriter;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileWriter;
    import java.io.IOException;
    import org.pdfbox.pdfparser.PDFParser;
    import org.pdfbox.pdmodel.PDDocument;
    import org.pdfbox.util.PDFTextStripper;

    public class PdfboxToText {
    private String filePath;
    public PdfboxToText(String filePath){
    this.filePath = filePath;
    }
    public String getTextFromPdf(){
    String result = null;
    FileInputStream is = null;
    PDDocument document = null;
    try {
    is = new FileInputStream(filePath);
    PDFParser parser = new PDFParser(is);
    parser.parse();
    document = parser.getPDDocument();
    PDFTextStripper stripper = new PDFTextStripper();
    result = stripper.getText(document);
    } catch (FileNotFoundException e) {
    e.printStackTrace();
    } catch (IOException e) {
    e.printStackTrace();
    } finally {
    if (is != null) {
    try {is.close();}catch(IOException e){e.printStackTrace();}
    }
    if (document != null) {
    try{document.close();}catch (IOException
    e){e.printStackTrace();}
    }
    }
    return result;
    }

    public void toTextFile(String filePath){
    String pdfContent = getTextFromPdf();
    try{
    File f = new File(filePath);
    if(!f.exists()){
    System.out.println("not exist");
    f.createNewFile();
    }
    BufferedWriter output = new BufferedWriter(new FileWriter(f));
    output.write(pdfContent);
    output.close();
    }catch (Exception e) {
    e.printStackTrace();
    }
    }
    }

    package pdfToText;

    import java.io.BufferedWriter;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileWriter;
    import java.io.IOException;
    import org.pdfbox.pdfparser.PDFParser;
    import org.pdfbox.pdmodel.PDDocument;
    import org.pdfbox.util.PDFTextStripper;

    public class PdfboxToText {
    private String filePath;
    public PdfboxToText(String filePath){
    this.filePath = filePath;
    }
    public String getTextFromPdf(){
    String result = null;
    FileInputStream is = null;
    PDDocument document = null;
    try {
    is = new FileInputStream(filePath);
    PDFParser parser = new PDFParser(is);
    parser.parse();
    document = parser.getPDDocument();
    PDFTextStripper stripper = new PDFTextStripper();
    result = stripper.getText(document);
    } catch (FileNotFoundException e) {
    e.printStackTrace();
    } catch (IOException e) {
    e.printStackTrace();
    } finally {
    if (is != null) {
    try {is.close();}catch(IOException e){e.printStackTrace();}
    }
    if (document != null) {
    try{document.close();}catch (IOException e){e.printStackTrace();}
    }
    }
    return result;
    }

    public void toTextFile(String filePath){
    String pdfContent = getTextFromPdf();
    try{
    File f = new File(filePath);
    if(!f.exists()){
    System.out.println("not exist");
    f.createNewFile();
    }
    BufferedWriter output = new BufferedWriter(new FileWriter(f));
    output.write(pdfContent);
    output.close();
    }catch (Exception e) {
    e.printStackTrace();
    }
    }
    }
    XpdfToText.java
    Java代码
    package pdfToText;

    import java.io.File;
    import java.io.IOException;

    public class XpdfToText {
    // PDF文件名
    private File pdffile;
    // 转换器的存放位置,默认在c:\xpdftest\xpdf下面
    private String CONVERTOR_STORED_PATH = "c:\\xpdftest\\xpdf\\";
    // 转换器的名称,默认为pdftotext
    private String CONVERTOR_NAME = "pdftotext";

    // 构造函数,参数为pdf文件的路径
    public XpdfToText(String pdffile) throws IOException {
    this.pdffile = new File(pdffile);
    }

    // 将pdf转为文本文档,参数为目标文件的路径
    public void toTextFile(String targetfile) throws IOException {
    toTextFile(targetfile, true);
    }

    // 将pdf转为文本文档,参数1为目标文件的路径,
    // 参数2为true则表示使用PDF文件中的布局
    public void toTextFile(String targetfile, boolean isLayout)
    throws IOException {
    String[] cmd = getCmd(new File(targetfile), isLayout);
    Runtime.getRuntime().exec(cmd);
    }

    // 获取PDF转换器的路径
    public String getCONVERTOR_STORED_PATH() {
    return CONVERTOR_STORED_PATH;
    }

    // 设置PDF转换器的路径
    public void setCONVERTOR_STORED_PATH(String path) {
    if (!path.trim().endsWith("\\"))
    path = path.trim() + "\\";
    this.CONVERTOR_STORED_PATH = path;
    }

    // 解析命令行参数
    private String[] getCmd(File targetfile, boolean isLayout) {

    // 命令字符
    String command = CONVERTOR_STORED_PATH + CONVERTOR_NAME;
    // PDF文件的绝对路径
    String source_absolutePath = pdffile.getAbsolutePath();
    // 输出文本文件的绝对路径
    String target_absolutePath = targetfile.getAbsolutePath();
    // 保持原来的layout
    String layout = "-layout";
    // 设置编码方式
    String encoding = "-enc";
    String character = "GBK";
    // 设置不打印任何消息和错误
    String mistake = "-q";
    // 页面之间不加入分页
    String nopagebrk = "-nopgbrk";
    // 如果isLayout为false,则设置不保持原来的layout
    if (!isLayout)
    layout = "";
    return new String[] { command, layout, encoding, character, mistake,

    nopagebrk, source_absolutePath, target_absolutePath };
    }
    }

    package pdfToText;

    import java.io.File;
    import java.io.IOException;

    public class XpdfToText {
    // PDF文件名
    private File pdffile;
    // 转换器的存放位置,默认在c:\xpdftest\xpdf下面
    private String CONVERTOR_STORED_PATH = "c:\\xpdftest\\xpdf\\";
    // 转换器的名称,默认为pdftotext
    private String CONVERTOR_NAME = "pdftotext";

    // 构造函数,参数为pdf文件的路径
    public XpdfToText(String pdffile) throws IOException {
    this.pdffile = new File(pdffile);
    }

    // 将pdf转为文本文档,参数为目标文件的路径
    public void toTextFile(String targetfile) throws IOException {
    toTextFile(targetfile, true);
    }

    // 将pdf转为文本文档,参数1为目标文件的路径,
    // 参数2为true则表示使用PDF文件中的布局
    public void toTextFile(String targetfile, boolean isLayout)
    throws IOException {
    String[] cmd = getCmd(new File(targetfile), isLayout);
    Runtime.getRuntime().exec(cmd);
    }

    // 获取PDF转换器的路径
    public String getCONVERTOR_STORED_PATH() {
    return CONVERTOR_STORED_PATH;
    }

    // 设置PDF转换器的路径
    public void setCONVERTOR_STORED_PATH(String path) {
    if (!path.trim().endsWith("\\"))
    path = path.trim() + "\\";
    this.CONVERTOR_STORED_PATH = path;
    }

    // 解析命令行参数
    private String[] getCmd(File targetfile, boolean isLayout) {

    // 命令字符
    String command = CONVERTOR_STORED_PATH + CONVERTOR_NAME;
    // PDF文件的绝对路径
    String source_absolutePath = pdffile.getAbsolutePath();
    // 输出文本文件的绝对路径
    String target_absolutePath = targetfile.getAbsolutePath();
    // 保持原来的layout
    String layout = "-layout";
    // 设置编码方式
    String encoding = "-enc";
    String character = "GBK";
    // 设置不打印任何消息和错误
    String mistake = "-q";
    // 页面之间不加入分页
    String nopagebrk = "-nopgbrk";
    // 如果isLayout为false,则设置不保持原来的layout
    if (!isLayout)
    layout = "";
    return new String[] { command, layout, encoding, character, mistake,
    nopagebrk, source_absolutePath, target_absolutePath };
    }
    }

    五、测试结果和总结
    1.txt文件大小
    一个大小为74KB的PDF文档经处理为txt文档后,大小明显减小。
    经xpdf处理后生成了10KB的txt文件。
    经pdfbox处理后生成了12KB的txt文件。

    2.时间性能
    从运行结果来看,xpdf处理的速度明显大大快于pdfbox的处理速度,几乎是1/10。
    如图3所示。



    3.读取效果
    在设置了保持原PDF文档的布局的情况下,xpdf读取的效果如图4所示




    若不保持原PDF文的的布局,xpdf读取的效果如图5所示




    经pdfbox读取的效果如图6和图7所示。




    4.分析总结
    从以上调用结果可以发现,在时间性能和空间性能上,xpdf都明显优于pdfbox
    。在最关键的读取效果上,pdfbox会自动在某些读取文字中加入一些格式,比如回车、空格等,造成了更不好的效果。至于在某些PDF文档的格式会读出乱码的情况上,两种方法读出的乱码都是比较一致的,这应该是由于这两个方法的缺陷造成的。

    综上所示,如果不要求很高的移植性的话,采用xpdf应该是比较好的方法 。



    由 kingmk 发表于 12:57:01 | 评论 (0) | 引用 (0) | 编 辑 




    Windows版MPlayer
    -  [软件开发 ]

      

    原文地址 http://forums.mozine.cn/index.php?showtopic=124&mode=threaded


    1、本文遵循GPL/LGPL协议,欢迎自由转载,但请注明作者出处。

    2、本文首发赢政。由于在那里被问到了几个MPlayer的问题,上网查了一下,发现关于Windows版MPlayer的文章较少,即使是官方中文文档(http://www.mplayerhq.hu/DOCS/HTML/zh/documentation.html),也侧重于Linux平台的安装使用。于是结合自己的使用经验写了一篇Windows平台下使用源代码编译MPlayer的帖子,在文章末尾简略的提了一下MPlayer命令行及GUI的使用。见笑了。

    3、Mplayer一段时间以来一直称得上Linux平台媒体播放软件的王者,其Windows移植版同样出色。但是最近Mplayer的日子过得挺尴尬。先是在Linux(KDE)平台上被媒体播放器的新贵Kaffeine 一通穷追猛打,然后又和自己的子项目FFmpeg一起惹上了莫名其妙的版权官司。(http://www.mplayerhq.hu/homepage/index.html)虽然目前Mplayer 开发工作仍在正常进行,但前途依然是个未知数。作为一个Mplayer 的忠实拥护者,我只能默默地祈祷它一路走好!

    4、本文主要参考文档:http://www4.mplayerhq.hu/MPlayer/releases/...MinGW-Howto.txt
    5、我的机器是NorthWood的赛扬2.0,winxp sp2 ,从编译过程来讲,A贩们的U和其他windows操作系统应该大同小异。

    6、时间仓促,错漏难免,敬请批评指正,谢谢!

    一、一般在Windows平台使用MPlayer的人大都会选择 KK编译版,相当出色和好用的版本,那么为什么还要费时费力地从源代码编译安装MPlayer?嘿嘿,我想有几个理由吧:

    1、命令行下执行MPlayer.exe你会发现,Mplayer的windows发行版默认都只是针对MMX和MMX2指令集进行的编译(如图),而它的源代码还支持SSE,SSE2,3DNOW!和3dnow-dsp!指令集,如果你有一颗比较新的CPU,通过编译源代码加入对以上几个指令集的支持,以达到更好的效果和更低的资源占用,是一件比较爽的事情。



    2、自己编译的MPlayer可以自定义一些性能选项。比如说,默认的MPlayer并不支持2GB以上的单个文件,这就是为什么有人使用MPlayer播放HDTV影片其效果相当糟糕的原因。 你可以通过自己编译加上对它的支持。

    3、MPlayer每天都会根据前一天的工作发布一个CVS的完整源代码包,只要你喜欢,每天你都可以编译一个最新的版本——你可以品尝到MPlayer最新的性能——当然,也可能包括最新的bug

    4、通过编译安装,除了打造完全适合自己机器的软件外,还能多学一点电脑知识。

    5、好玩。

    如果以上五个理由没有打动你,那你就不要编译安装了,老老实实的下载上面提到的KK版,也是相当好用的。

    二、安装前的准备工作

    1、别看我们说是在windows下编译安装MPlayer,但是win自身并不提供相关工具。我们还需要安装两个软件,去 http://www.mingw.org/download.shtml 下载MinGW-3.2.0-rc-3.exe和MSYS-1.0.10.exe ,首先双击安装MinGW-3.2.0-rc-3.exe,这个和普通的win程序安装没什么区别,一路next就可以搞定;然后双击安装MSYS- 1.0.10.exe,这个在安装结束的时候会弹出对话框:"Do you wish to continue with the post install? [yn ]"选y后,又会弹出一个"Do you have MinGW installed? [yn ]" 也是选y,然后让你给出MinGW的安装路径,如果是默认的话应当填C:/mingw(注意用“/”而不是“\”)安装结束后会在桌面生成一个MSYS的图标,双击即可执行。

    MinGW 和MSYS究竟是干什么用的?呵呵,我一直都把它们理解为Linux部分工具软件和库+shell命令行的Windows移植版。为了写这篇文章专门搜了一下,原来MinGW是指只用自由软件来生成纯粹的Win32可执行文件的编译环境,它是Minimalist GNU on Windows的略称。——反正就你能看见的部分来说,它就是一个类Unix/Linux的命令行式的软件编译环境。

    2、下载dx7的头文件(http://www.mplayerhq.hu/MPlayer/releases/w.../dx7headers.tgz)
    解压后把里面的全部文件复制到(c:\mingw\include)

    三、开始下载安装一些MPlayer编译所依赖的软件和lib等东东

    1、freetype(OSD字幕用)

    软件主页:http://www.gnu.org/software/libiconv/

    需要文件:libiconv-1.9.1.tar.gz

    这个文件和下面提到的文件在windows下都可以使用WinRAR解压。解压后把libiconv-1.9.1目录放在,比如说C盘下面,然后双击打开MSYS,输入

    cd C:\ libiconv-1.9.1

    注:打开libiconv-1.9.1目录,也可以按需要指定其他目录(下同)。回车,然后输入:

    ./configure --prefix=/mingw --disable-shared

    注:配置代码命令,其中--prefix=c:/mingw为指定目录命令, --disable-shared为取消共享。回车,等待执行完毕后,输入:

    make

    注:编译命令。回车,等待执行完毕后,输入:

    make install

    注:编译安装命令。

    等待执行完毕后,如果一切顺利,没有报错。那么到此就算完成了一个软件的安装。与下面的各个步骤大同小异,下面我就写的简单一些了。

    2、freetype2
    软件主页:http://sourceforge.net/project/showfiles.php?group_id=3157
    需要文件:freetype-2.1.9.tar.bz2
    同上一样,解压,然后
    cd freetype-2.1.9
    make 注:这个软件不需要./configure
    make install
    原文有错,应该要./configure

    3、zlib
    软件主页:http://www.gzip.org/zlib/
    需要文件:zlib-1.2.2.tar.bz2
    解压
    cd zlib-1.2.1
    make
    make install

    4、libpng
    软件主页:http://sourceforge.net/project/showfiles.php?group_id=5624
    所需文件:libpng-1.2.8-config.tar.gz
    解压
    cd libpng-1.2.8-config
    ./configure --prefix=c:/mingw --disable-shared
    make
    make install

    5、libjpeg
    软件主页:http://www.ijg.org/
    所需文件:jpegsrc.v6b.tar.gz
    解压
    cd jpeg-6b
    ./configure --prefix=/mingw/ --enable-static
    make
    cp .libs/libjpeg.a c:/mingw/lib/
    cp jpeglib.h jconfig.h jmorecfg.h c:/mingw/include/

    6、libregif
    软件主页:http://armory.nicewarrior.org/projects/libregif/
    所需文件:libregif 4.1.6
    解压
    cd libregif-4.1.5
    ./configure --prefix=/mingw
    make
    make install

    7、nasm
    软件主页:http://sourceforge.net/project/showfiles.php?group_id=6208
    所需文件:nasm-0.98.39.tar.bz2
    解压
    cd nasm-0.98.38
    ./configure --prefix=/mingw
    make
    mkdir c:/mingw/man/man1
    make install

    8、lame
    软件主页:http://lame.sourceforge.net/download/download.html
    所需文件:lame3.96.1.tar.gz
    解压
    cd lame-3.96.1
    ./configure --prefix=/mingw --disable-shared --disable-decoder
    make
    make install

    9、xvid
    软件主页:http://www.xvid.org/downloads.html
    所需文件:xvidcore-1.0.3.tar.bz2 (http://downloads.xvid.org/downloads/)
    这个软件最新的1.1beta版从我的机子上跑的情况来看,似乎对原来版本的兼容性有点问题,大家还是用旧的1.0.3版本的吧。
    解压
    cd xvidcore-1.0.3/build/generic
    ./configure --prefix=c:/mingw --disable-shared
    make
    make install
    mv c:/mingw/lib/xvidcore.a c:/mingw/lib/libxvidcore.a

    10、x264
    软件主页:http://subversion.tigris.org/servlets/Proj...ist?folderID=91
    所需文件:svn-win32-1.1.4.zip
    解压后将 \bin 文件夹内的所有文件复制到C:\mingw\bin文件夹内。
    原文错误,svn只是代码管理工具.x264下载地址:
    http://forum.doom9.org/showthread.php?t=89979
    下载后解压,然后
    ./configure --prefix=/mingw
    make
    make install

    11、live
    下载地址:http://www.live555.com/liveMedia/public/
    所需文件:live555-latest.tar.gz
    解压
    cd live
    genMakefiles mingw
    make

    12、RealCodecs

    下载附件中的文件(已分卷),将其解压到某个路径备用。

    至此,依赖软件和库文件的配置安装结束。

    四、编译安装MPlayer

    1、下载源代码包

    首先去http://www.mplayerhq.hu/homepage/design7/dload.html 下载MPlayer的源代码包,依据你的个人喜好,你可以下载正式发行的源码版本,比如MPlayer v1.0pre6a source,也可以下载每天更新的CVS版本。

    然后去http://www4.mplayerhq.hu/homepage/design7/codecs.html 下载那个名叫Windows all的解码器包。

    2、两个包全部解压

    3、用cd命令进入MPlayer源码的目录

    4、./configure --help

    注:执行这一步可以得到该软件支持的./configure的附加条件,可以根据自己的机器情况选用。

    其中有些条件是默认支持的,比如说,sse2,3dnow!等指令集的自动检测/支持,real及win32媒体文件的支持,流媒体的支持等等,你可以在附加条件中忽略它们。(有的时候,某些条件未必能够监测得出来。你可以注意一下下一步的 ./configure 后的执行输出,里面包含了所有的条件执行信息,如果有没有认出的,你可以手动指定。)

    5、下面就是./configure步骤了,这是我的配置,你可以根据自己的情况更改

    ./configure --prefix=D:/MPlayer --enable-win32 --enable-real --enable-live --enable-directx --enable-dshow --with-codecsdir=D:/MPlayer/codecs --with-win32libdir=D:/MPlayer/codecs --with-reallibdir=D:/MPlayer/realcodec --with-livelibdir=D:/MPlayer/codecs --enable-static --enable-largefiles --disable-mencoder
    其中:
    --prefix=D:/MPlayerr 为自定义Mplayer的安装路径。
    --with-codecsdir=D:/MPlayer/codecs 我把下载的那个/windows-all-20050115 的解码包解压到D:/MPlayer/codecs,这个命令是指定它的路径。(下面的win32也指向这个路径就行)
    --with-reallibdir=D:/MPlayer/realcodec 记得上面第12步中我们解压备用的那个RealCodecs吗?在这里指定它的路径。
    --with-livelibdir=D:/MPlayer/live 上面第11步中我们编译的那个live文件的路径。
    --enable-largefiles 支持2GB以上的单个文件——这恐怕对于HDTV爱好者来说是至关重要的。
    --enable-directx 和 --enable-dshow 这两项实际上是“自动监测”的,但是有一次在我的机器上没有认出来,还是写一下吧。
    --enable-static 是必须的,请注意一下。
    --disable-mencoder mencoder这东东我用不到,disable了。
    注意:如果你想将编译好的MPlayer.exe能够运行在不同的机器上,可以加上 --enable-runtime-cpudetection 选项;如果只是用在自己的机器和系统上,那就不要加这个。

    请注意一下 ./configure 以后的输出结果,在其中可能就能找到下次需要改进的地方。

    原文太多罗唆,精简如下:
    ./configure --prefix=D:/MPlayer --enable-win32 --enable-real --enable-live --enable-directx --enable-dshow --with-codecsdir=codecs --with-livelibdir=live --enable-static --enable-largefiles --disable-mencoder

    6、make

    如果你是1.0G以下的CPU,你大可以去午睡一会儿了。需要比较长的时间。

    7、make install

    好了,大功告成。去D:\MPlayer下看看,在bin文件夹下就可以找到Mplayer.exe了。

    将bin下的东西拷到/d/Mplayer下.lib下的东西也要拷出来.删除codecs,live之外的文件夹.(usr,man之类).如果对命令行有兴趣,将/d/mplayer加入系统path.我是没有兴趣的,所以我用了mpui.直接拷到/d/mplayer就好了.这个mplayer占用内存是少.我的播放DVD用了12M.加上MPUI一共17M.WMP可是占了30多M呢.微软的东东从来都是吃内存的大户

    五、MPlayer的使用

    1、命令行方式

    上述我们编译好的Mplayer.exe是一个命令行的应用程序——事实上官方的windows realse也是命令行版本的。这个在Windows的命令提示符里面可以运行,好在Windows的命令提示符支持拖动,我们也就不用费力的一个字符一个字符的输入了。

    如图,是Mplayer播放文件的正确命令,注意mplayer.exe和媒体文件路径之间有空格键。具体使用及控制键请参阅上面提到的官方文档。


    2、图形界面方式。
    世界各地的软件编写者们为MPlayer编写了大量的GUI,其中windows平台的也为数不少。你可以在这里查到它们的列表:http://www.mplayerhq.hu/homepage/design7/projects.html

    其中,比较优秀的有:

    (1)WinMPLauncher (http://chameleon.gazellevillage.com/~twerp...MPLauncher.html)

    我一直用这个,使用简单,功能强劲,而且资源占用几乎可以忽略不计。缺点是没有进度条和播控按钮。如图。使用方法:解压后双击 WinMPLauncher.exe,选择我们的MPlayer.exe所在路径,确定后即可使用它作为前端来调用MPlayer.exe播放文件了。

    (2)mplgui
    (http://www.mplayerhq.hu/homepage/design7/projects.html)

    这个图形界面的优点是功能全, 它支持皮肤、拖动、进度条、一些基本图形控制按钮,列表播放等。但是我只找到了一种方法打开文件——拖动,而且没有打开URL的控制项。使用方法和上面的那个大同小异。不再赘述。

    (3)MPlayerWIN(http://www.chronix.org/projects/mplayerwin/)

    有不少性能选项,也还可以。

    (4)MPlayer interface(http://home.freeuk.com/tom.nealon/mplayer.html)

    总体上介绍的第1、3、4基本上是同类的——单纯的GUI,但是综合性能上来讲还是第一个比较强。

    (5)MPUI(http://www-user.tu-chemnitz.de/~mfie/index.php?software=mpui)

    最好的一定要留在最后说。 这个图形界面功能是最全的,但同时也是占用资源最高的。下载后只将里面的MPUI.exe和autorun.inf两个文件解压到你的MPlayer目录,双击MPUI.exe即可使用。

    还有很多,就不一一列出了,大家可以自己尝试,选出自己喜欢的。

    如图是自己编译好的MPlayer,使用WinMPLauncher 界面播放mms流媒体时的截屏。但是mplayer播放的图像抓不下来哪位大虾知道怎么抓告诉一声,谢了!



    我编译的这个版本的资源占用情况:

    1094kbps的xvid影片(外挂sub字幕)连上GUI三个进程(在9~21%之间):

    原文地址 http://forums.mozine.cn/index.php?showtopic=124&mode=threaded



    由 kingmk 发表于 12:55:05 | 评论 (0) | 引用 (0) | 编 辑 




    chm 阅读器
    -  [电子书 ]

      

    电子书上面做了一个chm的阅读器。

    推荐解码库 chmlib

    http://www.jedrea.com/chmlib/



    由 kingmk 发表于 12:49:55 | 评论 (0) | 引用 (0) | 编 辑 




    Android 的一些资源
    -  [手机开发 ]

      

      Android的官方站点:

      http://www.android.com/

      AndroidSource的官方安装方法:

      http://source.android.com/download

      Android的中文站点:

      http://www.androidin.com/

      源代码包的相应联结地址:

      http://www.androidin.com/android-2337-1-1.html

      我们可以采用Android官方站点推荐方式来下载Android的源代码,也可以从Android中文站点直接下载源代码程序包,随后再更新和同步.

      当采用Android官方推荐方式下载或者需要更新你的源代码时,都需要git工具支持,当你的系统没有安装git或者git版本过低时,建议从下面的地址更新到最新的git包.(Android要求git版本必须大于1.5.4)

      http://git.or.cz/

      给git自动升级的方式:

      gitclonegit://git.kernel.org/pub/scm/git/git.git

      如果采用下载源代码包的方式,下载并展开后,在.repo/repo目录下有同步执行的文件repo,你可以将其拷贝到你的PATH所在路径以备使用,例如/usr/bin等等.或者也可以从Android站点得到最新的repo文件并复制到PATH所在路径.

      wgethttp://android.git.kernel.org/repo

      源代码包解开后,其主目录下存在repo_sync.sh文件,其主要是执行reposync以实现和Android站点同步代码包的目的,当执行出错后将再一次运行reposync命令直到同步正常结束,但原文件包含错误,建议改成下面的程序:(原文件中少了一个空格)

      #!/bin/bash

      echo"============startreposync================="

      reposync

      while[$?=1];do

      echo"============syncfailed,re-syncagain====="

      sleep3

      reposync

      done

      这样,运行shrepo_sync.sh就可以自动实现本地代码包的同步和更新动作了.

      我在FedoraCore6上经过同步之后,du-h./mydroid,占用空间大约是2.1G

      在kernel子目录下存放的就是Android的LinuxKernel了,通过和标准的Linux2.6.25Kernel的对比,我们可以发现,其主要增加了以下的内容:

      1.基于ARM架构增加Gold-Fish平台,相应增加的目录如下:

      kernel/arch/arm/mach-goldfish

      kernel/include/asm-arm/arch-goldfish

      Gold-Fish平台采用的是ARM926T CPU作为BaseBand处理器, 该CPU主频至少为200M HZ.

          采用MSM7201A CPU(ARM 11)作为主CPU, 其主频为528M HZ. 

      2.增加了yaffs2FLASH文件系统,相应增加的目录为:

      kernel/fs/yaffs2

      实际上,Android包经过编译后生成的system.img和ramdisk.img文件就是yaffs2格式的包.

      3.增加了Android的相关Driver,相应目录为:

      kernel/drivers/android

      主要分为:

      AndroidIPC系统:Binder

      Android日志系统:Logger

      Android电源管理:Power

      Android闹钟管理:Alarm

      Android内存控制台:Ram_console

      Android时钟控制的gpio:Timed_gpio

      4.增加了switch处理,相应的目录为:

      kernel/drivers/switch/

      5.增加了一种新的共享内存处理方式,相应增加的文件为:

      kernel/mm/ashmem.c

      6.其他为Linux-2.6.25内核所做的补丁等等,例如BlueTooth,在此不做详细分析

      另外GoldFish平台相关的驱动文件如下:

      1.字符输出设备:

      kernel/drivers/char/goldfish_tty.c

      2.图象显示设备:(FrameBuffer)

      kernel/drivers/video/goldfishfb.c

      3.键盘输入设备:

      kernel/drivers/input/keyboard/goldfish_events.c

      4.RTC设备:(RealTimeClock)

      kernel/drivers/rtc/rtc-goldfish.c

      5.USBDevice设备:

      kernel/drivers/usb/gadget/android_adb.c

      6.SD卡设备:

      kernel/drivers/mmc/host/goldfish.c

      7.FLASH设备:

      kernel/drivers/mtd/devices/goldfish_nand.c

      kernel/drivers/mtd/devices/goldfish_nand_reg.h

      8.LED设备:

      kernel/drivers/leds/ledtrig-sleep.c

      9.电源设备:

      kernel/drivers/power/goldfish_battery.c

      10.音频设备:

      kernel/arch/arm/mach-goldfish/audio.c

      11.电源管理:

      kernel/arch/arm/mach-goldfish/pm.c

      12.时钟管理:

      kernel/arch/arm/mach-goldfish/timer.c

      以上为Android内核的大致分析,希望能给有兴趣的人员以简单帮助。

      http://neilwong.cublog.cn



    由 kingmk 发表于 12:36:41 | 评论 (0) | 引用 (0) | 编 辑 




    madplay 一个很好用的mp3播放器
    -  [软件开发 ]

      

    madplay 是linux上的一个开源mp3播放器,它利用libmad库进行mp3软解码,libmad是一个开源的高精度 MPEG 音频解码库,支持 MPEG-1(Layer I, Layer II 和 LayerIII(也就是 MP3)。libmad提供 24-bit 的 PCM 输出,完全是定点计算,非常适合没有浮点支持的平台上使用。使用 libmad 提供的一系列 API,就可以非常简单地实现 MP3 数据解码工作。在 libmad 的源代码文件目录下的 mad.h 文件中,可以看到绝大部分该库的数据结构和 API 等。

     

    madplay基于libmad又做了一些扩展功能,比如将mp3格式转成别的音频格式如 wav等,又集成了libid3tag库进行mp3信息显示。

     

    由于项目需要我将madplay修改并移植到我们的系统中,作为音频播放界面的后台解码程序。另在程序中加入了wav的解码,使得这套代码能播放mp3和wav两种音频文件,试听下来效果也不错。



    由 kingmk 发表于 12:14:33 | 评论 (0) | 引用 (0) | 编 辑 




    png 图片的解码程序
    -  [功能代码 ]

      

    png算法(利用libpng):

    #ifndef png_jmpbuf
        #define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf)
    #endif

    #define PNG_BYTES_TO_CHECK (4)


    typedef struct
    {
        ML_U8* pSrcData;
        ML_U32 totolSize;
        ML_U32 readSize;
    }ML_PNG_READ_S;

    static void ml_png_warning(png_structp png_ptr, png_const_charp message)
    {
       ml_debugprintf("libpng warning: %s\n", message);
    }

    static void ml_png_error(png_structp png_ptr, png_const_charp message)
    {
       ml_debugprintf("libpng error: %s\n", message);
       longjmp(png_ptr->jmpbuf, 1);
    }

    static void ml_png_user_read_fn(png_structp png_ptr, png_bytep data, png_size_t length)
    {
        ML_PNG_READ_S* pImgReadCtrl;
       
        if(!png_ptr || !png_ptr->jmpbuf)
            return;
           
        pImgReadCtrl=(ML_PNG_READ_S*)png_get_io_ptr(png_ptr);
       
        if(!pImgReadCtrl)
        {
    //      longjmp(png_ptr->jmpbuf, 1);
            return;
        }
        if(pImgReadCtrl->pSrcData)
        {
            if(pImgReadCtrl->readSize+length>pImgReadCtrl->totolSize)
            {
    //          longjmp(png_ptr->jmpbuf, 1);
                ml_debugprintf("libpng read date outof memory\n");
                return;
            }
            memcpy(data, pImgReadCtrl->pSrcData+pImgReadCtrl->readSize, length);
            pImgReadCtrl->readSize+=length;
        }
    }

    ML_BOOL ml_png_decode (ML_U8* img_buf, ML_U32 img_size,IMG_PARA_S* pImgpara)
    {
        png_bytep*      row_pointers=NULL;
        png_structp     png_ptr = NULL;
        png_infop       info_ptr;
        ML_PNG_READ_S   userReadCtrl;


        ML_U32  m_width ;
        ML_U32  m_height;
     

        ML_U32  color_type;
        ML_U32  dwRead=0;

        ML_U32  i=0,j=0;
        ML_BOOL bRet=FALSE;

        ML_U8*  pArrayRGB = 0;

        ML_U32 channels=0; 
        ML_U32 chan_offset;

        if(!img_buf || img_size<MLMAX(1, PNG_BYTES_TO_CHECK))
            return FALSE;
     
        if(png_sig_cmp(img_buf, (png_size_t)0, PNG_BYTES_TO_CHECK))
        {
            return FALSE;
        }
        /* Initialize stuff */
        png_ptr=png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
        if(!png_ptr)
        {
            return FALSE;
        }
        info_ptr=png_create_info_struct(png_ptr);
        if(!info_ptr)
        {
            png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
            return FALSE;
        }
        if (setjmp(png_jmpbuf(png_ptr)))
        {
            /* Free all of the memory associated with the png_ptr and info_ptr */
            png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
            return FALSE;

        }

        png_set_error_fn(png_ptr, NULL, ml_png_error, ml_png_warning);

        //png_init_io(png_ptr, fp);

        userReadCtrl.pSrcData=img_buf;
        userReadCtrl.totolSize=img_size;
        userReadCtrl.readSize = 0;
        png_set_read_fn(png_ptr, &userReadCtrl, ml_png_user_read_fn);


        png_set_sig_bytes(png_ptr,0/* PNG_BYTES_TO_CHECK*/);
        //由于是内存源,比对标志后不需要恢复当前文件指针,
        //所以一定要设置成零,不然会造成后续操作指针越界等错误。

        //png_read_info(png_ptr, info_ptr);

        png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_EXPAND, 0);

        m_width = png_get_image_width(png_ptr, info_ptr);
        m_height = png_get_image_height(png_ptr, info_ptr); 
        color_type = png_get_color_type(png_ptr, info_ptr);
        pArrayRGB = (ML_U8*)ml_malloc(m_height*m_width*3);
        row_pointers = png_get_rows(png_ptr, info_ptr);


        switch(info_ptr->color_type)
        {
            case PNG_COLOR_TYPE_GRAY:
            case PNG_COLOR_TYPE_PALETTE:
                channels = 1;
                break;
            case PNG_COLOR_TYPE_GRAY_ALPHA:
                channels = 2;
                break;
            case PNG_COLOR_TYPE_RGB:
                channels = 3;
                break;
            case PNG_COLOR_TYPE_RGB_ALPHA:
                channels = 4;
                break;
            default:
                longjmp(png_ptr->jmpbuf, 1);
        }

        chan_offset = info_ptr->bit_depth >> 3;


        //需将 16 bit depth 缩减成 8 bit 否则显示花屏
        if (info_ptr->bit_depth > 8)
        {
            for( i = 0; i < m_height; i++)
            {
                for(j = 0; j < (channels * m_width); j ++)
                    row_pointers[i][j] = row_pointers[i][j*chan_offset];
            }
        }

        if (color_type == PNG_COLOR_TYPE_RGB)
        {
            int pos = 0;
            for( i = 0; i < m_height; i++)
            {
                for(j = 0; j < (3 * m_width); j += 3)
                {
                    pArrayRGB[pos++] = row_pointers[i][j];      // red
                    pArrayRGB[pos++] = row_pointers[i][j+1];    // green
                    pArrayRGB[pos++] = row_pointers[i][j+2];    // blue
                }
            }
        }

        // rgb with opacity
        else if (color_type == PNG_COLOR_TYPE_RGB_ALPHA)
        {
            int pos = 0;
            for( i = 0; i < m_height; i++)
            {
                for( j = 0; j < (4 * m_width); j += 4)
                {
                    pArrayRGB[pos++] = row_pointers[i][j];      // red
                    pArrayRGB[pos++] = row_pointers[i][j+1];    // green
                    pArrayRGB[pos++] = row_pointers[i][j+2];    // blue
                    //pArrayRGB[pos++] = row_pointers[i][j+3];    // alpha
                }
            }
        }

        // 256 grey values
        else if (color_type == PNG_COLOR_TYPE_GRAY)
        {
            int pos = 0;

            // get color values
            for( i = 0; i < m_height; i++)
            {
                for( j = 0; j < m_width; j++)
                {
                    pArrayRGB[pos++] = row_pointers[i][j];    // red
                    pArrayRGB[pos++] = row_pointers[i][j];    // green
                    pArrayRGB[pos++] = row_pointers[i][j];    // blue
                    //pArrayRGB[pos++] = 0;                    // alpha
                }
            }
        }

        // 256 grey values with opacity
        else if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
        {
            int pos = 0;

            // get color values
            for( i = 0; i < m_height; i++)
            {
                for( j = 0; j < (2 * m_width); j += 2)
                {
                    pArrayRGB[pos++] = row_pointers[i][j];        // blue
                    pArrayRGB[pos++] = row_pointers[i][j];        // green
                    pArrayRGB[pos++] = row_pointers[i][j];        // red
                    //pArrayRGB[pos++] = row_pointers[i][j+1];    // alpha
                }
            }
        }        

        pImgpara->imgHeight     = m_height;
        pImgpara->imgWidth      = m_width;
        pImgpara->imgRgbData    = pArrayRGB;

        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
        return TRUE;
    }



    由 kingmk 发表于 00:35:35 | 评论 (0) | 引用 (0) | 编 辑 




    jpeg 图片解码算法
    -  [功能代码 ]

      

     jpeg 算法(利用libjpeg解压):

    typedef struct
    {
        struct jpeg_source_mgr pub;
        ML_U8 *img_buf;
        ML_U32 img_size;
    } ml_jpg_source_mgr;

    typedef ml_jpg_source_mgr* ml_jpg_src_ptr;
    ml_jpg_source_mgr mlsrc;

    static void ml_jpg_init_source(j_decompress_ptr cinfo)
    {
      /**do nothing*/
    }

    static void ml_jpg_skip_input_data(j_decompress_ptr cinfo, ML_S32 num_bytes)
    {
        ml_jpg_src_ptr src = (ml_jpg_src_ptr)cinfo->src;
       
        if(num_bytes > 0)
        {
            src->pub.next_input_byte += num_bytes;
            src->pub.bytes_in_buffer -= num_bytes;
        }
    }

    static void ml_jpg_term_source(j_decompress_ptr cinfo)
    {
        ml_jpg_src_ptr src = (ml_jpg_src_ptr)cinfo->src;
       
        /**no work necessary here*/
    }

    static boolean ml_jpg_fill_input_buffer(j_decompress_ptr cinfo)
    {
        ml_jpg_src_ptr src = (ml_jpg_src_ptr)cinfo->src;
       
        if(src->img_buf)
        {
            src->pub.next_input_byte = src->img_buf;
            src->pub.bytes_in_buffer = src->img_size;
            src->img_buf = NULL;
        }
        return TRUE;
    }

    static void jpeg_init_src(j_decompress_ptr cinfo, ML_U8* img_buf, ML_U32 img_size)
    {
        ml_jpg_src_ptr src = NULL;
       
        // if(cinfo->src == NULL)
        //  cinfo->src = (struct jpeg_source_mgr *) (*cinfo->mem->alloc_small)((j_common_ptr)cinfo, JPOOL_PERMANENT, sizeof(ml_jpg_source_mgr));
       
        cinfo->src = (struct jpeg_source_mgr*)&mlsrc;
        src = (ml_jpg_src_ptr)cinfo->src;
       
        src->pub.init_source = ml_jpg_init_source;
        src->pub.skip_input_data = ml_jpg_skip_input_data;
        src->pub.resync_to_restart = jpeg_resync_to_restart;
        src->pub.term_source = ml_jpg_term_source;
        src->pub.fill_input_buffer = ml_jpg_fill_input_buffer;
       
        src->pub.bytes_in_buffer = 0;
        src->pub.next_input_byte = NULL;
       
        src->img_buf = img_buf;
        src->img_size = img_size;

    }

    static void exitErrorHandler(void *error)
    {
        //do nothing
    }

    ML_BOOL ml_jpg_decode(ML_U8* img_buf, ML_U32 img_size,IMG_PARA_S* pImgpara)
    {
        struct jpeg_decompress_struct cinfo;
        struct jpeg_error_mgr jerr;
        ML_U32 row_stride;
        JSAMPARRAY buffer;
        ML_U8  *src = NULL;

        ML_U16  x,y;
        ML_U8*  pArrayRGB = 0;
        
        cinfo.err = jpeg_std_error(&jerr);

        jerr.error_exit = &exitErrorHandler;

        jpeg_create_decompress(&cinfo);
        jpeg_init_src(&cinfo, img_buf, img_size);
        jpeg_read_header(&cinfo, TRUE);


        jpeg_start_decompress(&cinfo);
        row_stride = cinfo.output_width * cinfo.output_components;

        buffer = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
        if(!buffer)
        {
            jpeg_finish_decompress(&cinfo);
            jpeg_destroy_decompress(&cinfo);
            return FALSE;
        }

        pArrayRGB = (ML_U8*)ml_malloc(cinfo.output_height*cinfo.output_width*3);
        if(!pArrayRGB)
        {
            return FALSE;
        }
        while(cinfo.output_scanline < cinfo.output_height)
        {
            y = cinfo.output_scanline;
            jpeg_read_scanlines(&cinfo, (JSAMPARRAY)buffer, 1);

            if(cinfo.output_components == 3)
            {
                for(x = 0, src = buffer[0]; x < cinfo.output_width; x++, src+=3)
                {
                    ML_U32 index = (y*cinfo.output_width+x)*3;

                    pArrayRGB[index]    = src[0];
                    pArrayRGB[index+1]  = src[1];
                    pArrayRGB[index+2]  = src[2];

                }
            }
            else if(cinfo.output_components == 2)
            {
                for(x = 0, src = buffer[0]; x < cinfo.output_width; x++, src+=2)
                {
                    ML_U16 col16 ;
                    ML_U32 index = (y*cinfo.output_width+x)*3;
                    col16 = src[0]+(src[1]<<8);
                    pArrayRGB[index] = ((FRAME_RGB16TO32(col16))>>24)&0xff;
                    pArrayRGB[index+1] = ((FRAME_RGB16TO32(col16))>>16)&0xff;
                    pArrayRGB[index+2] = ((FRAME_RGB16TO32(col16))>>8)&0xff;
                }
            }
            else if(cinfo.output_components == 1)
            {
                for(x = 0, src = buffer[0]; x < cinfo.output_width; x++, src++)
                {

                    ML_U32 index = (y*cinfo.output_width+x)*3;
                    pArrayRGB[index]    = src[0];
                    pArrayRGB[index+1]  = src[0];
                    pArrayRGB[index+2]  = src[0];
                }
            }
            else
            {
                break;
            }

        }
        pImgpara->imgHeight     = cinfo.output_height;
        pImgpara->imgWidth      = cinfo.output_width;
        pImgpara->imgRgbData    = pArrayRGB;

      
        //error:
        jpeg_finish_decompress(&cinfo);
        jpeg_destroy_decompress(&cinfo);
        return TRUE;
    }

     



    由 kingmk 发表于 00:34:03 | 评论 (0) | 引用 (0) | 编 辑 




    bmp 图片的解码程序
    -  [功能代码 ]

      

    最近在电子书上做了几种图片的软解码程序。这里把样例程序 记录一下,方便参考。(由于博客长度限制 分三篇发布)

    程序实现 将图片内存(即先将图片文件读取到一片内存)解压成RGB的数组,解压后每个像素有三个字节分别存 R G B值。

     typedef struct
    {
        ML_U32          imgWidth;               //图片宽
        ML_U32          imgHeight;              //图片高
        ML_U8          *imgRgbData;             //解压后图片的rgb点阵
    }IMG_PARA_S;

     bmp算法:

     __packed struct tagbmp_filehead_s
    {
        ML_U16    bfType;
        ML_U32    bfSize;
        ML_U16    bfReserved1;
        ML_U16    bfReserved2;
        ML_U32    bfOffBits;
    } packed_attribute;

    typedef struct tagbmp_filehead_s bmp_filehead_s;

    __packed  struct tagbmp_infohead_s
    {
        ML_U32       biSize;
        ML_S32       biWidth;
        ML_S32       biHeight;
        ML_U16       biPlanes;
        ML_U16       biBitCount;
        ML_U32       biCompression;
        ML_U32       biSizeImage;
        ML_S32       biXPelsPerMeter;
        ML_S32       biYPelsPerMeter;
        ML_U32       biClrUsed;
        ML_U32       biClrImportant;
    }packed_attribute;
    typedef struct tagbmp_infohead_s bmp_infohead_s;

     typedef struct 
    {
        ML_U8   rgbBlue;
        ML_U8   rgbGreen;
        ML_U8   rgbRed;
        ML_U8   rgbReserved;
    } RGBQUAD;


    bmp_filehead_s   bf;
    bmp_infohead_s   bi;

    ML_BOOL ml_bmp_decode (ML_U8* img_buf, ML_U32 img_size,IMG_PARA_S* pImgpara)
    {  

        RGBQUAD     *pPal;
        ML_U8       *pBmpData;
        ML_U16      bitDepth;
        ML_U32      numColors;
        ML_S32      i,j;

        ML_U8       *pFileBuf  = img_buf;
        ML_U8       *pArrayRGB = 0;


        ml_memcpy((ML_U8*)&bf,pFileBuf,sizeof(bmp_filehead_s));
        pFileBuf += sizeof(bmp_filehead_s);
        ml_memcpy((ML_U8*)&bi,pFileBuf,sizeof(bmp_infohead_s));

        if(bi.biCompression!=0)
        {
            printf("bmp Compression not support\n");
            return FALSE; //压缩格式不支持
        }
        bitDepth = bi.biBitCount;

       
        if(bi.biClrUsed!=0)
        {
            numColors=(ML_U32)bi.biClrUsed;
        }
        else
        {
            switch(bitDepth)
            {
                case 1:
                    numColors=2;
                break;
                case 4:
                    numColors=16;
                break;
                case 8:
                    numColors=256;
                break;
                case 24:
                case 32:
                    numColors=0;
                break;
                default:
                //16bit 暂时不支持
                    return FALSE;
            }
        }
        if(bf.bfOffBits!=(ML_U32)(numColors*sizeof(RGBQUAD)+sizeof(bmp_filehead_s)
                                +sizeof(bmp_infohead_s)))
        {
            printf("Invalid color numbers!\n");
            return FALSE;
        }
        pBmpData =(ML_U8*)(img_buf+bf.bfOffBits);

    //  bf.bfSize=sizeof(bmp_filehead_s)+sizeof(bmp_infohead_s)+numColors*sizeof(RGBQUAD)+ImgSize;
        pArrayRGB = (ML_U8*)ml_malloc(bi.biHeight*bi.biWidth*3);
        if(!pArrayRGB)
        {
            return FALSE;
        }
        if(numColors!=0)
        {
            int index1,index2;
            pPal = (RGBQUAD* )(img_buf+sizeof(bmp_filehead_s)+sizeof(bmp_infohead_s));

            for ( i=0; i<bi.biHeight;i++)
            {
                for ( j=0; j<bi.biWidth; j++)
                {
                    index1 = (bi.biHeight-i-1)*bi.biWidth+j;
                    index2 = ((pBmpData[(index1*bitDepth)>>3])>> (((8/bitDepth) -1 -  (index1 % (8/bitDepth)))*bitDepth))&((1<<bitDepth)-1);
                  
                    pArrayRGB[(i*bi.biWidth+j)*3]   = pPal[index2].rgbRed;
                    pArrayRGB[(i*bi.biWidth+j)*3+1] = pPal[index2].rgbGreen;
                    pArrayRGB[(i*bi.biWidth+j)*3+2] = pPal[index2].rgbBlue;

                }
            } 
        }
        else
        {
            int index;
            int byteoff;
        //  pFileBuf = img_buf+sizeof(bmp_filehead_s);
       
     
        //  pImgData = (bmp_infohead_s*)pFileBuf;
       
            byteoff =  bitDepth/8;
       //   pRGB = (RGBQUAD* )((ML_U8*)pImgData + (ML_U32)sizeof(bmp_infohead_s));
            for ( i=0; i<bi.biHeight;i++)
            {
                for ( j=0; j<bi.biWidth; j++)
                {
                    index = ((bi.biHeight-i-1)*bi.biWidth+j)*byteoff;
                    pArrayRGB[(i*bi.biWidth+j)*3]    = pBmpData[index+2];
                    pArrayRGB[(i*bi.biWidth+j)*3+1]  = pBmpData[index+1];
                    pArrayRGB[(i*bi.biWidth+j)*3+2]  = pBmpData[index];

                }
            }   
       
        }

        pImgpara->imgHeight = (ML_U16)bi.biHeight;
        pImgpara->imgWidth  = (ML_U16)bi.biWidth;
        pImgpara->imgRgbData = pArrayRGB;


        return TRUE;

    }

     



    由 kingmk 发表于 00:23:46 | 评论 (1) | 引用 (0) | 编 辑 




    ubuntu下让应用独占framebuffer显示
    -  []

      
    linux上写了一个应用程序 显示用操作framebuffer方式实现。运行这样的应用程序有一个问题,即framebuffer 刷屏不是独占的 容易跟终端的其他显示输出相互干扰。
     
    解决方法就是操作tty设备。原理很简单,就是打开一个新的终端tty设备,把它激活,并设为图形模式,让它独占framebuffer设备,然后再输出图形,这样,即使用户按Alt+Fi也无法切换终端,framebuffer就不会被重刷,从而实现了稳定的输出。
    测试代码如下:
    //kingmk added for this app occupy framebuffer alone 
    {
        int vtnum, ttyfd;
        char ttystr[20];
        /* open /dev/tty0 and get the vt number */
        if ((ConsoleFd = open("/dev/tty0", O_WRONLY, 0)) < 0)
        {
            return;
        }
        if (ioctl(ConsoleFd, VT_OPENQRY, &vtnum) < 0 || vtnum < 0)
        {
            return;
        }
        close(ConsoleFd);
        ConsoleFd = -1;
        /* open the console tty */
        sprintf(ttystr, "/dev/tty%d", vtnum);  /* /dev/tty1-64 */
        ConsoleFd = open(ttystr, O_RDWR | O_NDELAY, 0);
       
        if (ConsoleFd < 0)
        {
            return;
        }
         /* save current vt number */
       
        {
            struct vt_stat vts;
            if (ioctl(ConsoleFd, VT_GETSTATE, &vts) == 0)
               OldVT = vts.v_active;
        }
        /* disconnect from controlling tty */
        ttyfd = open("/dev/tty", O_RDWR);
        if (ttyfd >= 0)
        {
            ioctl(ttyfd, TIOCNOTTY, 0);
            close(ttyfd);
        }
       
        /* some magic to restore the vt when we exit */
        {
       
            struct vt_mode vt;
           
            if (ioctl(ConsoleFd, VT_ACTIVATE, vtnum) != 0)
                printf("ioctl VT_ACTIVATE\n");
           
            if (ioctl(ConsoleFd, VT_WAITACTIVE, vtnum) != 0)
                printf("ioctl VT_WAITACTIVE\n");
           
            if (ioctl(ConsoleFd, VT_GETMODE, &vt) < 0)
            {
                printf( "error: ioctl VT_GETMODE\n");
                return;
            }
            vt.mode = VT_PROCESS;
            vt.relsig = SIGUSR1;
            vt.acqsig = SIGUSR1;
            if (ioctl(ConsoleFd, VT_SETMODE, &vt) < 0)
            {
                printf( "error: ioctl(VT_SETMODE) failed\n");
                return;
            }
       
        }
         /* go into graphics mode */
        if (ioctl(ConsoleFd, KDSETMODE, KD_GRAPHICS) < 0)
        {
            printf( "error: ioctl(KDSETMODE, KD_GRAPHICS) failed\n");
            return;
        }
    }
     
    退出应用时:
    {   
        struct vt_mode VT;
        /* restore text mode */
        ioctl(ConsoleFd, KDSETMODE, KD_TEXT);
        /* set vt */
       
        if (ioctl(ConsoleFd, VT_GETMODE, &VT) != -1)
        {
            VT.mode = VT_AUTO;
            ioctl(ConsoleFd, VT_SETMODE, &VT);
        }
        /* restore original vt */
       
        if (OldVT >= 0)
        {
            ioctl(ConsoleFd, VT_ACTIVATE, OldVT);
            OldVT = -1;
        }
      
        close(ConsoleFd); 
    }


    由 kingmk 发表于 00:21:51 | 评论 (0) | 引用 (0) | 编 辑 




    automake 错误
    -  [软件开发 ]

      
    虚拟机与windows 的共享目录下操作automake --add-missing 命令时会出现
    installing `./install-sh'; error while making link 等错误
    将代码目录cp到其他地方(非共享目录下)则操作正常。
    用qmake 生成makefile 则没有问题。


    由 kingmk 发表于 00:20:54 | 评论 (0) | 引用 (0) | 编 辑 




    VirtualBox+ubuntu
    -  []

      
    环境:主机操作系统是Windows XP,虚拟机是Ubuntu 8.10,虚拟机是VirtualBox 2.1.0。
    1. 安装增强功能包(Guest Additions)
    安装好Ubuntu 8.10后,运行Ubuntu并登录。然后在VirtualBox的菜单里选择"设备(Devices)" -> "安装增强功能包(Install Guest Additions)"。

    你会发现在Ubuntu桌面上多出一个光盘图标,这张光盘默认被自动加载到了文件夹/media/cdom0。进入命令行终端,输入:
    cd /media/cdom0
    sudo ./VboxLinuxAdditions.run
    开始安装工具包。安装完毕后会提示要重启Ubuntu。
    2. 设置共享文件夹
    重启完成后点击"设备(Devices)" -> 共享文件夹(Shared Folders)菜单,添加一个共享文件夹,选项固定和临时是指该文件夹是否是持久的。共享名可以任取一个自己喜欢的,比如"gongxiang",尽量使用英文名称。
    3. 挂载共享文件夹
    重新进入虚拟Ubuntu,在命令行终端下输入:
    sudo mkdir /mnt/shared
    sudo mount -t vboxsf gongxiang /mnt/shared
    其中"gongxiang"是之前创建的共享文件夹的名字。OK,现在Ubuntu和主机可以互传文件了。
    假如您不想每一次都手动挂载,可以在/etc/fstab中添加一项
    gongxiang /mnt/shared vboxsf rw,gid=100,uid=1000,auto 0 0
    这样就能够自动挂载了。
    4. 卸载的话使用下面的命令:
    sudo umount -f /mnt/shared
    注意:
    共享文件夹的名称千万不要和挂载点的名称相同。比如,上面的挂载点是/mnt/shared,如果共享文件夹的名字也是shared的话,在挂载的时候就会出现如下的错误信息(看http://www.virtualbox.org/ticket/2265):
    /sbin/mount.vboxsf: mounting failed with the error: Protocol error
    原因分析可以看Tips on running Sun Virtualbox的Shared Folder on a Linux Guest节。


    由 kingmk 发表于 00:19:51 | 评论 (0) | 引用 (0) | 编 辑 




    ubuntu 的一些问题及解决
    -  []

      
    1) 时区相差8个小时
     
    修改时区可以用
    sudo dpkg-reconfigure tzdata
    设置为上海以后时间显示还是相差8个时区,需修改
    /etc/default/rcS 文件,将 UTC=yes 改为 UTC=no
     
    2)这次安装了ubuntu 后发现 ctrl+alt+fn 无法进入文本模式,不知道什么原因。但有时候我想在纯文本下测试 比如framebuffer的使用。没办法,只好硬来了,在终端运行runlevel 后显示 N2 ,即用2级启动。
     
    进 /etc/rc2.d 移除S30gdm 文件
     
    sudo mv /S30gdm K30gdm //这样系统启动时找不到gdm 不会进入图形界面,则进入文本模式。
    (文本模式下 ctrl+alt+fn 组合键又起作用了,晕死。)输入 startx 可以进图形模式,图形模式下能正常使用终端 但无法用组合键切换到文本模式?估计是装了vmtool 后造成的问题。重新安装vmware tools 问题解决。
     
    3)ubuntu8 正常情况下没有 /dev/fb0 设备文件,这样无法在程序中使用framebuffer 控制显示界面
    vi /boot/grub/menu.lst
    在每个kernel 行后加入 vga= 0x314(800x600 16bit) 重启后出现 /dev/fb0 文件,在终端编写一个程序 打开这个设备文件,发现不能正常打开 perror 提示权限错误。
    sudo chmod 777 /dev/fb0
    之后能正确打开,但在终端下对framebuffer 进行操作 比如刷一帧白屏没有反应,切换到文本模式下,程序可以正常工作。
     
    4) 关机速度慢
    sudo gedit /etc/init.d/alsa-utils
    找到
    mute_and_zero_levels "$TARGET_CARD" || EXITSTATUS=1
    改为
    #mute_and_zero_levels "$TARGET_CARD" || EXITSTATUS=1
    重启即可
     
     


    由 kingmk 发表于 00:18:09 | 评论 (0) | 引用 (0) | 编 辑 




    ubuntu下搭建C/C++开发环境
    -  [软件开发 ]

      
    更新apt的源,测试下来台湾镜像速度是比较快的,2M带宽apt的速度基本能上200k 另据说大陆网易源也不错,没试过。
     
    sudo cp /etc/apt/sources.list /etc/apt/sources.listbk

    然后将以下内容替换到 /etc/apt/sources.list (我用的是ubuntu8.10)
     

     

    # deb cdrom:[Ubuntu 8.10 _Intrepid Ibex_ - Release i386 (20081029.5)]/ intrepid main restricted
    # See
    http://help.ubuntu.com/community/UpgradeNotes for how to upgrade to
    # newer versions of the distribution.
    deb http://tw.archive.ubuntu.com/ubuntu/ intrepid main restricted
    deb-src
    http://tw.archive.ubuntu.com/ubuntu/ intrepid main restricted
    ## Major bug fix updates produced after the final release of the
    ## distribution.
    deb
    http://tw.archive.ubuntu.com/ubuntu/ intrepid-updates main restricted
    deb-src
    http://tw.archive.ubuntu.com/ubuntu/ intrepid-updates main restricted
    ## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu
    ## team. Also, please note that software in universe WILL NOT receive any
    ## review or updates from the Ubuntu security team.
    deb
    http://tw.archive.ubuntu.com/ubuntu/ intrepid universe
    deb-src
    http://tw.archive.ubuntu.com/ubuntu/ intrepid universe
    deb
    http://tw.archive.ubuntu.com/ubuntu/ intrepid-updates universe
    deb-src
    http://tw.archive.ubuntu.com/ubuntu/ intrepid-updates universe
    ## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu
    ## team, and may not be under a free licence. Please satisfy yourself as to
    ## your rights to use the software. Also, please note that software in
    ## multiverse WILL NOT receive any review or updates from the Ubuntu
    ## security team.
    deb
    http://tw.archive.ubuntu.com/ubuntu/ intrepid multiverse
    deb-src
    http://tw.archive.ubuntu.com/ubuntu/ intrepid multiverse
    deb
    http://tw.archive.ubuntu.com/ubuntu/ intrepid-updates multiverse
    deb-src
    http://tw.archive.ubuntu.com/ubuntu/ intrepid-updates multiverse
    ## Uncomment the following two lines to add software from the 'backports'
    ## repository.
    ## N.B. software from this repository may not have been tested as
    ## extensively as that contained in the main release, although it includes
    ## newer versions of some applications which may provide useful features.
    ## Also, please note that software in backports WILL NOT receive any review
    ## or updates from the Ubuntu security team.
    # deb
    http://us.archive.ubuntu.com/ubuntu/ intrepid-backports main restricted universe multiverse
    # deb-src
    http://us.archive.ubuntu.com/ubuntu/ intrepid-backports main restricted universe multiverse
    ## Uncomment the following two lines to add software from Canonical's
    ## 'partner' repository. This software is not part of Ubuntu, but is
    ## offered by Canonical and the respective vendors as a service to Ubuntu
    ## users.
    # deb
    http://archive.canonical.com/ubuntu intrepid partner
    # deb-src
    http://archive.canonical.com/ubuntu intrepid partner
    deb http://tw.archive.ubuntu.com/ubuntu/ intrepid-security main restricted
    deb-src
    http://tw.archive.ubuntu.com/ubuntu/ intrepid-security main restricted
    deb
    http://tw.archive.ubuntu.com/ubuntu/ intrepid-security universe
    deb-src
    http://tw.archive.ubuntu.com/ubuntu/ intrepid-security universe
    deb
    http://tw.archive.ubuntu.com/ubuntu/ intrepid-security multiverse
    deb-src
    http://tw.archive.ubuntu.com/ubuntu/ intrepid-security multiverse
     
     
     

    更新源列表以后输入
    sudo apt-get update
     
    然后可以安装所需要的软件了。
     
    1)装基本开发环境
    sudo apt-get install build-essential gcc make gdb

    2)装编辑器
    sudo apt-get install vim emacs

    3)装基本开发库
    sudo apt-get install libc6 libc6-dev

    4)装manpage, 装了之后可以直接用 man 查阅各函数的详细用法 如 man opendir
    sudo apt-get install manpages-dev

    5)装esvn版本管理器
    sudo apt-get install esvn

     

    可以选择安装一些集成开发环境 如eclipse kdevelop 等。
     
    另外如需要makefile生成工具可以选择 automake qmake 等。
     
    现在可以通过ubuntu 进行软件开发了。


    由 kingmk 发表于 00:16:44 | 评论 (1) | 引用 (0) | 编 辑 




    windows7 终于可以工作了
    -  [软件开发 ]

      
    想在windows7 系统上工作,对我来说以下几个软件是必要的:
     
    1)vc 6.0 这个运行基本没有问题---比较奇怪的是如果将vc6.0的兼容模式改成:windows xp sp 2 或者以管理员身份运行时有问题。这两项都不要打勾就行了。
     
    2)ads1.2 这个是arm编译器。安装一切正常,但运行时总会有莫名其妙的异常,兼容模式中选择:windows xp sp2,禁用桌面组件,以管理员身份运行之后就可以了。
     
    3)VMware-workstation-7 + ubuntu 8.10
         这里把虚拟机更新到7.0 比较好( 跟windows7无关),因为之前用vmware 5.6.x 时,ubuntu8 无法使用共享文件夹,当时因为没有找到破解的vm7.0以上版本,很费劲的用虚拟机的网络下载了一个高版本的vmtools才搞定。直接用vm7.0 就没有这些问题了。
     
    4)程序阅读工具 UE,Source Insight 这些都能正常运行。
     
    现在整体测试下来 性能还不错,T43终于正式退役了 哈哈。


    由 kingmk 发表于 00:13:15 | 评论 (0) | 引用 (0) | 编 辑 




    Arm 系统中常用的段分类说明
    -  []

      

    .text段是代码段。它用来放程序代码(code)。它通常是只读的。
    .data段是数据段。它用来存放初始化了的(initailized)全局变量(global)和初始化了的静态变量(static)。它是可读可写的。
    .bss段是全局变量数据段。它用来存放未初始化的(uninitailized)全局变量(global)和未初始化的静态变量(static)。它也是可读可写的。bss是英文Block Started by Symbol的缩写。之所以把bssdata分开来,是因为系统会为这些bss段的变量的初值清零。
    .rodata段是常量数据段。它用来存放常量(const)。它也是只读的。

    ARM的集成开发环境中,
    1、只读的代码段称为Code段,即上述的.text段。
    2、只读的常量数据段,被称作RO Data段,即上述的.constdata段。
    以上两个段统称为RO段(Read Only),放在ROMFLASH等非易失性器件中。
    3、可读可写的初始化了的全局变量和静态变量段,被称作RW Data段(ReadWrite),即上述的.data段。
    4、可读可写的未初始化的全局变量和静态变量段,被称作ZI Data段(Zero Init),即上述的.bss段。因为这个段里的变量要被初始化为零,所以叫ZI段。
    以上两个段统称为RW段,而在运行时,它必须重新装载到可读可写的RAM中。

    一 可执行文件组成及内存映射
    在ADS下,可执行文件有两种,一种是.axf文件,带有调试信息,可供AXD调试工具使用.另一种是.bin
    文件,可执行的二进制代码文件。我们重点是讲描.bin文件的组成。
    我们把可执行文件分为两种情况:分别为存放态和运行态。
    1. 存放态
    存放态是指可执行文件通过fromelf产生后,在存储介质(flash或磁盘)上的分布. 此时可执行文件一
    般由两部分组成:分别是代码段和数据段。代码段又分为可执行代码段(.text)和只读数据段(.rodata),
    数据段又分为初始化数据段(.data)和未初始化数据段(.bss)。可执行文件的存放态如下:
    +-------------+-----------
    | .bss |
    +-------------+-- 数据段
    | .data |
    +-------------+-----------
    | .rodata |
    |_____________| 代码段
    | .text |
    +-------------+-----------
    2. 运行态
    可执行文件通过装载过程, 搬入到RAM中运行, 这时候可执行文件就变成运行态。在ADS下对可执行代
    码各段有另一个名称:
    | ... |
    +-------------+-----------
    | .bss | ZI 段
    +-------------+-- 数据段
    | .data | RW 段
    +-------------+-----------
    | .rodata |
    |_____________| 代码段(RO 段)
    | .text |
    +-------------+-----------
    | ... |
    装载前
    当可执行文件装载后, 在RAM中的分布如下:
    | ... |
    +-------------+-- ZI段结束地址
    | ZI 段 |
    +-------------+-- ZI段起始地址
    | 保留区2 |
    +-------------+-- RW段结束地址
    | RW 段 |
    +-------------+-- RW段起始地址
    | 保留区1 |
    +-------------+-- RO段结束地址
    | RO 段 |
    +-------------+-- RO段起始地址
    | ... |
    装载后
    所以装载过程必须完成把执行文件的各个段从存储介质上搬到RAM指定的位置。而这个装载过程由谁来完
    成呢?由我们的启动程序来完成.

    二 装载过程
    在ADS中,可以通过两种方式来指定可执行代码各段在RAM中的位置,一个是用armlink来指定,一种是
    用scatter文件来指定.RAM区的起始地址:0x30000000.
    1. armlink指定代码段地址
    我们通常的代码,只用指定两个段开始地址, RO段的起始地址和RW段的起始地址, ZI段紧接在RW段之
    后.示例见该部分的1.1.3.
    2. scatter指定代码段地址
    我们也可以通过scatter文件指定可执行文件各段的详细地址. Scatter文件如下:
    MYLOADER 0x30000000
    ;MYLOADER: 为可执行文件的名称, 可自定义
    ;0x3000000: 起始地址
    {
    RO 0x30000000
    ;RO 只读代码段的名称
    ;0x30000000: 只读代码段的起始地址
    {
    init.o (Init, +First)
    ; Init代码段为可执行文件的第一部分.
    * (+RO) ;所有其它的代码段和只读数据段放在该部分
    }
    RW +0
    ;RW: RW段的名称
    ;+0: 表示RW段紧接着RO段
    {
    * (+RW) ;所有RW段放在该部分
    }
    ZI +0
    ;ZI: ZI段的名称
    ;+0: 表示ZI段紧接着RW段
    {
    *(+ZI) ;所有ZI段放在该部分
    }
    }
    3. ADS产生的各代码段宏
    |Image$$RO$$Base| /* RO代码段起始地址 */
    |Image$$RO$$Limit| /* RO 代码段结束地址 */
    |Image$$RW$$Base| /* RW代码段起始地址 */
    |Image$$RW$$Limit| /* RW 代码段结束地址 */
    |Image$$ZI$$Base| /* ZI 代码段起始地址 */
    |Image$$ZI$$Limit| /* ZI 代码段结束地址 */
    注意:在两个$$之间的名称, 与scatter中指定的段的名称相同.
    4. 装载过程说明
    当从NorFlash启动时, 要把flash芯片的首地址映射到0x00000000位置, 系统启动后, 启动程序本身把自己从
    flash中搬到RAM中运行. 搬移后的各段起始地址, 由以上宏来确定.
    当从NandFlash启动时, S3C2410会自动把前NandFlash的前4k搬到S3C2410的内部RAM中,并把内部
    RAM的首地址设为0x00000000,CPU从0x00000000开始执行. 所以, 在nandFlash的前4k程序中,必须包含从
    NandFlash把BootLoader的其余部分装入RAM的程序.

    附:TI 编译中常用的段说明

    系统常用的段定义:

    .cinit包含未用const声明的外部(external)或静态(static)数据表

    .const包含已用const声明的外部或静态数据表以及字符串常量

    .text包含所有可执行的代码以及常量

    .bss用于为cinit段以及未初始化的全局和静态变量保留空间(一般是内存空间)



    由 kingmk 发表于 22:45:58 | 评论 (0) | 引用 (0) | 编 辑 




    分页共3页 1 2 3 下一页 最后一页