2010-07-08 77 views
6

Ai cũng có thể cung cấp cho con trỏ cách tôi có thể thực hiện nén/giải nén lzw trong điều kiện bộ nhớ thấp (< 2k). điều đó có thể không?Nén/giải nén LZW trong điều kiện bộ nhớ thấp

+1

môi trường là gì? – ULysses

+0

Tôi cũng cần phải đặt mã này vào một chiếc điện thoại di động thấp cấp .... – Manas

+0

Tôi đã cập nhật thẻ của bạn để thêm 'nhúng' để bạn có thể tiếp xúc với những lập trình viên làm việc với các tài nguyên hạn chế như <2K. Do yêu cầu từ điển, bạn có thể muốn khám phá các thuật toán nén khác (như LZ77?) – tomlogic

Trả lời

0

Đề xuất tốt nhất của tôi là kiểm tra nguồn BusyBox và xem việc triển khai LZW của họ có đủ nhỏ để hoạt động trong môi trường của bạn không.

+0

Có lẽ không - BusyBox dành cho các hệ thống có nhiều tài nguyên hơn. – tomlogic

+1

Bạn đã kiểm tra thay vì chỉ nói "có thể không". Khá nhiều tất cả các thuật toán trong BusyBox là nhỏ nhất (cả về kích thước mã và không gian làm việc) mà bất kỳ nhà phát triển nào cũng có thể tìm thấy/tạo ra, thường là do chi phí của hiệu suất khá.Nếu hiệu suất quá tệ, thường có tùy chọn biên dịch để chọn giữa kích thước nhỏ với hiệu suất kinh khủng và kích thước/hiệu suất vừa phải. –

+0

@tomlogic: hầu hết các triển khai LZW mà tôi đã thấy trong quá khứ có kích thước của từ điển (bộ nhớ chính) như là một định nghĩa thời gian biên dịch. Nó là giá trị kiểm tra. Kích thước tối thiểu của từ điển IIRC là 257 + 1. Nhưng đó sẽ là một tương đương với không nén ở tất cả. – Dummy00001

1

Đã hơn 15 năm kể từ lần cuối tôi chơi với thuật toán nén LZW, vì vậy hãy thực hiện các thao tác sau với một hạt muối.

Với những hạn chế về bộ nhớ, điều này sẽ khó khăn nhất. Từ điển bạn xây dựng sẽ tiêu thụ phần lớn những gì bạn có sẵn. (Giả sử rằng mã + bộ nhớ < = 2k.)

Chọn kích thước cố định nhỏ cho từ điển của bạn. Nói 1024 mục.

Hãy mỗi mục từ điển mang hình thức của ....

struct entry { 
    intType prevIdx; 
    charType newChar; 
}; 

Cấu trúc này làm cho đệ quy điển. Bạn cần mục ở chỉ mục trước có giá trị để nó hoạt động đúng. Điều này có khả thi không? Tôi không chắc. Tuy nhiên, chúng ta hãy giả định cho thời điểm đó là và tìm ra nơi nó dẫn chúng ta ...

Nếu bạn sử dụng các loại tiêu chuẩn cho int và char, bạn sẽ hết bộ nhớ nhanh. Bạn sẽ muốn đóng gói mọi thứ lại với nhau càng chặt càng tốt. 1024 mục sẽ mất 10 bit để lưu trữ. Nhân vật mới của bạn, có thể sẽ mất 8 bit. Tổng cộng = 18 bit.

18 bit * 1024 mục = 18432 bit hoặc 2304 byte.

Thoạt nhìn, điều này xuất hiện quá lớn. Chúng ta làm gì? Tận dụng lợi thế của thực tế là 256 mục đầu tiên đã được biết đến - bộ ascii mở rộng điển hình của bạn hoặc những gì có bạn. Điều này có nghĩa là chúng tôi thực sự cần 768 mục.

768 * 18 bit = 13824 bit hoặc 1728 byte.

Điều này khiến bạn có khoảng 320 byte để phát cùng với mã. Đương nhiên, bạn có thể chơi xung quanh với kích thước từ điển và xem những gì tốt cho bạn, nhưng bạn sẽ không kết thúc với rất nhiều không gian cho mã của bạn. Vì bạn đang tìm kiếm rất ít không gian mã, tôi mong rằng bạn sẽ kết thúc việc lập trình.

Tôi hy vọng điều này sẽ hữu ích.

+0

Có thể loại bỏ từ điển và phân tích lại để chỉ nhận được mục nhập cần thiết từ nguồn trên mọi tra cứu không? Tất nhiên điều này sẽ cực kỳ chậm nhưng nó có thể là cách duy nhất. –

+0

@R ..: Tôi không nghĩ vậy. Từ điển là trạng thái của en/decoder. Các bit trong luồng được mã hóa là các chỉ mục trong từ điển. – Dummy00001

4

Thư viện zlib mà mọi người sử dụng đều cồng kềnh trong số các vấn đề khác (để nhúng). Tôi khá chắc chắn nó sẽ không làm việc cho trường hợp của bạn. Tôi đã có một bộ nhớ nhiều hơn một chút có thể 16K và không thể làm cho nó phù hợp. Nó phân bổ và zeros khối lớn của bộ nhớ và giữ bản sao của các công cụ, vv Các thuật toán có thể có thể làm điều đó, nhưng việc tìm kiếm mã hiện tại là thách thức.

Tôi đã đi với http://lzfx.googlecode.com Vòng giải nén là nhỏ, nó là loại nén lz cũ dựa vào kết quả trước, do đó bạn cần truy cập vào kết quả không nén ... byte tiếp theo là 0x5, byte tiếp theo là 0x23, 15 byte tiếp theo là bản sao của 15 200 byte trước, 6 byte tiếp theo là bản sao của 127 trước ... thuật toán lz mới hơn là bảng chiều rộng biến có thể lớn hoặc lớn tùy thuộc vào cách được triển khai .

Tôi đã xử lý dữ liệu lặp đi lặp lại và cố gắng nén một vài K xuống vài trăm, tôi nghĩ rằng nén là khoảng 50%, không lớn nhưng công việc và thói quen giải nén rất nhỏ.Gói lzfx ở trên là nhỏ, không giống như zlib, giống như hai hàm chính có mã ngay tại đó, không phải hàng tá tệp. Bạn có thể thay đổi độ sâu của bộ đệm, có lẽ cải thiện thuật toán nén nếu bạn mong muốn. Tôi đã phải sửa đổi các mã giải nén (như 20 hoặc 30 dòng mã có lẽ) nó đã được con trỏ nặng và tôi chuyển nó sang mảng vì trong môi trường nhúng của tôi các con trỏ ở sai vị trí. Ghi có thể là một đăng ký thêm hoặc không phụ thuộc vào cách bạn thực hiện nó và trình biên dịch của bạn. Tôi cũng đã làm điều đó vì vậy tôi có thể tóm tắt các fetches và các cửa hàng của các byte như tôi đã có chúng đóng gói vào bộ nhớ mà không phải là byte địa chỉ.

Nếu bạn tìm thấy điều gì đó tốt hơn, hãy đăng nó ở đây hoặc ping tôi qua stackoverflow, tôi cũng rất quan tâm đến các giải pháp nhúng khác. Tôi tìm kiếm khá một chút và ở trên là một trong những hữu ích duy nhất tôi tìm thấy và tôi đã may mắn rằng dữ liệu của tôi là như vậy mà nó nén đủ tốt bằng cách sử dụng thuật toán đó ... cho bây giờ.

+1

Có một chương trình nén được gọi là pucrunch http://www.cs.tut.fi/~albert/Dev/pucrunch/ có thể bạn sẽ thấy thú vị. – ninjalj

+0

Tôi đã tìm thấy http://www.embedded.com/design/opensource/217800397 Điều này cho biết "Kỹ thuật nén này có khả năng đạt được tỷ lệ nén đáng kính, thường là theo thứ tự 50" 60%, trong khi tiêu thụ khoảng 2K RAM ".... Tôi cần phải thử này ra – Manas

3

Ai cũng có thể cung cấp cho con trỏ cách tôi có thể triển khai nén/giải nén lzw trong điều kiện bộ nhớ thấp (< 2k). điều đó có thể không?

Vì sao LZW? LZW cần rất nhiều bộ nhớ. Nó dựa trên tỷ lệ băm/từ điển và nén tỉ lệ thuận với kích thước băm/từ điển. Nhiều bộ nhớ hơn - nén tốt hơn. Ít bộ nhớ hơn - đầu ra có thể lớn hơn đầu vào.

Tôi chưa chạm mã hóa cho thời gian dài rất, nhưng IIRC Huffman coding thì tốt hơn một chút khi nói đến mức tiêu thụ bộ nhớ.

Nhưng tất cả phụ thuộc vào loại thông tin bạn muốn nén.

2

Nếu lựa chọn thuật toán nén không được đặt trong đá, bạn có thể thử gzip/LZ77 thay thế. Dưới đây là một thực hiện rất đơn giản tôi đã sử dụng và thích nghi một lần:

ftp://quatramaran.ens.fr/pub/madore/misc/myunzip.c

Bạn sẽ cần phải dọn dẹp đường nó đọc đầu vào, xử lý lỗi, vv nhưng đó là một khởi đầu tốt. Nó có lẽ cũng là cách quá lớn nếu dữ liệu và mã của bạn cần phải phù hợp trong 2k, nhưng ít nhất là kích thước dữ liệu là nhỏ rồi.

Điểm cộng lớn là miền công cộng nên bạn có thể sử dụng nó theo cách bạn muốn!

+1

liên kết của bạn với việc thực hiện doen't làm việc – Paha

2

Tôi đã sử dụng LZSS. Tôi đã sử dụng code từ Haruhiko Okumura làm cơ sở. Nó sử dụng phần cuối của dữ liệu không nén (2K) làm từ điển. Mã tôi liên kết có thể được sửa đổi để sử dụng gần như không có bộ nhớ nếu bạn có tất cả các dữ liệu chưa nén sẵn có trong bộ nhớ. Với một chút googling bạn sẽ thấy rằng rất nhiều triển khai khác nhau.

-3
typedef unsigned int  UINT; 
typedef unsigned char BYTE; 

BYTE *lzw_encode(BYTE *input ,BYTE *output, long filesize, long &totalsize); 
BYTE *lzw_decode(BYTE *input ,BYTE *output, long filesize, long &totalsize); 
+2

-1 Làm thế nào điều này sẽ trả lời câu hỏi? Ở đâu là một mô tả hoặc liên kết cho thư viện. Hoặc infos về kích thước hoặc cái gì khác – jeb

Các vấn đề liên quan