Mã hóa một hình ảnh bên trong nguồn


10

Thử thách chơi gôn là mã hóa và nén hình ảnh sau trong tệp nguồn.

Hình ảnh

Để thực hiện việc này, bạn cần viết 3 hàm : red, greenbluechấp nhận tọa độ x / y của hình ảnh và trả về giá trị pixel R / G / B tương ứng trong khoảng 0-255.

Đây là mã kiểm tra C / C ++:

#include <stdio.h>
#include "your_file"
int main() {
  int x, y;
  for(y = 0; y < 32; ++y)
  for(x = 0; x < 32; ++x)
    printf("%i %i %i\n", red(x, y), blue(x, y), green(x, y));
}

Và đầu ra: http://pastebin.com/A770ckxL (bạn có thể sử dụng điều này để tạo dữ liệu hình ảnh của mình)

Quy tắc & chi tiết:

  • Đây là một sân gôn
  • Chỉ mã / tệp của bạn được đánh gôn - mã kiểm tra là riêng biệt
  • Bộ ký tự được sử dụng là ASCII, tuy nhiên, các ký tự điều khiển trong chuỗi chỉ có thể được sử dụng nếu được thoát (như '\ n' và '\ r', v.v.)
  • Mọi thứ phải được chứa trong nguồn - không tải tập tin
  • Đầu ra của bạn phải phù hợp với đầu ra ví dụ. Điều này có nghĩa là nén không thua lỗ.

Ngôn ngữ:

Vấn đề được viết với C / C ++, nhưng tôi đang loại bỏ những hạn chế đó. Như đã nói, tôi vẫn sẽ khuyên bạn nên sử dụng chúng.


4
Nếu không có lý do cụ thể để làm như vậy, việc sửa một câu hỏi sang một ngôn ngữ cụ thể rất không được khuyến khích. Lý do tại sao một người không phải sử dụng các ngôn ngữ khác là gì?
FUZxxl

3
Nếu một giải pháp ít thú vị hơn, đừng bỏ phiếu. Cấm các giải pháp "khập khiễng" bằng cách loại trừ các ngôn ngữ là quá mức cần thiết.
FUZxxl

2
Nếu bạn đã giới hạn ký tự được đặt thành ASCII (mà tôi cho là hoàn toàn ổn), làm thế nào chúng ta có thể sử dụng các bản hack Unicode? Đối với cơ sở 64, bạn có thể thực hiện điều đó bên trong tiêu chuẩn C cũng như bất kỳ ngôn ngữ nào khác, nó chỉ có số lượng mã trình bao bọc khác nhau. - Nhưng tôi thích nhiệm vụ.
đã ngừng quay ngược chiều

1
Hmm, còn các ký tự điều khiển ASCII 0-31 (và 127) thì sao? Về mặt kỹ thuật, chúng là một phần của ASCII, nhưng chúng có được phép không? Và nếu không, tôi hy vọng một ngoại lệ ít nhất được tạo ra cho nhân vật LF (10), và có lẽ CR (13) và TAB (9) nữa?
Ilmari Karonen

1
Ừm ... vì vậy, đọc phiên bản mới của bạn theo nghĩa đen, tất cả các giải pháp phải nằm trên một dòng, vì các nguồn cấp dữ liệu không được phép không được phép. Đó thực sự là những gì bạn dự định?
Ilmari Karonen

Câu trả lời:


6

C, 796 754 712 703 692 685 682 670 666 662 656 648 ký tự

Thay đổi:

  • 754-> 712: Được thêm returnvào #define, thay thế ifvới ?báo cáo (nhờ @FUZxxl), loại bỏ inttừ các chức năng tham số danh sách.
  • 712-> 703: Sao chép không biết xấu hổ từ bunnit một lần nữa :) Đã chuyển toàn bộ sáng tạo hình ảnh vào #define
  • 703-> 692: Đã hợp nhất p[]h[], một số ?:cải tiến khác
  • 692-> 685: incrementing bnên ikhông cần thiết nữa. m=bthay vì m=11n<2e3thay vì i<356- những thứ này gần với tham nhũng hành vi / bộ nhớ không xác định, nhưng có vẻ như tôi may mắn :)
  • 685-> 682: khiện tại (32,16,8,4,2,1,0) thay vì (5,4,3,2,1,0). Gotcha, DC;)
  • 682-> 670: Tách p[]h[], được chuyển đổi h[]thành char*- awwww, có một con mèo buồn ngủ trong đó^<+_=>-
  • 670-> 666: while=> for, l=l*2+...=>l+=l+...
  • 666-> 662: m=m>9?...=>c[n++]=m>9?...
  • 662-> 656: Đảo ngược thứ tự bit trong b[], vì vậy chúng ta có thể ánh xạ tới 64-127 thay vì 0-63 và không cần chỉ số bit knữa. Cảm ơn @Piotr Tarsa . Đã thay thế ?:(phần mở rộng GCC) bằng|| . Cảm ơn @JamesB
  • 656-> 648: Bản sao không biết xấu hổ từ Shelwien :) (hằng số nhiều ký tự cho p[])

Hình ảnh được chuyển đổi thành chuỗi giống Base64 (ASCII 37-100), sử dụng mã hóa huffman để mã hóa màu 0-9 bằng 3-6 bit và màu 10 đặc biệt (pixel giống như trước đó) chỉ sử dụng 1 bit.

#define P (x,y){for(;n<2e3;j/=2){j>1||(j=*b+++27);l+=l+(j&1);for(m=0;m<11;m++)l-h[m]+32||(c[n++]=m>9?c[n-1]:m,l=0,m=b);}return 255&p[c[x+y*32]]
char*h="$^<+_=>-,* ",*b="F0(%A=A=%SE&?AEVF1E01IN8X&WA=%S+E+A-(,+IZZM&=%]U5;SK;cM84%WE*cAZ7dJT3R.H1I2@;a^/2DIK&=&>^X/2U*0%'0E+;VC<-0c>&YU'%],;]70R=.[1U4EZ:Y=6[0WU4%SQARE0=-XDcXd_WW*UAF&cFZJJ0EV*(a(P05S3IXA>51cH:S5SAE6+W%/[]7SF(153UM]4U()(53DA+J:]&5+5KX,L6>*4I,/UMBcML9WKLa9%UYIHKWW(9-*):(-ZW(9%T'N&9;C,C/Ea/Y7(JJ\\6CD9E,2%J*,ac]NIW8(M=VFac)/^)?IS-;W&45^%*N7>V,,C-4N35FMQaF,EaWX&*EJ4'";p[]={0,'R@+','aXL',7783255,'4k`',16354410,'NNv',5295994,4671418,9975021},c[1024],j,l,m,n;red P;}blue P>>16;}green P>>8;}

Sao chép hai điều từ câu trả lời của bunnit, #definevà toàn bộ hình ảnh được giải mã hoàn toàn mỗi lần red/ green/ blueđược gọi. Có một số chỗ để cải tiến bổ sung, vì vậy hãy chờ đợi một số cập nhật :) Tôi không chắc chắn về việc tuân thủ mã, đã sử dụng GCC 4.6.1 để biên dịch và kiểm tra.

Nén-khôn ngoan, tôi nghĩ rằng mã hóa số học sẽ giúp ích vì phân phối khá sai lệch, nhưng có lẽ chi phí mã sẽ quá nặng trong trường hợp này. LZW cũng nên làm một công việc rất tốt. Màu sắc khá cục bộ, vì vậy mã hóa thích ứng có thể là một ý tưởng.

Phiên bản 754 ký tự dễ đọc hơn với một số bình luận:

#define P 255&p[c[x+y*32]]
// Base64 coded image bitstream, ASCII 37-100
// Huffman codes: 100, 111110, 11100, 1011, 111111, 11101, 11110, 1101, 1100, 1010, 0
char b[]="FYU%3+3+%B&E;3&HF1&Y1.JWXE83+%B=&=3)U]=.PP*E+%,('?B>?D*Wa%8&MD3P7dNbARIV1.Q[?4L9Qc.>E+EKLX9Q(MY%5Y&=?HC_)YDKE0(5%,]?,7YR+I@1(a&PO0+G@Y8(a%B23R&Y+)XcDXd<88M(3FEDFPNNY&HMU4UZY'BA.X3K'1DVOB'B3&G=8%9@,7BFU1'A(*,a(U-U'Ac3=NO,E'='>X]^GKMa.]9(*SD*^/8>^4/%(0.V>88U/)M-OU)P8U/%b5JE/?C]C9&4907UNN`GCc/&]Q%NM]4D,J.8WU*+HF4D-9L-;.B)?8Ea'L%MJ7KH]]C)aJA'F*24F]&48XEM&Na5";
// Colors, order GBR (one char shorter than all the others)
p[]={0,5390379,6379596,7783255,3435360,16354410,5131894,5295994,4671418,9975021};
// Huffman codes for colors 0-10
h[]={4,62,28,11,63,29,30,13,12,10,0};
// Array for image data
c[1024];
i,j,k,l,m,n;
red(int x,int y){
  while(i<356){
    k--;
    if (k<0) {
      j=b[i++]-37;
      k=5;
    }
    l*=2;
    if (j&(1<<k)) l++;
    for(m=0;m<11;m++){
      if(l==h[m]){
        if (m>9) m=c[n-1];
        c[n++]=m;
        l=0;
        m=12;
      }
    }
  }
  return P;
}
blue(int x,int y){return P>>16;}
green(int x,int y){return P>>8;}

Rất hay, không thể tin rằng tôi đã không nghĩ đến việc sử dụng cơ sở 64. Tôi nghĩ rằng bạn vẫn có thể lưu khá nhiều ký tự, đặc biệt là trong vòng lặp đó. Hoạt động tốt trong VS2008 btw.
Scott Logan

Tôi nghĩ rằng bạn có thể xóa đó intkhỏi danh sách tham số để xóa thêm một số byte.
FUZxxl

Làm thế nào về m=m>9?c[n-1]:m;cho if(m>9)m=c[n-1];?
FUZxxl

Và cũng: if(k<0){j=b[i++]-37;k=5;}tại sao không k>=0?:(j=b[i++]-37,k=5);? (Mã này sử dụng phần mở rộng C của gcc, x=a?:bgiống như x=a?a:b, với sự khác biệt mà a chỉ được đánh giá một lần.
FUZxxl

red(x,y){while(i<356){--k>=0?:(j=b[i++]-37,k=5);l*=2;if(j&(1<<k))l++;for(m=0;m<11;m++)l!=h[m]?:(m=m<=9?:c[n-1],c[n++]=m,l=0,m=12);}return P;}
FUZxxl

4

Con trăn ( 684 592 ký tự)

red,blue,green=[lambda x,y,i=i:[15570996,2839104,7010700,5732035,6304875,0,12207943,8016079,7753294,5005656][int('eJxtkgGSxSAIQ6+kaLTe/2JLImj7Z9MZ6/gMIgjAzMbVWisGySRNm2ut5Hhx/2M0JMfHH5PWwo9x4mNO8pb6JkFM3hpqrR4+qY6eVK1mjlsFeSOBjPyCMy3348aXVRtq9X8czovMIwA5FeXKtGOcvfcf/lbvyW0n2BTOh122HiIH0g/uNrx47zupzMxuuTv808pZd3K7deJ/+PiH61AztmaNwPAsOnNGYovWIxswRill6vnAL4HgxDF17jFcjwRk/5b3Q1x1flLI9n64CIci8bmQe7NL8XoKliu+Jk/AR9rnjkwAYaDka8OXu/a+5NvvNzkcmqifL47H04kAz9M+9slKkDMGuOHi5PR7GZwv7MeApkz5JOSPHFVW3QTbzDJtzDIczkuWjeupLbckLyU5/gByftMg'.decode('base64').decode('zip')[32*y+x])]>>i&255 for i in 16,8,0]

Vì thử thách này hiện đang mở cho tất cả mọi người, tại sao không! Đó là tuyến mã hóa zlib quen thuộc -> base64, vì vậy tôi xin lỗi vì điều đó. Hy vọng rằng một mục với một số ngữ nghĩa của sự khéo léo sẽ ngắn hơn!

Đây là một đoạn kiểm tra tương tự như bản gốc:

for y in range(32):
    for x in range(32):
        print red(x,y), blue(x,y), green(x,y)

Bạn cũng nên thử thêm một màu đặc biệt để lặp lại giá trị pixel trước đó. 588 chars base64 lớn hơn nhiều so với chuỗi trong câu trả lời của tôi (365 ký tự) và mặc dù zLib quá mức cần thiết ở đây, nhưng nó sẽ cho kết quả tương tự, vì vậy có thể có khoảng 500 ký tự theo cách này.
schnaader

4

C ++, 631 ký tự; C - 613

Một bộ mã hóa mtf cơ sở 92, C ++, 631 ký tự:

#define A(Z)int Z(int X,int Y){char*s="xdGe*V+KHSBBGM`'WcN^NAw[,;ZQ@bbZVjCyMww=71xK1)zn>]8b#3&PX>cyqy@6iL?68nF]k?bv/,Q`{i)n[2Df1zR}w0yIez+%^M)Diye{TC]dEY\\0,dU]s'0Z?+bo;7;$c~W;tvFl%2ruqWk$Rj0N[uP)fSjk?Tnpn_:7?`VbJ%r@7*MQDFCDo3)l#ln<kuRzzHTwCg&gYgSXtv\\m_Eb}zRK7JK<AZzOe}UX{Crk)SyBn;;gdDv=.j*O{^/q6)`lHm*YYrdM/O8dg{sKW#B3BLMiI8@-Zo-EsgE.R#viYL$-<EU*~u5pe$r:`b)^dgXOJtf4";int*v,B=92,R=1,C=0,w[]={0,16354410,4671418,'aXL',7783255,5295994,'R@+','4k`',9975021,'NNv'};for(X+=Y*32+1;X--;)for(v=w;;){for(Y=*v++;R<B*B*B;C=C%R*B+*s++-35)R*=B;if(R/=2,C>=R){for(C-=R;--v>w;*v=v[-1]);*v=Y;break;}}return 255&Y
A(red);}A(blue)>>16;}A(green)>>8;}

Và phiên bản C ở trên (613 ký tự):

#define A (X,Y){char*s="xdGe*V+KHSBBGM`'WcN^NAw[,;ZQ@bbZVjCyMww=71xK1)zn>]8b#3&PX>cyqy@6iL?68nF]k?bv/,Q`{i)n[2Df1zR}w0yIez+%^M)Diye{TC]dEY\\0,dU]s'0Z?+bo;7;$c~W;tvFl%2ruqWk$Rj0N[uP)fSjk?Tnpn_:7?`VbJ%r@7*MQDFCDo3)l#ln<kuRzzHTwCg&gYgSXtv\\m_Eb}zRK7JK<AZzOe}UX{Crk)SyBn;;gdDv=.j*O{^/q6)`lHm*YYrdM/O8dg{sKW#B3BLMiI8@-Zo-EsgE.R#viYL$-<EU*~u5pe$r:`b)^dgXOJtf4";int*v,B=92,R=1,C=0,w[]={0,16354410,4671418,'aXL',7783255,5295994,'R@+','4k`',9975021,'NNv'};for(X+=Y*32+1;X--;)for(v=w;;){for(Y=*v++;R<B*B*B;C=C%R*B+*s++-35)R*=B;if(R/=2,C>=R){for(C-=R;--v>w;*v=v[-1]);*v=Y;break;}}return 255&Y
red A;}blue A>>16;}green A>>8;}

Chỉ cần bao gồm một mục với dữ liệu cơ sở 95 và mã hóa số học + mô hình thống kê thích ứng.
Mã schnaader sử dụng ~ 438 ký tự cho dữ liệu và chỉ khai thác được 318 (mặt nạ 311 w / o).
Nhưng như mong đợi, mã hóa số học quá phức tạp đối với một mẫu nhỏ như thế này.

(Đây là 844 ký tự)

char* q="q^<A\">7T~pUN1 adz824K$5a>C@kC8<;3DlnF!z8@nD|9D(OpBdE#C7{yDaz9s;{gF[Dxad'[oyg\\,j69MGuFcka?LClkYFh=:q\\\\W(*zhf:x)`O7ZWKLPJsP&wd?cEu9hj 6(lg0wt\\g[Wn:5l]}_NUmgs]-&Hs'IT[ Z2+oS^=lwO(FEYWgtx),)>kjJSIP#Y?&.tx-3xxuqgrI2/m~fw \\?~SV={EL2FVrDD=1/^<r*2{{mIukR:]Fy=Bl.'pLz?*2a? #=b>n]F~99Rt?6&*;%d7Uh3SpLjI)_abGG$t~m{N=ino@N:";
#define I int
#define F(N) for(i=0;i<N;i++)
#define Z C=(C%T)*B+(*q++)-32
enum{B=95,H=1024,T=B*B*B};I p[B],v[B+H],n=3,*m=&v[B],R=T*B,C,i,j,y,c,x,w;void D(I P){w=(R>>11)*P;(y=C>=w)?R-=w,C-=w:R=w;while(R<T)R*=B,Z;}struct u{u(){F(4)Z;F(B)p[i]=H,v[i]=0;F(H){v[0]=m[i-1];v[1]=m[i-32];j=i;F(n){I&P=p[i];D(P);if(y){P-=P>>4;c=v[i];goto t;}else P+=H+H-P>>4;}c<<=7;for(x=-255;x<0;x+=x+y)D(H);v[n++]=c=x;t:m[i=j]=c;}}}d;I red(I x,I y,I z=0){return m[y*32+x]>>z&255;}
#define blue(x,y) red(x,y,8)
#define green(x,y) red(x,y,16)

Các thử nghiệm (từ phiên bản cơ sở 96 trước đó):
http://codepad.org/qrwuV3Oy
http://ideone.com/ATngC

Bằng cách nào đó SO ăn mã 7F, vì vậy tôi đã phải cập nhật nó lên base = 95


3

C ++ - 1525 1004 964 ký tự

#define e (int x,int y){for(i=g=0;i<702;i=i+2)for(j=48;j<d[i];++j)c[g++]=d[i+1]-48;return 255&z[c[x+y*32]]
int i,g,j,z[]={0,7010700,12207943,5005656,5732035,8016079,2839104,6304875,15570996,7753294},c[1024];
char*d="3031;23322337261524453223310625132101214103453101233722172643310323342102521229492333210352112241036141014821042552621241014161016141024121022103210151015104526211034361034726510352625107441:530855425201511551045378554>55755312410242035201510528725212044451015411032:73135216561321012171017101725313581125152572531358122415257257110213310131231422022172025105110315322103210623815203110113053521053223817506920721013361322282530991062101213361322282520491049682224133614121028101510291029;812341023342835694810582018841018356978194810842835193329781019482410542835192310193668399428454319362928102829843845331019263028101330441014382035104369285338101810284536334910291018534820283546891019102943883536";
int red e>>16;}
int blue e>>8;}
int green e;}

Tạo một mảng z lưu trữ tất cả các màu có thể dưới dạng một số nguyên duy nhất. (R << 16 | g << 8 | b). Đã tạo một mảng d lưu trữ {lượng, giá trị}, giá trị là vị trí trong mảng z, số lượng là số pixel liên tiếp với giá trị đó. (Tức là 3.0, có nghĩa là colout t [0] xuất hiện 3 tiếp theo pixel. Mảng pixel thực tế (c) sau đó được tính mỗi khi màu đỏ được gọi. Giá trị trong mảng sau đó được dịch chuyển sang phải và ANDed khi cần thiết để có được thành phần chính xác.

Tôi có thể có thể lưu thêm một vài ký tự (~ 50) bằng cách lấy thêm các mẫu ra khỏi mảng như định nghĩa.

Chỉnh sửa 1 - đã thay đổi mảng d cho một mảng char với mỗi giá trị được bù bằng 48, có nghĩa là tôi có thể biểu diễn nó dưới dạng một chuỗi lưu một dấu phẩy.

Chỉnh sửa 2 - Lấy một phần lớn hơn của các hàm trong câu lệnh xác định.


Tại sao bạn không sử dụng C? Trong C, có thể xóa tên loại khỏi intint f(int x,int y)f(x,y)
decaratrion

@FUzxxl, có C hầu như sẽ luôn ngắn hơn C ++ nhưng tôi không thực sự sử dụng C hàng ngày và không thực sự biết tất cả các sắc thái có thể được sử dụng để giảm độ dài. Tôi không bận tâm bằng cách cố gắng để giành chiến thắng, tôi chỉ cố gắng đánh bại bất kỳ câu trả lời C ++ nào khác.
Scott Logan

3

Javascript, 696 694 ký tự

Cảm ơn schnaader cho 696 -> 694.

Tôi đã tìm ra một định dạng mã hóa khác, về cơ bản là mã hóa Run-length với bảng tra cứu màu. Nó hoạt động khá tốt, vì có ít hơn 16 màu và chúng xuất hiện ít hơn 16 lần liên tiếp; vì vậy mọi định nghĩa pixel bao gồm cả độ dài vừa với một byte. Tôi đặt màu ở phần cao của byte và số đếm ở phần thấp.

Cuối cùng, chuỗi base64 hóa ra dài hơn tôi mong đợi (472 ký tự), nhưng chương trình giải mã thực sự ngắn.

for(b=i=a=[];a&15||(a=atob("AxMrMyIzJxYlRDUiMwEmFSMBIUEBQzUBITMnEidGMwEjMyQBUhIi
SSkzIwFTEiFCAWNBAUEoASRVYhJCAUFhAWFBAUIhASIBIwFRAVEBVGISAUNjAUMnVgFTYlIBRxRaA1hF
UgJREVUBVHNYRV51VRNCAUICUwJRASV4UhICRFQBURQBI3oTUxJWFiMBIXEBcQFxUhNTGCEVJXVSE1MY
IhQldVIXARIzATEhEyQCInECUgEVARM1IgEjASaDUQITAREDNSUBNSKDcQWWAicBMWMxIoJSA5kBJgEh
MWMxIoJSApQBlIYiQjFjQSEBggFRAZIBkoshQwEyQ4JTloQBhQKBSAGBU5aHkYQBSIJTkTOShwGRhEIB
RYJTkTIBkWOGk0mCVDSRY5KCAYKSSINUMwGRYgOCATEDRAFBgwJTATSWgjWDAYEBglRjM5QBkgGBNYQC
glNkmAGRAZI0iFNjAQ==").charCodeAt(i++));b.push([0,16354410,4671418,6379596,77832
55,5295994,5390379,3435360,9975021,5131894][a-- >>4]));green=(red=function(c,d){
return b[32*d+c]>>this&255}).bind(16);blue=red.bind(8)

Lưu ý: Tôi tách mã để có một chút dễ đọc. Nó cần phải ở trên một dòng để chạy.

Mã kiểm tra:

for(var y = 0; y < 32; ++y) {
    for(var x = 0; x < 32; ++x) {
        console.log(red(x, y), green(x, y), blue(x, y));
    }
}

Tôi nghĩ rằng kết quả ví dụ thực sự là đầu ra của màu đỏ, xanh lá cây, xanh dương (không phải đỏ, xanh dương, xanh lục như trong mã kiểm tra ban đầu); nó làm việc cho tôi như thế nào


Hãy thử thay đổi mảng bảng màu thành [0,16354410,4671418,6379596,7783255,5295994,5390379,3435360,9975021,5131894]- điều này sẽ tiết kiệm 1 ký tự và là thứ tự GBR thay vì RGB.
schnaader

@schnaader Cảm ơn. Tôi yêu những tối ưu hóa vi mô đó :-) Chỉnh sửa: Nó thậm chí còn lưu 2 ký tự vì tôi đã sử dụng màu xanh hai lần trong nguồn gốc của mình
sao chép

2

C ++, 1357 ký tự

int i,j,C[]={0,0,0,106,249,140,186,71,71,76,97,88,87,118,195,122,80,207,43,82,64,96,52,107,237,152,52,118,78,78},E[]={30,31,112,33,22,33,72,61,52,44,53,22,33,10,62,51,32,10,12,14,10,34,53,10,12,33,72,21,72,64,33,10,32,33,42,10,25,21,22,94,92,33,32,10,35,21,12,24,10,36,14,10,14,82,10,42,55,26,21,24,10,14,16,10,16,14,10,24,12,10,22,10,32,10,15,10,15,10,45,26,21,10,34,36,10,34,72,65,10,35,26,25,10,74,41,105,30,85,54,25,20,15,11,55,10,45,37,85,54,145,57,55,31,24,10,24,20,35,20,15,10,52,87,25,21,20,44,45,10,15,41,10,32,107,31,35,21,65,61,32,10,12,17,10,17,10,17,25,31,35,81,12,51,52,57,25,31,35,81,22,41,52,57,25,71,10,21,33,10,13,12,31,42,20,22,17,20,25,10,51,10,31,53,22,10,32,10,62,38,15,20,31,10,11,30,53,52,10,53,22,38,17,50,69,20,72,10,13,36,13,22,28,25,30,99,10,62,10,12,13,36,13,22,28,25,20,49,10,49,68,22,24,13,36,14,12,10,28,10,15,10,29,10,29,118,12,34,10,23,34,28,35,69,48,10,58,20,18,84,10,18,35,69,78,19,48,10,84,28,35,19,33,29,78,10,19,48,24,10,54,28,35,19,23,10,19,36,68,39,94,28,45,43,19,36,29,28,10,28,29,84,38,45,33,10,19,26,30,28,10,13,30,44,10,14,38,20,35,10,43,69,28,53,38,10,18,10,28,45,36,33,49,10,29,10,18,53,48,20,28,35,46,89,10,19,10,29,43,88,35,36,10};int*Q(int n){for(i=0;1;i++){for(j=0;j<E[i]/10;j++){if(!n)return&C[E[i]%10*3];n--;}}}
#define red(x,y) Q(x+32*y)[0]
#define blue(x,y) Q(x+32*y)[1]
#define green(x,y) Q(x+32*y)[2]

Khử nhiễu một chút:

int C[]={0,0,0,106,249,140,186,71,71,76,97,88,87,118,195,122,80,207,43,82,64,96,52,107,237,152,52,118,78,78},
int E[]={30,31,112,33,22,33,72,61,52,44,53,22,33,10,62,51,32,10,12,14,10,34,53,10,12,33,72,21,72,64,33,10,32,33,42,10,25,21,22,94,92,33,32,10,35,21,12,24,10,36,14,10,14,82,10,42,55,26,21,24,10,14,16,10,16,14,10,24,12,10,22,10,32,10,15,10,15,10,45,26,21,10,34,36,10,34,72,65,10,35,26,25,10,74,41,105,30,85,54,25,20,15,11,55,10,45,37,85,54,145,57,55,31,24,10,24,20,35,20,15,10,52,87,25,21,20,44,45,10,15,41,10,32,107,31,35,21,65,61,32,10,12,17,10,17,10,17,25,31,35,81,12,51,52,57,25,31,35,81,22,41,52,57,25,71,10,21,33,10,13,12,31,42,20,22,17,20,25,10,51,10,31,53,22,10,32,10,62,38,15,20,31,10,11,30,53,52,10,53,22,38,17,50,69,20,72,10,13,36,13,22,28,25,30,99,10,62,10,12,13,36,13,22,28,25,20,49,10,49,68,22,24,13,36,14,12,10,28,10,15,10,29,10,29,118,12,34,10,23,34,28,35,69,48,10,58,20,18,84,10,18,35,69,78,19,48,10,84,28,35,19,33,29,78,10,19,48,24,10,54,28,35,19,23,10,19,36,68,39,94,28,45,43,19,36,29,28,10,28,29,84,38,45,33,10,19,26,30,28,10,13,30,44,10,14,38,20,35,10,43,69,28,53,38,10,18,10,28,45,36,33,49,10,29,10,18,53,48,20,28,35,46,89,10,19,10,29,43,88,35,36,10};
int*Q(int n){
  for(int i=0;1;i++){
    for(int j=0;j<E[i]/10;j++){
      if(!n)return&C[E[i]%10*3];
      n--;
    }
  }
}
#define red(x,y) Q(x+32*y)[0]
#define blue(x,y) Q(x+32*y)[1]
#define green(x,y) Q(x+32*y)[2]

Cchứa các giá trị RGB cho mười màu riêng biệt của hình ảnh. Echứa dữ liệu cho hình ảnh, trong đó mỗi phần tử E[i]mã hóa cả số lần lặp lại E[i]/10và chỉ số màu E[i]%10.


+1 Bạn có thể tắt một vài ký tự trong vòng lặp: pastebin.com/2UY8H2qt
Pubby

1
Nếu bạn đặt lại thương hiệu cho giải pháp của mình là C (không yêu cầu thay đổi mã) và biến định nghĩa thành các hàm loại không có tên như int red(x,y){R Q(x+32*y)[0]}(only # notify` return), thì bạn có thể cạo được nhiều ký tự hơn.
FUZxxl

1
Bằng cách nào đó, đây là gian lận, vì màu đỏ, xanh dương và xanh lá cây không phải là chức năng mà là macro.
FUZxxl

1
Điều này thực hiện một chức năng và ngắn hơn (1339 byte). Xin lưu ý rằng chương trình này có lẽ chỉ có hiệu lực trong đồng bằng cũ C: hpaste.org/65584
FUZxxl

Tôi loại bỏ tất cả các thông tin loại từ nguồn. Nó vẫn còn hiệu lực C.
FUZxxl

1

Python 3 (589 ký tự)

import base64,zlib
red,blue,green=(lambda x,y,i=i:b'\xed\x984+R@j\xf9\x8cWv\xc3`4k\0\0\0\xbaGGzP\xcfvNNLaX'[zlib.decompress(base64.decodebytes(b'eJxtkgGSxSAIQxWN1vtfeEkEbf9sOmMdn0EEAZjZuFprxSCZpGlzrZUcL+5/jIbk+Phj0lr4MU58zEneUt8kiMlbQ63VwyfV0ZOq1cxxqyBvJJCRX3Cm5X7c+LJqQ63+j8N5kXkEIKeiXJl2jLP3/sPf6j257QSbwvmwy9ZD5ED6wd2GF+99J5WZ2S13h39aOetObrdO/A8f/3AdasbWrBEYnkVnzkhs0XpkA8YopUw9H/glEJw4ps49huuRgOzf8n6Iq85PCtneDxfhUCQ+F3JvdileT8FyxdfkCfhI+9yRCSAMlHxt+HLX3pd8+/0mh0MT9fPF8Xg6EeB52sc+WQlyxgA3XJycfi+D84X9GNCUKZ+E/JGjyqqbYJtZpo1ZhsN5ybJxPbXlluSlJMcf++8TIA=='))[32*y+x]*3+i]for i in(0,1,2))

Mã kiểm tra

for y in range(32):
    for x in range(32):
        print(red(x,y), blue(x,y), green(x,y))

Dựa trên giải pháp từ Dillon Cower


1

PHP (5.4) - 822

Tôi đã cố tình không sử dụng bất kỳ chức năng nén tích hợp nào . Giải pháp này chưa kết thúc, tôi không chắc là tôi đã từ bỏ chưa, tôi có thể thấy các khu vực cần cải thiện nhưng tôi không thể tìm thấy thời gian / ý chí để cấu trúc lại toàn bộ vào lúc này, vì vậy tôi đang đăng những gì tôi có cho đến nay

Dòng mới + bình luận sẽ bị xóa cho 822 byte.

// Colour map
$c=[0,16354410,4671418,6379596,7783255,5295994,5390379,3435360,9975021,5131894];

// Optimised RLE map
$r=array_merge(array_diff(range(10,89),[27,40,47,56,59,60,63,66,67,70,73,75,76,77,79,80,83,86]),[92,94,99,105,107,112,118,145]);

// Image data (base 70)
$e="CDsF<Fd]WPX<F0^VE0240GX02Fd;d_F0EFN0?;<onFE0H;2>0I404h0NZ@;>0460640>20<0E05050Q@;0GI0Gd`0H@?0eMqCjY?:51Z0QJjYu[ZD>0>:H:50Wk?;:PQ05M0ErDH;`]E0270707?DHg2VW[?DHg<MW[?c0;F032DN:<7:?0V0DX<0E0^K5:D01CXW0X<K7Ub:d03I3<A?Cp0^023I3<A?:T0Ta<>3I420A050B0Bt2G0=GAHbS0\:8i08Hbf9S0iAH9FBf09S>0YAH9=09IaLoAQO9IBA0ABiKQF09@CA03CP04K:H0ObAXK080AQIFT0B08XS:AHRm090BOlHI0";

// Expand image data
for($i=0;$i<352;$i++){$b=$r[ord($e[$i])-48];$l=(int)($b/10);while($l--)$d[]=$c[$b%10];}

// Colour retrieval functions
function red($x,$y){global$d;return$d[$x+$y*32]&0xff;}
function green($x,$y){global$d;return$d[$x+$y*32]>>8;}
function blue($x,$y){global$d;return($d[$x+$y*32]>>8)&0xff;}

Sơ khai thử nghiệm:

for ($y=0;$y<32;$y++) {
    for ($x=0;$x<32;$x++) {
        printf("%d %d %d\n", red($x, $y), blue($x, $y), green($x, $y));
    }
}

Bản thân việc nén dữ liệu hình ảnh là khá tốt, nhưng các chức năng truy xuất giá trị RGB chiếm tới 1/4 mã.

Tôi đang sử dụng một cơ chế mã hóa chiều dài cơ sở tùy chỉnh 70 +.

  1. Có 10 màu độc đáo.
  2. Màu sắc có độ dài chạy trong khoảng từ 1 đến 14 (12 được sử dụng).
  3. Có 120 kết hợp có thể.
  4. Chỉ có 70 kết hợp chạy / màu duy nhất thực sự được sử dụng.

Dữ liệu hình ảnh được mã hóa tham chiếu chỉ mục mảng của RLE, lần lượt lập chỉ mục mảng màu. Tôi không chắc có bao nhiêu chi phí này cộng hoặc trừ so với việc tham chiếu trực tiếp các màu.

Sine có 10 màu (0 đến 9), RLE được lưu dưới dạng run_length * 10 + colour_index . Đưa ra một loạt các bảng mã từ 10 đến 145 mà không cần thử nghiệm tối ưu hóa dựa trên thứ tự màu. (tức là tôi có thể tạo phạm vi 19 đến 140 bằng cách di chuyển các màu từ 0 đến 5, 5 đến 9 và 9 đến 0 - nhưng điều này có thể có các hiệu ứng kích thích khác)

Một câu trả lời trước cho biết dữ liệu được mã hóa của họ là 472 byte. Dữ liệu hình ảnh được mã hóa của tôi là 352 byte, nhưng bản đồ RLE / màu trung gian (không được mã hóa nhị phân) là 129 byte nữa, đặt tổng số ở mức 480. (cũng như chi phí bổ sung để nối hai). Tuy nhiên tôi nghi ngờ phương pháp của tôi có thể mở rộng tốt hơn cho hình ảnh lớn hơn.

LÀM:

  1. Điều tra mã hóa nhị phân của bản đồ RLE
  2. Tìm cách giảm kích thước của các chức năng. globallà một con chó cái, nhưng không thể truy cập các chỉ mục ký tự trên các hằng số.
  3. Thử nghiệm với thứ tự chỉ số màu để xem kích thước bản đồ RLE có thể được giảm với các chuỗi số liên tiếp dài hơn không
  4. Tối ưu hóa cụ thể 64 bit của bản đồ màu? (r0 << 56 | r1 << 48 | ...)?
  5. Thử nghiệm với RLE dọc để xem liệu nó có dẫn đến một bộ mã hóa nhỏ gọn hơn không.
  6. Mã hóa khu vực?

1

C (gcc) , 602 byte

P[]={0,6982905,0xba4747,5003361,5751670,8048464,2834514,6318900,0xed3498,7753294},X[1024],*i,r,w;
#define u(d)i=X;for(char*I="56s-8-8_TKCL-8!UJ7!#%!9L!#8_,_W8!78A!0,-us87!:,#/!;%!%i!AN1,/!%'!'%!/#!-!7!&!&!D1,!9;!9_X!:10!a@v&5lM0+&\"N!D<lMvNPN6/!/+:+&!Kn0,+CD!&@!7x(6:,XT7!#(!(!(06:h#JKP06:h-@KP0^!,8!$#6A+-(+0!J!6L-!7!U=&+6!\"5LK!L-=(I\\+_!$;$-305z!U!#$;$-30+H!H[-/$;%#!3!&!4!4y3#9!.93:\\G!Q+)k!):\\e*G!k3:*84e!*G/!M3:*.!*;[>u3DB*;43!34k=D8!*153!$5C!%=+:!B\\3L=!)!3D;8H!4!)LG+3:Ep!*!4Bo:;!";w=*I-33,*I++;)for(r=w/10+1;r--;*i++=P[w%10]>>d&255);x=X[y*32+x];
red(x,y){u(16)}green(x,y){u(8)}blue(x,y){u(0)}

Hãy thử trực tuyến!

Chạy xuống

P[]={...},              The palette. Each entry is an integer on the form `RRGGBB`.
X[1024],                The buffer we unpack things into.
*i,r,w;                 Misc variables.
#define u(d)            Macro taking the number of bits to shift palette entries.
i=X;for(char*I="...";   Start at beginning of X for output, I is the encoded data.
                        Data was packed as ((R - 1) * 10) + P + 33, with R being
                        run-length and P the palette entry.
w=*I-33,*I++;)          Pick up encoded char, and check for end of data.
for(r=w/10+1;r--;       Get run-length from encoded byte.
*i++=P[w%10]>>d&255);   Get palette entry and extract colour given by d to store in X.
x=X[y*32+x];            Implicit return of the value at given coordinates.
red(x,y){u(16)}         The specific functions for each channel, calling u() for the
green(x,y){u(8)}        real work.
blue(x,y){u(0)}
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.