如何才能使我的代码达到最佳状态? [英] How can I do my code Optimal?

查看:118
本文介绍了如何才能使我的代码达到最佳状态?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望以自己的格式压缩位图2步。第一个编码器,比解码器。

Das ist mein Coder。我怎么能比解码更优化呢?







I want to compress bitmap in my own format by 2 steps. First coder, than decoder.
Das ist mein Coder. How can I do it more optimal and than decoding?



#include <iostream>
#include <stdio.h>
#include <fstream>
#include <stdlib.h>
#include <assert.h>

using namespace std;

int cnt(unsigned char *a,unsigned char b){ 

    if (*a != b)
        return 0;
    return 1+cnt(a+1, b);
}

int bytes_to_int(
    unsigned char b1, unsigned char b2,
    unsigned char b3, unsigned char b4
)
{
    return (b1 | b2<<8 | b3<<16 | b4<<24);
}

int bytes_to_int(unsigned char* b)
{
    return (b[0] | b[1]<<8 | b[2]<<16 | b[3]<<24);
}

int main()
{
    FILE *image=fopen("image.bmp","rb");
    FILE *image2=fopen("image.mRLE","wb");
    //printf("========================%d=========================\n",ftell(image));
    fseek(image,0,SEEK_END);

    const unsigned long long file_size=ftell(image);
    unsigned char* file=new unsigned char [ftell(image) + 16];

    fseek(image,0,SEEK_SET);
    fread(file, file_size, 1, image);
    fclose(image);
    //printf("\n+++++++++++++++++\n");
    const unsigned int
        width=bytes_to_int(file+18)
        ,hight=bytes_to_int(file+22)
        ,offset=bytes_to_int(file+10);
    fwrite(&width, 4, 1, image2);
    fwrite(&hight, 4, 1, image2);
    printf("width = %d; \n height = %d.\n",width,hight);

    const unsigned int length = bytes_to_int(file+2);
    fwrite(&length, 4, 1, image2);
    //fseek(image2,12,SEEK_CUR)
    fwrite(file + 54, 1024, 1, image2);
    //fseek(image,1078,SEEK_SET);

    unsigned char *a = file+1078, *aa = a + width*hight;
    //fread(a,width*hight,1,image);
    unsigned long int sizef=0;
    int i = 0;
    while(i < width*hight)
    {
        int k;
        unsigned char *c = a;
        unsigned char beg = *c;
        k = 1; ++c;
        while (c < aa && k < 255 && *c == beg)
        {
            ++k;
            ++c;
        }
        cout << k << " chars" << (int) beg << endl;
        assert(0 < k && k <= 255);
        unsigned char b1 = (unsigned char) k;
        unsigned char b2 = beg;
        a += j;
        i += j;
        fwrite(&b1, 1, 1, image2);
        fwrite(&b2, 1, 1, image2);
        //printf("===%d=========%d\n",(int)b1,(int)b2);
        // printf("%d\n",i);
    }
    /* fseek(image2,8,SEEK_SET);
    fwrite(&file_size,8,1,image2); */

    fclose(image2);
    std::cout << "Your program has finished the task!" << endl;
    // system("pause");
    return 0;
}

推荐答案

虽然使用(或可选)RLE与一些众所周知的图像格式,除非你使用分色图像,有更好的文件存储方案。 RLE仅考虑压缩期间的连续值,它很容易错过机会,甚至可能增加图像大小,例如一个像素级的棋盘格模式将在RLE下扩展,而LZ77可以缩小到99%。



也就是说,实现这样的事情可以很好地实现自己的启发。



我有一些旧代码用于RLE压缩,虽然它设计用于图形引擎,但压缩器会发出一个字节流,所以它不应该难以适应。无论如何,这里有一些建议和一些代码。

Although RLE is used (or optional) with a few well known image formats, unless you're using posterized images, there are better schemes for file storage. RLE only considers consecutive values during compression, it can easily miss opportunities and may even increase image size, e.g. a pixel level checkerboard pattern will expand under RLE while LZ77 could deflate up to 99%.

That said, it can be good to implement things like this for one's own edification.

I have some old code lying around for RLE compression, and although it was designed to work with a graphics engine, the compressor emits a byte stream, so it shouldn't be difficult to adapt. Anyway, here's some advice and some code.


  1. 决定格式并使用结构强制执行。
  2. RLE是
  3. 从较小的复杂函数中构建复杂的函数。
  4. 尽可能保持简单。



每条扫描线都以指定 pitch (字节长度)的标题开头;连续标头为每次运行指定 skip / copy 对,然后是 copy 字节值的数据。



Snippet标题,


Each scanline begins with a header specifying pitch (byte length) for that line; successive headers specify a skip/copy pair for each run, followed by copy bytes worth of data.

Snippet header,

struct rlehead {
/* rle header type. */
	static const unsigned int size;

	rlehead() : pitch(0) {}
	explicit rlehead(const void* in);

	void read(const void* in);
	void write(void* out) const;

	union {
		unsigned int pitch;
		struct { unsigned short skip, copy; };
	};
};
const unsigned int rlehead::size = sizeof(rlehead);

inline rlehead::rlehead(const void* in)
{	this->read(in);
}

inline void rlehead::read(const void* in)
{	*this = *static_cast<const>(in);
}

inline void rlehead::write(void* out) const
{	*static_cast<rlehead*>(out) = *this;
}
</const>



代码段编码,


Snippet encode,

inline char* rle_advance_scanline_(char* x, int count = 1)
/* advance rle scanline along y-axis. */
{
	while ( count-- )
	 {
	   rlehead head(x);
	   x += head.pitch;
	 }
	return x;
}

void rle_encode_eval_line_(Surface* surf, int y, std::vector<rlehead>& list)
/* generate headers from pixel data. */
{
	const PixelBase& op = Pixel.op();

	Color key = surf->col_key();
	int bpp = surf->bpp();
	int x = 0;

	while ( 1 )
	 {
	   rlehead head;
	   for ( ; x < surf->w() && op.get(surf, x, y) == key; x++ )
	      head.skip += bpp;
	   for ( ; x < surf->w() && op.get(surf, x, y) != key; x++ )
	      head.copy += bpp;
	   list.push_back(head);

	   if (head.copy == 0)
	      break;
	 }
}

void rle_encode_commit_line_(Surface* surf, int y,
  std::vector<rlehead>::iterator first, char* tmpbase)
/* write encoded line data to buffer. */
{
	char* pix = surf->pixels(0, y);
	char* tmp = tmpbase + rlehead::size;

	rlehead head;
	while ( 1 )
	 {
	   head = *first++;
	   head.write(tmp);
	   tmp += head.size;
	   pix += head.skip;

	   if (head.copy == 0)
	      break;
	   fwdcopy(tmp, pix, head.copy);
	   tmp += head.copy;
	   pix += head.copy;
	 }
	head.pitch = tmp - tmpbase;
	head.write(tmpbase);
}

void rle_encode_(Surface* surf)
/* encode surface. */
{
	const int bufsize = surf->h() * surf->pitch();
	char* tmpbase = new char[bufsize*2];
	char* tmp = tmpbase;

	std::auto_ptr<char> sentinal(tmpbase);

	for ( int y = 0; y < surf->h(); y++ )
	 {
	   std::vector<rlehead> list;
	   rle_encode_eval_line_(surf, y, list);
	   rle_encode_commit_line_(surf, y, list.begin(), tmp);
	   tmp = rle_advance_scanline_(tmp);

	   if (tmp - tmpbase > bufsize)
	      return;
	 }

	fwdcopy(surf->pixels(), tmpbase, tmp - tmpbase);
	surf->set_encoding(RLE_ENCODE);
}
</rlehead></char></rlehead></rlehead>



代码段解码,


Snippet decode,

void std_encode_commit_line_(char* tmpbase, int y, Surface* surf)
/* write decoded line data to surface. */
{
	const PixelBase& op = Pixel.op();

	char* pix = surf->pixels(0, y);
	char* tmp = tmpbase + rlehead::size;

	while ( 1 )
	 {
	   rlehead head(tmp);
	   tmp += head.size;

	   op.hz_fill(pix, surf->col_key(), head.skip);
	   pix += head.skip;

	   if (head.copy == 0)
	      break;
	   fwdcopy(pix, tmp, head.copy);
	   pix += head.copy;
	   tmp += head.copy;
	 }
}

void std_encode_(Surface* surf)
/* decode rle surface. */
{
	char* pixbase = surf->pixels();
	char* pix = rle_advance_scanline_(pixbase, surf->h());

	const int bufsize = pix - pixbase;
	char* tmpbase = new char[bufsize];
	char* tmp = tmpbase;

	fwdcopy(tmpbase, surf->pixels(), bufsize);

	for ( int y = 0; y < surf->h(); y++ )
	 {
	   std_encode_commit_line_(tmp, y, surf);
	   tmp = rle_advance_scanline_(tmp);
	 }

	delete [] tmpbase;
	surf->set_encoding(STD_ENCODE);
}



希望这有帮助。


Hope this helps.


这篇关于如何才能使我的代码达到最佳状态?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆