懒人笔记-cximage篇<ubuntu>

本文档详细记录了在Ubuntu系统下,如何使用cximage库将jpg转换为TIFF的过程,包括下载、编译遇到的问题及解决方案,以及在QT工程中的应用示例。在编译过程中,主要涉及源码修改、配置选项设置和依赖库安装。通过解决各种错误,最终成功实现了JPG到TIFF的转换。
摘要由CSDN通过智能技术生成

前言

由于项目需要,需要将jpg转换成TIFF,考虑到window下已经实现过,所以继续用cximage来进行图片转换。

过程

下载

请下载linux专版cximage599c

编译

文件修改

在编译之前,需要修改tif_xfile.cpp的源码,需要修改的内容网上一堆,但是我用ubuntu测试了下,都不行,对照了windows的源码,需要调整的红色标注如下:
TIFF*
_TIFFFdOpen(void* fd, const char* name, const char* mode)
{
TIFF* tif;
tif = TIFFClientOpen(name, mode,
(thandle_t) fd,
_tiffReadProcEx, _tiffWriteProcEx, _tiffSeekProcEx, _tiffCloseProcEx,
_tiffSizeProcEx, _tiffMapProcEx, _tiffUnmapProcEx);
if (tif)
tif->tif_fd =(long) fd;
return (tif);
}

extern “C” TIFF* _TIFFOpenEx(CxFile* stream, const char* mode)
{
return (_TIFFFdOpen((void*)stream, “TIFF IMAGE”, mode));
}

正式编译

由于直接直行sudo ./configure会报权限问题,按照如下进行重新生成:

#重新生成 aclocal.m4
aclocal

#重新生成configure文件
autoconf -i -v -f

#删除原来的makefile
find ./ -name Makefile -exec rm -rf {} \;

#重新生成Makefile
./configure
make

出现错误1:
configure:error cannot guess build type;you must specify one cximage
不能确定编译的操作系统
解决方法
在gcc编译中我们使用
  ./configure --build=编译平台 --host=运行平台 --target=目标平台
./configure --build=arm-linux --prefix=/usr

出现错误2:
error: C++ preprocessor “/lib/cpp” fails sanity check
是由于缺少C++库,解决方法
apt-get install build-essential
apt-get install g++
然后再
./configure
make

出现错误3:
configure.in:62: ‘automake --add-missing’ can install ‘compile’
make: *** [Makefile.in] Error 1  

#解决方法,在终端里执行如下命令
automake --add-missing
make

出现错误4:
fatal error: jasper/jas_config.h: 没有那个文件或目录
#删除原来的 Makefile
find ./ -name Makefile -exec rm -rf {} \;
#添加–with-extra-includes指定头文件路径,重新生成Makefile
./configure --with-extra-includes=/home/cximage599c/cximage/jasper/include/
make clean  
make

代码

以下工程用QT进行测试,请注意!

在pro文件夹加入如下链接
LIBS += -L $$PWD/lib -lCxImage -ljpeg -ltiff -lzlib -lpng -ljasper

在pro同级目录下创建Include、lib文件夹
将cximage599c/cximage目录下的相应文件拷贝到以上文件夹下面

整个工程的组织如下图:

demo
include
lib
main.cpp
xfile.h
ximacfg.h
ximadef.h
ximage.h
ximatif.h
xiofile.h
xmemfile.h
tiff文件夹
tiff.h
tiffio.h
libCxImage.a
libjasper.a
libjpeg.a
libtiff.a
libj2k.a
libjbig.a
libpng.a
libzlib.a

下面展示 测试代码

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

//#include "./include/ximage.h"
#include "./include/ximatif.h"


int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QStringList imgList_jpg;
    imgList_jpg.append("scan_1.jpg");
    imgList_jpg.append("scan_2.jpg");   
    QString strFolder("/home/redcolor/qt_study/cximage_link/jpg_convert");
    QString strTIFF_jpg ;
    
#ifdef jpg2tif
    CxImage image_jpg[2];
    for(int i = 0 ; i < imgList_jpg.size();i++)  {
        QString szJpgAt = QString("%1/%2").arg(strFolder).arg(imgList_jpg.at(i));
        if (image_jpg[i].Load((const char*)szJpgAt.toLocal8Bit().data(),CXIMAGE_FORMAT_JPG))
            image_jpg[i].DecreaseBpp(4,0);
    }
    strTIFF_jpg = QString("%1/%2").arg(strFolder).arg("tiff_jpg.tif");
    FILE* hFileTiff = fopen(strTIFF_jpg.toLocal8Bit().data(),_T("w+b"));
    if (hFileTiff)   {
        int nIndex = 0 ;
        CxImage* img[2];
        img[nIndex] = &image_jpg[nIndex];nIndex++;
        img[nIndex] = &image_jpg[nIndex];nIndex++;      
        CxImage image;
        image.Encode(hFileTiff,img,nIndex,CXIMAGE_FORMAT_TIF);
        fclose(hFileTiff);
    }
#else
    strTIFF_jpg = QString("%1/%2").arg(strFolder).arg("tiff_jpg_direct.tif");
    FILE* hFileTiff = fopen(strTIFF_jpg.toLocal8Bit().data(),_T("w+b"));
    if (hFileTiff)  {
        CxImageTIF image_tif;
        for(int i = 0 ; i < imgList_jpg.size();i++)  {
            QString szJpgAt = QString("%1/%2").arg(strFolder).arg(imgList_jpg.at(i));
            if (image_tif.Load((const char*)szJpgAt.toLocal8Bit().data(),CXIMAGE_FORMAT_JPG)){
                image_tif.DecreaseBpp(4,0);
                image_tif.Encode(hFileTiff,TRUE);
            }
        }
        fclose(hFileTiff);
    }
#endif
    return 1;
}

上面的代码展示了2个jpg到tiff的转换方法,本质都是一样的,但是引用的库不一样,可以看头文件引用部分。
由于之前windows的代码是将jpg转换为bmp,再由bmp转换为TIFF文件,导致在Linux环境下一开始也是按照这种思路在推进,结果就是一顿baidu也没有找到解决方法(cximage599c里面的bmp完全不能用),没有办法我就按照windows的代码对Linux下的一顿魔改,最终可以实现load CXIMAGE_FORMAT_JPG 图片保存为CXIMAGE_FORMAT_BMP位图图片,也可以实现DecreaseBpp(1,0),但是只能实现位深度为1的压缩。
后来继续了解了下BMP、TIFF、JPG的图片格式,然后换了思路,直接用JPG转TIFF,先用源码尝试了下可行,然后又用静态库试了下也行,才有了这篇文章。

说实话,BMP魔改真实蛋疼,核心就是下面这个结构体

typedef struct tagBITMAPINFOHEADER{
    DWORD      biSize;
    long       biWidth;
    long       biHeight;
	WORD       biPlanes;
	WORD       biBitCount;
    DWORD      biCompression;
    DWORD      biSizeImage;
    long       biXPelsPerMeter;
    long       biYPelsPerMeter;
    DWORD      biClrUsed;
    DWORD      biClrImportant;
} BITMAPINFOHEADER;

改为如下结构体

typedef struct tagBITMAPINFOHEADER_WIN32{
    UINT      biSize;
    UINT       biWidth;
    UINT       biHeight;
    WORD       biPlanes;
    WORD       biBitCount;
    UINT      biCompression;
    UINT      biSizeImage;
    UINT       biXPelsPerMeter;
    UINT       biYPelsPerMeter;
    UINT      biClrUsed;
    UINT      biClrImportant;
} BITMAPINFOHEADER_WIN32;

本质就是位图信息格式长度不对,导致解析失败,对应的就是decode和encode里面的地址偏移量的问题了。其中bool CxImageBMP::Encode(CxFile * hFile)部分的魔改代码如下

 BITMAPFILEHEADER	hdr;
    hdr.bfType      = 0x4d42;         // 'BM' WINDOWS_BITMAP_SIGNATURE
    hdr.bfSize      = (sizeof(BITMAPINFOHEADER_WIN32) + head.biSizeImage + GetPaletteSize()) + 14 ; //  GetSize() + 14 /*sizeof(BITMAPFILEHEADER)*/;
    hdr.bfReserved1 = hdr.bfReserved2 = 0;
    hdr.bfOffBits   = 14 /*sizeof(BITMAPFILEHEADER)*/ + sizeof(BITMAPINFOHEADER_WIN32) + GetPaletteSize();
    hdr.bfType      = m_ntohs(hdr.bfType);
    hdr.bfSize      = m_ntohl(hdr.bfSize);
    hdr.bfOffBits   = m_ntohl(hdr.bfOffBits);

    BITMAPINFOHEADER_WIN32 headBMP;
    headBMP.biSize = sizeof(BITMAPINFOHEADER_WIN32);
    headBMP.biBitCount = head.biBitCount;
    headBMP.biClrImportant = head.biClrImportant;
    headBMP.biClrUsed = head.biClrUsed;
    headBMP.biCompression = head.biCompression;
    headBMP.biHeight = head.biHeight;
    headBMP.biPlanes = head.biPlanes;
    headBMP.biSizeImage = head.biSizeImage;
    headBMP.biWidth = head.biWidth;
    headBMP.biXPelsPerMeter = head.biXPelsPerMeter;
    headBMP.biYPelsPerMeter = head.biYPelsPerMeter;

    // Write the file header
    int nFileHeadLen = min(14,sizeof(hdr));
    hFile->Write(&hdr,nFileHeadLen,1);
	 //copy attributes
    memcpy(pDib,&headBMP,sizeof(BITMAPINFOHEADER_WIN32));
    bihtoh((BITMAPINFOHEADER_WIN32*)pDib);

    // Write the DIB header and the pixels
    if(nImgType == CXIMAGE_FORMAT_JPG)
    {
        int nBmpInfoHeaderLen = sizeof(BITMAPINFOHEADER_WIN32);
        hFile->Write(pDib,nBmpInfoHeaderLen,1);
        int nJpgInfoHeaderLen = sizeof(BITMAPINFOHEADER);
        int nBodyLen =   GetPaletteSize() + headBMP.biSizeImage ;
        hFile->Write(pDib+nJpgInfoHeaderLen,nBodyLen,1);
    }else
    {
        int nBodyLen = sizeof(BITMAPINFOHEADER_WIN32) + GetPaletteSize() + headBMP.biSizeImage ;
        hFile->Write(pDib,nBodyLen,1);
    }
    bihtoh((BITMAPINFOHEADER_WIN32*)pDib);

这仅仅是核心部分代码,其它代码有需要的请自行魔改!
鉴于项目需要,仅支持JPG转BMP的,其它格式的还需要自行支持。

完结

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

羽毛乱发

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值