zoukankan      html  css  js  c++  java
  • 将位图分块

    最近由于工作需要,要实现一个简单的gis系统。要求能够显示同一区域的多种分辨率的地图。由于图片有大有小,当图片很大的时候如果将整张图片读入内存,将会消耗大量的内存,效率不高。所以考虑将大的图片切割成小块保存,根据显示时候的需要调用指定区域的图片,拼接起来显示。
    下面是我切割图片的代码;仅供参考,希望能对大家有所帮助

    BMPSpliter.h

     1// BMPSpliter.h: interface for the BMPSpliter class.
     2//
     3//////////////////////////////////////////////////////////////////////
     4
     5#if !defined(AFX_BMPSPLITER_H__1B6BD900_9C6F_4BCD_8B77_2BC47F32D1D0__INCLUDED_)
     6#define AFX_BMPSPLITER_H__1B6BD900_9C6F_4BCD_8B77_2BC47F32D1D0__INCLUDED_
     7
     8#if _MSC_VER > 1000
     9#pragma once
    10#endif // _MSC_VER > 1000
    11class BMPSpliter : public CObject  
    12{
    13public:
    14    BOOL ReadFile();
    15    
    16    void SetSourceFileName(CString fileName);
    17    void SetDestDirectory(CString pdestDir);
    18    void SetStartNumber(int startNumber);
    19    
    20     
    21    BOOL Split(int XPxCount, int YPxCount);
    22    BOOL ReadFile(CString fileName);
    23    BMPSpliter();
    24    virtual ~BMPSpliter();
    25private:
    26    CString SourceFileName;
    27    CString DestDirectory;
    28    int StartNumber;
    29    int GetTheLineOffset(int XNum, int XPxCount);
    30    int GetOneLineSize(int XPxCount);
    31    
    32    int GetTheTileSize(int XPxCount, int YPxCount);
    33    LPBYTE GetTheTile( int XNum, int YNum,int XPxCount, int YPxCount );
    34    LPBYTE lpbmpBody;
    35    BITMAPINFO bitmapInfo;
    36    BITMAPINFOHEADER bmpInfoHeader;
    37    BITMAPFILEHEADER fileHeader;
    38    BOOL WriteFile(CString fileName,LPBYTE bmpBody, int count, int height, int width);
    39    
    40}
    ;
    41
    42#endif // !defined(AFX_BMPSPLITER_H__1B6BD900_9C6F_4BCD_8B77_2BC47F32D1D0__INCLUDED_)
    43

    BMPSpliter.cpp
      1// BMPSpliter.cpp: implementation of the BMPSpliter class.
      2//
      3//////////////////////////////////////////////////////////////////////
      4//////////////////////////////////////////////////////////////////////////

      5//只能构处理24位色以上的图片。
      6//用户只要指定要切割的图片,以及切割后图片的宽度和高度,该类即会按照从左到右、
      7//从下到上的顺序来切割图片;
      8//通过SetDestDirectory()用户可以指定切割后图片的存放目录;
      9//通过SetStartNumber()可以指定切割后图片的起始编号;
     10//////////////////////////////////////////////////////////////////////////
     11#include "stdafx.h"
     12#include "SplitBMP.h"
     13#include "BMPSpliter.h"
     14#include <math.h>
     15#ifdef _DEBUG
     16#undef THIS_FILE
     17static char THIS_FILE[]=__FILE__;
     18#define new DEBUG_NEW
     19#endif
     20
     21//////////////////////////////////////////////////////////////////////
     22// Construction/Destruction
     23//////////////////////////////////////////////////////////////////////
     24
     25BMPSpliter::BMPSpliter()
     26{
     27    SetStartNumber(0);    
     28    lpbmpBody = NULL;
     29    SetDestDirectory("map");
     30    SetSourceFileName("");
     31}

     32
     33BMPSpliter::~BMPSpliter()
     34{
     35    if(lpbmpBody!=NULL)
     36        delete [] lpbmpBody;
     37    lpbmpBody =NULL;
     38}

     39
     40BOOL BMPSpliter::ReadFile(CString fileName)
     41{
     42    SetSourceFileName(fileName);
     43    return ReadFile();    
     44}

     45
     46BOOL BMPSpliter::Split( int XPxCount, int YPxCount )
     47{
     48    if(lpbmpBody == NULL)
     49        return FALSE;
     50    if(SourceFileName.IsEmpty())
     51        return FALSE;
     52    double temp = XPxCount;
     53    int XCount = (int)ceil(bmpInfoHeader.biWidth/temp);
     54    temp = YPxCount;
     55    int YCount = (int)ceil(bmpInfoHeader.biHeight/temp);
     56    LPBYTE bmpBody;
     57    CString fileName;
     58    CString msg;
     59    for (int j = 0; j <YCount  ; j++)
     60    {
     61        for (int i = 0; i <XCount  ; i++)
     62        {
     63            bmpBody = GetTheTile(i,j, XPxCount,YPxCount);                        
     64            fileName.Format("%s\\%d.bmp",DestDirectory,i+j*XCount+this->StartNumber);
     65            if (!WriteFile(fileName,bmpBody,GetTheTileSize(XPxCount,YPxCount),XPxCount,YPxCount))
     66            {
     67                msg.Format("%s 写入失败!",fileName);
     68                //messagePrinter(msg);
     69                return FALSE;
     70            }

     71        }

     72    }

     73    return TRUE;
     74//    return WriteFile("map\\A.bmp",lpbmpBody,bmpInfoHeader.biSizeImage,bmpInfoHeader.biHeight,bmpInfoHeader.biWidth);
     75}

     76
     77BOOL BMPSpliter::WriteFile(CString fileName,LPBYTE bmpBody, int count, int height, int width)
     78{
     79    CFile file;
     80    if (!file.Open(fileName,CFile::modeCreate|CFile::modeWrite))
     81        return FALSE;
     82    BITMAPFILEHEADER header = this->fileHeader;
     83    header.bfSize = 54 + count;
     84    BITMAPINFOHEADER infoHeader = this->bmpInfoHeader;
     85    infoHeader.biHeight = height;
     86    infoHeader.biWidth = width;
     87    infoHeader.biSizeImage = count;
     88    try
     89    {
     90        file.Seek(0,CFile::begin);
     91        file.Write( (LPVOID)&header, sizeof(BITMAPFILEHEADER));
     92        file.Write( (LPVOID)&infoHeader, sizeof(BITMAPINFOHEADER));
     93        file.Write( (LPVOID)bmpBody, count);
     94        file.Flush();        
     95    }

     96    catch (CException* e)
     97    {        
     98        file.Close();    
     99        return FALSE;
    100    }
        
    101    file.Close();
    102    return TRUE;
    103}

    104
    105
    106
    107LPBYTE BMPSpliter::GetTheTile(  int XNum, int YNum,int XPxCount, int YPxCount  )
    108{
    109    //根据参数计算要读取的区域
    110    //如果超越了原图的边界,用空白补齐;
    111    LPBYTE lpbody= NULL;
    112    int count = GetOneLineSize(XPxCount);
    113    count = count * YPxCount;
    114    lpbody = (LPBYTE) new char[count];
    115    FillMemory(lpbody,count,0xFF);
    116    int StartPos = GetOneLineSize(bmpInfoHeader.biWidth)*YPxCount*YNum + (bmpInfoHeader.biBitCount/8)*XPxCount*XNum;
    117    int OneLineOffset = GetTheLineOffset(XNum, XPxCount);
    118    int LineStartPos = 0;
    119    for (int i = 0; i < YPxCount ; i++)
    120    {
    121        LineStartPos = StartPos + GetOneLineSize(bmpInfoHeader.biWidth)*i;
    122        CopyMemory(&lpbody[GetOneLineSize(XPxCount)*i],&lpbmpBody[LineStartPos],OneLineOffset);
    123    }
        
    124    return lpbody;
    125
    126}

    127
    128int BMPSpliter::GetTheTileSize( int XPxCount, int YPxCount )
    129{
    130    //根据参数来计算该Tile的图像体的大小。
    131    int result = GetOneLineSize(XPxCount);
    132    result = result*YPxCount;
    133    return result;
    134}

    135
    136
    137int BMPSpliter::GetOneLineSize(int XPxCount)
    138{
    139    int result = (((XPxCount*bmpInfoHeader.biBitCount)+31)>>5)<<2;
    140    return result;
    141}

    142
    143int BMPSpliter::GetTheLineOffset(int XNum, int XPxCount)
    144{
    145    int result = XPxCount*(bmpInfoHeader.biBitCount/8);
    146    int sourceBmpLengthPerLine = bmpInfoHeader.biWidth*(bmpInfoHeader.biBitCount/8);
    147    if( result*(XNum+1)>sourceBmpLengthPerLine)
    148        result = sourceBmpLengthPerLine - (result*XNum);
    149    return result;
    150}

    151
    152
    153void BMPSpliter::SetStartNumber(int startNumber)
    154{
    155    StartNumber = startNumber;
    156}

    157
    158void BMPSpliter::SetDestDirectory(CString destDir )
    159{
    160    this->DestDirectory = destDir;
    161    CFileFind ff;
    162    if(!ff.FindFile(DestDirectory+"\\*.*"))
    163        CreateDirectory(DestDirectory+"\\",NULL);    
    164}

    165
    166void BMPSpliter::SetSourceFileName(CString fileName)
    167{
    168    SourceFileName = fileName;
    169}

    170
    171BOOL BMPSpliter::ReadFile()
    172{
    173    CFile file;
    174    file.Open(SourceFileName,CFile::modeRead);
    175    try
    176    {
    177        int counts = file.Read((LPVOID)&fileHeader,sizeof(BITMAPFILEHEADER));
    178        if (counts!=sizeof(BITMAPFILEHEADER))
    179            throw new CException;
    180        if(fileHeader.bfType != 0x4d42
    181            throw new CException;
    182        //文件头信息->位图信息->位图数据
    183        //bfOffBits为从文件开始到数据内容之间的距离
    184        int size = fileHeader.bfOffBits - sizeof(BITMAPFILEHEADER);
    185        //bmpInfoHeader = (LPBITMAPINFOHEADER) new char[size];
    186        // BITMAPINFOHEADER和颜色表
    187        counts = file.Read(&bmpInfoHeader, sizeof(BITMAPINFOHEADER));
    188        if (counts!=sizeof(BITMAPINFOHEADER))
    189            throw new CException;
    190        //如果为16位色或者更小,则无法处理
    191        if(bmpInfoHeader.biBitCount<=16)
    192            throw new CException;
    193        //如果图像是压缩的,则也无法处理
    194        if(bmpInfoHeader.biCompression !=BI_RGB)
    195            throw new CException;
    196        //读取图像内容
    197        file.Seek(fileHeader.bfOffBits,CFile::begin);
    198        lpbmpBody = (LPBYTE)new char[bmpInfoHeader.biSizeImage];
    199        counts  = file.Read(lpbmpBody,bmpInfoHeader.biSizeImage);
    200    }

    201    catch (CException* e)
    202    {
    203        AfxMessageBox("Read File Error");
    204        return FALSE;
    205    }

    206    return TRUE;
    207}

    208


    一个简单例子:
    1    BMPSpliter spliter;
    2    spliter.ReadFile("map\\Source.bmp");
    3    spliter.SetDestDirectory("splitResult");
    4    spliter.SetStartNumber(16);
    5    spliter.Split(256,256);
  • 相关阅读:
    判断字符串和null相等 if(keyword.equals("null"))
    去掉input text后面的叉
    设置标题小图标ico
    使用onclick跳转到其他页面。使用button跳转到指定url
    中文输入法不触发onkeyup事件的解决办法
    全选js实现
    修改数据库结构需要修改的部分
    1. 移动测试点
    2.7.2 元素定位:frame 内定位 driver.switch_to.frame()
    2.7.1 元素定位:selenium消息框处理 (alert、confirm、prompt)
  • 原文地址:https://www.cnblogs.com/strinkbug/p/651212.html
Copyright © 2011-2022 走看看