Mảng biến đổi Paeth


8

Một trong những phần quan trọng của thuật toán nén của PNG là phép biến đổi Paeth, biến đổi hình ảnh theo cách làm cho nó nén tốt hơn (thông thường). Trong thử thách này, nhiệm vụ của bạn là viết một chương trình để tính toán một phép biến đổi Paeth. Hoạt động của một chuyển đổi Paeth được mô tả dưới đây.

Sự chuyển đổi Paeth

Phép biến đổi Paeth trừ đi từng thành viên Xcủa mảng 2 chiều một yếu tố dự đoán. Công cụ dự đoán là phần tử của thành viên mảng ở bên trái ( A), top ( B) và top-left ( C) Xcó giá trị có ít khác biệt nhất A + B - C.

┼─┼─┼
│C│B│
┼─┼─┼
│A│X│
┼─┼─┼

Nếu một trong A, Bhoặc C, nằm ngoài giới hạn, giá trị của nó được thay thế bằng 0. Đây là mã giả từ đặc tả PNG nêu rõ cách tính toán của công cụ dự đoán này:

function PaethPredictor (a, b, c)
begin
     ; a = left, b = above, c = upper left
     p := a + b - c        ; initial estimate
     pa := abs(p - a)      ; distances to a, b, c
     pb := abs(p - b)
     pc := abs(p - c)
     ; return nearest of a,b,c,
     ; breaking ties in order a,b,c.
     if pa <= pb AND pa <= pc then return a
     else if pb <= pc then return b
     else return c
end

Đối với thử thách này, các thành viên mảng là các số tự nhiên trong phạm vi từ 0 đến 255. Nếu phép biến đổi Paeth dẫn đến một giá trị nằm ngoài phạm vi đó, nó sẽ bị giảm modulo 256 thành một giá trị trong phạm vi đó.

Đầu vào và đầu ra

Đầu vào là hai số nguyên xy trong phạm vi từ 2 đến 1023 biểu thị chiều rộng và chiều cao của ma trận để biến đổi và một mảng các phần tử x × y . Đầu vào được định dạng dưới dạng số thập phân cách nhau bởi một ký tự trống được kết thúc bằng nguồn cấp dữ liệu. Đây là những gì đầu vào này có thể trông như sau:

2 3 4 5 6 7 8 9

Điều này sẽ đại diện cho một ma trận 2 nhân 3 với các mục:

4 5
6 7
8 9

Đầu ra phải có cùng định dạng với đầu vào với sự thư giãn rằng các số có thể được phân tách bằng một lượng ký tự khoảng trắng khác không tùy ý (dấu cách, tab ngang hoặc dọc, nguồn cấp dữ liệu hoặc biểu mẫu) và bị chấm dứt bởi một lượng tùy ý ký tự khoảng trắng.

Đầu vào sẽ được nhận từ stdin, đầu ra sẽ đi đến stdout. Nếu điều này là không thể, hãy chọn một cách khác để nhận đầu vào và ghi đầu ra không mã hóa đầu vào.

Hành vi của chương trình của bạn khi được trình bày với đầu vào không hợp lệ không phải là một phần của thách thức này.

Đánh giá và thực hiện tham khảo

Một chương trình ANSI C được cung cấp để tạo đầu vào mẫu, giải quyết các trường hợp và xác minh các giải pháp. Gọi chương trình với gđể g enerate đầu vào, với stới s olve một ví dụ đầu vào và với vtới v erify đúng đắn của một giải pháp.

Nếu bạn nghĩ rằng việc thực hiện tham chiếu là bị lỗi, xin vui lòng cho tôi biết để tôi có thể sửa nó càng sớm càng tốt.

Ví dụ đầu vào và đầu ra

Theo yêu cầu phổ biến.

10 5 166 156 108 96 63 227 122 99 117 135 125 46 169 247 116 55 151 1 232 114 214 254 6 127 217 88 206 102 252 237 75 250 202 145 86 198 172 84 68 114 58 228 66 224 186 217 210 108 11 179

đại diện cho mảng

166 156 108  96  63 227 122  99 117 135
125  46 169 247 116  55 151   1 232 114
214 254   6 127 217  88 206 102 252 237
 75 250 202 145  86 198 172  84  68 114
 58 228  66 224 186 217 210 108  11 179

được chuyển thành

166 246 208 244 223 164 151 233  18  18
215 177 123  78 125  84  96 135 231 138
 89 129   8 121 101 228  55 101  20 123
117 175 196 199 125 112 222 238  72  46
239 234 120 158  41  19  12  24 183 111

được mã hóa thành

10 5 166 246 208 244 223 164 151 233 18 18 215 177 123 78 125 84 96 135 231 138 89 129 8 121 101 228 55 101 20 123 117 175 196 199 125 112 222 238 72 46 239 234 120 158 41 19 12 24 183 111

Điều kiện chiến thắng

Đối với thử thách này, hãy viết chương trình tạo chuyển đổi Paeth chính xác của đầu vào và viết chúng ra. Đây là code-golf, chương trình có số lượng ký tự ít nhất trong mã nguồn của nó sẽ thắng. Vui lòng thử đính kèm một lời giải thích và một phiên bản mã có thể đọc được vào trình của bạn để người khác có thể thấy những gì nó làm.


1
Ý bạn là gì khi " Nếu phép biến đổi Paeth dẫn đến một giá trị nằm ngoài phạm vi đó "? Vì kết quả luôn được rút ra từ một bộ gồm ba yếu tố, tất cả đều nằm trong phạm vi, nên điều này dường như bao trùm một trường hợp không thể.
Peter Taylor

@PeterTaylor Phép biến đổi Paeth dành cho mỗi thành viên mảng, sự khác biệt giữa giá trị của thành viên đó và yếu tố dự đoán cho thành viên đó, có thể âm.
FUZxxl

@ MartinBüttner Điều đó chắc chắn đã trượt qua chỉnh sửa bản sao.
FUZxxl

1
@FUZxxl: Sự thật. Không nhận ra rằng không có thỏa thuận phổ quát về điều đó cho đến một lúc trước. Nhưng đó là một tổng số sang một bên. Thử thách đẹp.
Alex A.

3
Btw, chúc mừng bạn đã đăng câu hỏi không. 3000! (Không tính các câu hỏi đã bị xóa và bị khóa.)
Martin Ender

Câu trả lời:


3

J - 77 char

Thực hiện một cách tiếp cận có vẻ khác với câu trả lời của FUZxxl nhưng thực sự rất giống nhau.

1!:2&4":2({.,|.@{.,@(256|$-0(0{[/:+`-/|@-])"1@|:(-#:1 2 3)|.!.0$)}.)0".1!:1]3

Một số ý kiến ​​về các bit thú vị.

  • 1!:2&4":(...) 0".1!:1]3- Nếu J không tệ về I / O và phân tích cú pháp, điều này có thể được cấu trúc lại để sử dụng &.".&.stdin'', để lưu 3 ký tự. Nhưng nó là như vậy chúng ta không thể. Nghỉ ngơi trong hòa bình, nhân vật quý giá.
  • 2 ({.,|.@{.,@( ... stuff using $ ... )}.)- Điều này tháo rời đầu vào và lắp lại đầu ra. Chúng tôi sử dụng $cả hai như một tham chiếu đến đầu vào stuff using $và như là một hoạt động chúng tôi cần thực hiện trên đầu vào trước khi chạy stuffnó.
  • 0( blah )"1@|:- Có, đó là Transpose dyadic: chúng tôi tập hợp lại ba kết quả xoay dưới dạng trục mảng trong cùng, để logic Paeth có thể áp dụng riêng cho từng bộ "1.
  • 0{[/:+`-/|@-]- Logic Paeth: sắp xếp a,b,ctheo độ lớn của ( ptrừ đi từng điểm a,b,c) và lấy đầu tiên.

Điều này thực sự gọn gàng.
FUZxxl 3/03/2015

2

J, 97 91 88 87 ký tự

Hãy bắt đầu điều này. Thông báo vắng mặt exit; J in một dấu nhắc (ba khoảng trống) sau khi tất cả đầu ra đã được ghi, nhưng sau đó bật EOF stdin, khiến nó chấm dứt.

Tôi tin rằng khá nhiều cải tiến có thể có trong mã này.

1!:2&4":(|.@$,,)256|((-+`-/+[:(>&|{,)"0/]-"2+`-/)(3 2$-*i.3)|.!.0])2(|.@{.$}.)0".1!:1]3

Đây là mã trước khi chơi golf; Nó chủ yếu bằng mã hiện tại.

NB. A, B, and C values
abc =: (0 _1 , _1 0 ,: _1 _1)&(|.!.0)
p =: +`-/@abc
NB. minimum of magnitudes
mmin =: (>&| { ,)"0
pred =: p + [: mmin/ abc -"2 2 p
paeth =: 256 | ] - pred
input =: [: (2&}. $~ 2 |.@{. ]) 0 ". 1!:1
output =: [: 1!:2&4 LF ,~ [: ": |.@$ , ,
output paeth input 3
exit 0

Mã này cung cấp một đầu ra không chính xác: 3 2$-*i:3không tương đương với 0 _1,_1 0,:_1 _1.
thuật toán bắt đầu

@alerskymshark Xin lỗi. tốt hơn theo cách này?
FUZxxl
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.