Lossy ASCII 아트 압축


21

배경

PICASCII 는 이미지를 ASCII 아트로 변환하는 깔끔한 도구입니다.

다음과 같은 10 개의 ASCII 문자를 사용하여 다른 정도의 밝기를 얻습니다.

@#+';:,.` 

우리는이 charxels (문자 요소)가 1 (부호)에서 10 (공간)까지의 밝기를 가지고 있다고 말할 것입니다.

아래에서는 작은 글꼴, 웨일스 어 깃발, 넘친 프랙탈, 큰 송어 및 작은 골프를 올바른 글꼴로 표시 한 결과를 볼 수 있습니다.

ASCII 아트

이 바이올린 에서 이미지를보고 Google 드라이브 에서 이미지를 다운로드 할 수 있습니다 .

태스크

PICASCII의 최종 결과는 시각적으로 만족 스럽지만 결합 된 5 개의 이미지는 모두 153,559 바이트입니다. 품질의 일부를 기꺼이 희생하려는 경우 이러한 이미지를 얼마나 압축 할 수 있습니까?

당신의 임무는 위와 같은 ASCII 아트 이미지와 최소 품질을 입력으로 받아들이고 전체 프로그램 또는 단일 문자열을 반환하는 함수의 형태로 이미지의 손실 압축을 인쇄하는 프로그램을 작성하는 것입니다. 품질 요구 사항.

즉, 별도의 압축 해제기를 작성하지 않아도됩니다. 압축 된 각 이미지에 내장되어 있어야합니다.

원본 이미지는 밝기가 1에서 10 사이 인 charxels로 구성되며 줄 바꿈으로 같은 길이의 줄로 구분됩니다. 압축 된 이미지는 크기가 동일해야하며 동일한 문자 세트를 사용해야합니다.

n 개의 charxels 로 구성된 압축되지 않은 이미지 의 경우 이미지의 압축 버전 품질은 다음과 같이 정의됩니다.

품질 공식

여기서 c를 의 밝기이다 내가 번째 압축 영상의 출력과 charxel U I 의 밝기 I 번째의 압축되지 않은 이미지 charxel.

채점

코드는 각 이미지에 대해 0.50, 0.60, 0.70, 0.80 및 0.90의 입력 및 최소 품질 설정으로 위의 5 개 이미지로 실행됩니다.

점수는 압축 된 모든 이미지의 크기, 즉 25 개의 압축 된 이미지의 길이에 대한 곱의 근이 25입니다.

최저 점수가 이깁니다!

추가 규칙

  • 스코어링에 사용 된 이미지 만이 아니라 임의의 이미지에 대해 코드가 작동해야합니다.

    테스트 사례에 맞게 코드를 최적화 할 것으로 예상되지만 임의의 이미지를 압축 하려고 시도 하지 않는 프로그램 은 나에게 찬성하지 않습니다.

  • 컴프레서는 내장 바이트 스트림 컴프레서 (예 : gzip)를 사용할 수 있지만 압축 된 이미지를 위해 직접 구현해야합니다.

    바이트 스트림 압축 해제 기 (예를 들어, 기본 변환, 런-길이 디코딩)에서 일반적으로 사용되는 Bulit-in이 허용됩니다.

  • 압축기와 압축 이미지는 동일한 언어 일 필요는 없습니다.

    그러나 모든 압축 이미지에 대해 단일 언어를 선택해야합니다.

  • 각 압축 이미지에 표준 코드 골프 규칙이 적용됩니다.

확인

모든 품질 요구 사항을 쉽게 확인하고 제출 점수를 계산하기 위해 CJam 스크립트를 만들었습니다.

여기 또는 여기 에서 Java 인터프리터를 다운로드 할 수 있습니다 .

e# URLs of the uncompressed images.
e# "%s" will get replaced by 1, 2, 3, 4, 5.

"file:///home/dennis/codegolf/53199/original/image%s.txt"

e# URLs of the compressed images (source code).
e# "%s-%s" will get replaced by "1-50", "1-60", ... "5-90".

"file:///home/dennis/codegolf/53199/code/image%s-%s.php"

e# URLs of the compressed images (output).

"file:///home/dennis/codegolf/53199/output/image%s-%s.txt"

e# Code

:O;:C;:U;5,:)
{
    5,5f+Af*
    {
        C[IQ]e%g,X*:X;
        ISQS
        [U[I]e%O[IQ]e%]
        {g_W=N&{W<}&}%
        _Nf/::,:=
        {
            {N-"@#+';:,.` "f#}%z
            _::m2f#:+\,81d*/mq1m8#
            _"%04.4f"e%S
            @100*iQ<"(too low)"*
        }{
            ;"Dimension mismatch."
        }?
        N]o
    }fQ
}fI
N"SCORE: %04.4f"X1d25/#e%N

배쉬 → PHP, 30344.0474

cat

모든 입력에 대해 100 % 품질을 달성합니다.

$ java -jar cjam-0.6.5.jar vrfy.cjam
1 50 1.0000 
1 60 1.0000 
1 70 1.0000 
1 80 1.0000 
1 90 1.0000 
2 50 1.0000 
2 60 1.0000 
2 70 1.0000 
2 80 1.0000 
2 90 1.0000 
3 50 1.0000 
3 60 1.0000 
3 70 1.0000 
3 80 1.0000 
3 90 1.0000 
4 50 1.0000 
4 60 1.0000 
4 70 1.0000 
4 80 1.0000 
4 90 1.0000 
5 50 1.0000 
5 60 1.0000 
5 70 1.0000 
5 80 1.0000 
5 90 1.0000 

SCORE: 30344.0474

이 부분을 이해하는 데 약간의 어려움이 있습니다. 누가 q = 0.5를 선택하면 입력 파일의 각 문자가 출력의 절반 밝기로 문자로 대체되어야합니까? 공백을 제외하면 전체 이미지가 엉망이 될 수 있습니다.
Nicolás Siplis

1
너무 혼란스럽고 허풍 적입니다. mattmahoney.net/dc/barf.html 항목을 어떻게 중지 합니까? 압축 해제 기는 압축 이미지 이외의 파일도 읽을 수 있습니까? 파이썬 스크립트 또는 실제로 이미지의 품질을 확인하고 점수를 계산하여 그 앞면에 퀴즈가 생기지 않도록하는 것을 제공 할 수 있습니까? 기타

1
@ 혼란 스러운가? 아마도. 그러나 나는 허풍이라고 생각하지 않습니다. 압축 된 각 이미지는 프로그램 또는 기능이어야하므로 BARF와 같은 재미없는 농담은 자동으로 제외됩니다. 나는 파이썬을 모른다. 그러나 나는 간단한 검증을 생각할 것이다.
Dennis

8
"저는 모든 품질 요구 사항을 쉽게 확인하고 제출 점수를 계산하기 위해 CJam 스크립트를 만들었습니다." 사람들이 실제로이 작업을 사용하여 일반 스크립트를 수행합니까? 친애하는 주님 ...
치명적인

답변:


4

자바 → CJam, ≈4417.89

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import net.aditsu.cjam.CJam;

public class Compress {
    protected static final char[] DIGITS = "0123456789ABCDEFGHIJK".toCharArray();
    protected static final String CHARS = "@#+';:,.` ";
    protected static final char[] CHR = CHARS.toCharArray();

    private static class Img {
        public final int rows;
        public final int cols;
        public final int[][] a;

        public Img(final int rows, final int cols) {
            this.rows = rows;
            this.cols = cols;
            a = new int[rows][cols];
        }

        public Img(final List<String> l) {
            rows = l.size();
            cols = l.get(0).length();
            a = new int[rows][cols];
            for (int i = 0; i < rows; ++i) {
                for (int j = 0; j < cols; ++j) {
                    a[i][j] = CHARS.indexOf(l.get(i).charAt(j));
                }
            }
        }

        public static Img read(final Reader r) {
            try {
                final BufferedReader br = new BufferedReader(r);
                final List<String> l = new ArrayList<>();
                while (true) {
                    final String s = br.readLine();
                    if (s == null || s.isEmpty()) {
                        break;
                    }
                    l.add(s);
                }
                br.close();
                return new Img(l);
            }
            catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        public static Img read(final File f) {
            try {
                return read(new FileReader(f));
            }
            catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        public Img scaleDown(final int fr, final int fc) {
            final int r1 = (rows + fr - 1) / fr;
            final int c1 = (cols + fc - 1) / fc;
            final Img x = new Img(r1, c1);
            final int[][] q = new int[r1][c1];
            for (int i = 0; i < rows; ++i) {
                for (int j = 0; j < cols; ++j) {
                    x.a[i / fr][j / fc] += a[i][j];
                    q[i / fr][j / fc]++;
                }
            }
            for (int i = 0; i < r1; ++i) {
                for (int j = 0; j < c1; ++j) {
                    x.a[i][j] /= q[i][j];
                }
            }
            return x;
        }

        public Img scaleUp(final int fr, final int fc) {
            final int r1 = rows * fr;
            final int c1 = cols * fc;
            final Img x = new Img(r1, c1);
            for (int i = 0; i < r1; ++i) {
                for (int j = 0; j < c1; ++j) {
                    x.a[i][j] = a[i / fr][j / fc];
                }
            }
            return x;
        }

        public Img crop(final int r, final int c) {
            if (r == rows && c == cols) {
                return this;
            }
            final Img x = new Img(r, c);
            for (int i = 0; i < r; ++i) {
                for (int j = 0; j < c; ++j) {
                    x.a[i][j] = a[i][j];
                }
            }
            return x;
        }

        public Img rescale(final int fr, final int fc) {
            return scaleDown(fr, fc).scaleUp(fr, fc).crop(rows, cols);
        }

        public double quality(final Img x) {
            if (x.rows != rows || x.cols != cols) {
                throw new IllegalArgumentException();
            }
            double t = 0;
            for (int i = 0; i < rows; ++i) {
                for (int j = 0; j < cols; ++j) {
                    final int y = a[i][j] - x.a[i][j];
                    t += y * y;
                }
            }
            t /= 81 * rows * cols;
            t = 1 - Math.sqrt(t);
            return Math.pow(t, 8);
        }

        @Override
        public String toString() {
            final StringBuilder sb = new StringBuilder();
            for (int i = 0; i < rows; ++i) {
                for (int j = 0; j < cols; ++j) {
                    sb.append(CHR[a[i][j]]);
                }
                sb.append('\n');
            }
            return sb.toString();
        }

        public Array toArray() {
            final Array x = new Array(rows * cols);
            int k = 0;
            for (int i = 0; i < rows; ++i) {
                for (int j = 0; j < cols; ++j) {
                    x.a[k++] = a[i][j];
                }
            }
            return x;
        }

        public String compress(final double quality) {
            int bi = 1;
            int bj = 1;
            int bs = rows * cols;
            Img bx = this;

            for (int i = 1; i < 3; ++i) {
                for (int j = 1; j < 3; ++j) {
                    Img x = rescale(i, j);
                    if (quality(x) >= quality) {
                        x = scaleDown(i, j);
                        if (x.rows * x.cols < bs) {
                            bi = i;
                            bj = j;
                            bs = x.rows * x.cols;
                            bx = x;
                        }
                    }
                }
            }

            Array a = bx.toArray();
            int bf = 0;
            for (int i = 1; i <= 20; ++i) {
                final int t = a.rle11(i).n;
                if (t < bs) {
                    bs = t;
                    bf = i;
                }
            }

            int b = 10;
            if (bf > 0) {
                b = 11;
                a = a.rle11(bf);
            }

            String s = null;
            for (int i = 92; i < 97; ++i) {
                for (char c = ' '; c < '$'; ++c) {
                    final String t = a.cjamBase(b, i, c);
                    boolean ok = true;
                    for (int j = 0; j < t.length(); ++j) {
                        if (t.charAt(j) > '~') {
                            ok = false;
                            break;
                        }
                    }
                    if (!ok) {
                        continue;
                    }
                    if (s == null || t.length() < s.length()) {
                        s = t;
                    }
                }
            }

            if (bf > 0) {
                s += "{(_A={;()";
                if (bf > 1) {
                    s += DIGITS[bf] + "*";
                }
                s += "\\(a@*}&\\}h]e_";
            }
            if (bi * bj == 1) {
                return s + '"' + CHARS + "\"f=" + cols + "/N*";
            }
            s += bx.cols + "/";
            if (bi > 1) {
                s += bi + "e*";
                if (rows % 2 == 1) {
                    s += "W<";
                }
            }
            if (bj > 1) {
                s += bj + "fe*";
                if (cols % 2 == 1) {
                    s += "Wf<";
                }
            }
            return s + '"' + CHARS + "\"ff=N*";
        }

        public void verify(final String s, final double quality) {
            final String t = CJam.run(s, "");
            final Img x = read(new StringReader(t));
            final double q = quality(x);
            if (q < quality) {
                throw new RuntimeException(q + " < " + quality);
            }
//          System.out.println(q + " >= " + quality);
        }
    }

    private static class Array {
        public final int[] a;
        public final int n;

        public Array(final int n) {
            this.n = n;
            a = new int[n];
        }

        public Array(final int[] a) {
            this.a = a;
            n = a.length;
        }

        public String join() {
            final StringBuilder sb = new StringBuilder();
            for (int x : a) {
                sb.append(x).append(' ');
            }
            sb.setLength(sb.length() - 1);
            return sb.toString();
        }

//      public String cjamStr() {
//          final StringBuilder sb = new StringBuilder("\"");
//          for (int x : a) {
//              sb.append(DIGITS[x]);
//          }
//          sb.append("\":~");
//          return sb.toString();
//      }

        public String cjamBase(final int m, final int b, final char c) {
            final boolean zero = a[0] == 0;
            String s = join();
            if (zero) {
                s = "1 " + s;
            }
            s = CJam.run("q~]" + m + "b" + b + "b'" + c + "f+`", s);
            s += "'" + c + "fm" + b + "b" + DIGITS[m] + "b";
            if (zero) {
                s += "1>";
            }
            return s;
        }

        public Array rle11(final int f) {
            final int[] b = new int[n];
            int m = 0;
            int x = -1;
            int k = 0;
            for (int i = 0; i <= n; ++i) {
                final int t = i == n ? -2 : a[i];
                if (t == x && m < 11 * f) {
                    m++;
                }
                else {
                    if (m >= f && m > 3) {
                        b[k++] = 10;
                        b[k++] = m / f - 1;
                        b[k++] = x;
                        for (int j = 0; j < m % f; ++j) {
                            b[k++] = x;
                        }
                    }
                    else {
                        for (int j = 0; j < m; ++j) {
                            b[k++] = x;
                        }
                    }
                    m = 1;
                    x = t;
                }
            }
            return new Array(Arrays.copyOf(b, k));
        }
    }

    private static void score() {
        double p = 1;
        for (int i = 1; i < 6; ++i) {
            final File f = new File("image" + i + ".txt");
            final Img img = Img.read(f);
            final int n = (int) f.length();
            for (int j = 5; j < 10; ++j) {
                final double q = j / 10.0;
                final String s = img.compress(q);
                System.out.println(f.getName() + ", " + q + ": " + n + " -> " + s.length());
                img.verify(s, q);
                p *= s.length();
            }
        }
        System.out.println(Math.pow(p, 1 / 25.0));
    }

    public static void main(final String... args) {
        if (args.length != 2) {
            score();
            return;
        }
        final String fname = args[0];
        final double quality = Double.parseDouble(args[1]);
        try {
            final Img img = Img.read(new File(fname));
            final String s = img.compress(quality);
            img.verify(s, quality);
            final FileWriter fw = new FileWriter(fname + ".cjam");
            fw.write(s);
            fw.close();
        }
        catch (IOException e) {
            throw new RuntimeException();
        }
    }
}

클래스 경로에 CJam jar이 필요합니다. 두 개의 명령 줄 인수 (파일 이름 및 품질)를 지정하면 파일 이름에 ".cjam"이 추가되고 압축 된 이미지가 여기에 기록됩니다. 그렇지 않으면 현재 디렉토리에있는 것으로 간주되는 5 개의 테스트 이미지에서 점수를 계산합니다. 이 프로그램은 또한 모든 압축 이미지를 자동으로 확인합니다. 불일치가있는 경우 점수 계산을 다시 확인할 수 있습니다.

지금까지 사용 된 기술은 품질을 너무 많이 줄이지 않으면 절반 (수평, 수직 또는 둘 다)으로 확장, 사용자 지정 코딩 된 RLE 및 각 문자에 더 많은 데이터를 저장하기위한 기본 변환 인쇄 가능한 ASCII 범위.


이것을 실행하는 방법에 대한 간략한 개요를 알려주시겠습니까? 난과 (성공적으로, 나는 생각한다)를 컴파일 javac -cp cjam-0.6.5.jar Compress.java하지만, java -cp cjam-0.6.5.jar Compress라고 Error: Could not find or load main class Compress하고 java CompressCJam 클래스를 찾을 수 없습니다.
Dennis

@Dennis Compress.class를 포함하는 디렉토리를 클래스 경로 (-cp)에 추가해야합니다. 현재 디렉토리에 있다면 -cp .:cjam-0.6.5.jar(windoze에서 콜론 대신 세미콜론이 필요하다고 생각합니다)
aditsu

그 트릭을했다, 감사합니다.
Dennis

2

Python 3.5 (메인 및 출력) (현재 비경쟁)

생일 축하해! 여기 당신의 선물이 있습니다 : 답변!

편집 : 출력을 파이썬 코드로 변환, 압축률 향상 (약간) EDIT2 : size1 일 때 원시 인쇄로 만들었습니다 . 점수가 향상되었지만 점수를 다시 계산해야합니다. EDIT3 : @Dennis는 여전히 수정해야 할 버그가 있다고 지적 했으므로 대답을 비 경쟁으로 표시했습니다.

암호:

import sys
LIST = [' ','`','.',',',':',';',"'",'+','#','@']

def charxel_to_brightness(charxel):
    return LIST.index(charxel)

def brightness_to_charxel(bright):
    return LIST[bright]

def image_to_brightness(imagetext):
    return [list(map(charxel_to_brightness,line)) for line in imagetext.split("\n")]

def brightness_to_image(brightarray):
    return '\n'.join([''.join(map(brightness_to_charxel,line)) for line in brightarray])

def split_into_parts(lst,size):
    return [lst[x:x+size] for x in range(0, len(lst), size)]

def gen_updown(startxel,endxel,size):
    return [[int((size-r)*(endxel-startxel)/size+startxel) for c in range(size)] for r in range(size)]

def gen_leftright(startxel,endxel,size):
    return [[int((size-c)*(endxel-startxel)/size+startxel) for c in range(size)] for r in range(size)]

def gen_tlbr(startxel,endxel,size):
    return [[int((2*size-r-c)/2*(endxel-startxel)/size+startxel) for c in range(size)] for r in range(size)]

def gen_bltr(startxel,endxel,size):
    return [[int((size-r+c)/2*(endxel-startxel)/size+startxel) for c in range(size)] for r in range(size)]

def gen_block(code,startxel,endxel,size):
    if code==0:return gen_updown(startxel,endxel,size)
    if code==1:return gen_leftright(startxel,endxel,size)
    if code==2:return gen_bltr(startxel,endxel,size)
    if code==3:return gen_tlbr(startxel,endxel,size)

def vars_to_data(code,startxel,endxel):
    acc=endxel
    acc+=startxel<<4
    acc+=code<<8
    return acc

def data_to_vars(data):
    code=data>>8
    startxel=(data>>4)&15
    endxel=data&15
    return code,startxel,endxel

def split_into_squares(imgarray,size):
    rows = split_into_parts(imgarray,size)
    allsquares = []
    for rowblock in rows:
        splitrows = []
        for row in rowblock:
            row = split_into_parts(row,size)
            splitrows.append(row)
        rowdict = []
        for row in splitrows:
            for x in range(len(row)):
                if len(rowdict)<=x:
                    rowdict.append([])
                rowdict[x].append(row[x])
        allsquares.append(rowdict)
    return allsquares

def calc_quality(imgarray,comparray):
    acc=0
    for row in range(len(imgarray)):
        for col in range(len(imgarray[row])):
            acc+=pow(imgarray[row][col]-comparray[row][col],2)
    return (1-(acc/81.0/sum([len(row) for row in imgarray]))**.5)**8

def fuse_squares(squarray):
    output=[]
    counter=0
    scounter=0
    sqrow=0
    while sqrow<len(squarray):
        if scounter<len(squarray[sqrow][0]):
            output.append([])
            for square in squarray[sqrow]:
                output[counter].extend(square[scounter])
            scounter+=1
            counter+=1
        else:
            scounter=0
            sqrow+=1
    return output

def main_calc(imgarray,threshold):
    imgarray = image_to_brightness(imgarray)
    size = 9
    quality = 0
    compimg=[]
    datarray=[]
    testdata = [vars_to_data(c,s,e) for c in range(4) for s in range(10) for e in range(10)]
    while quality<threshold:
        squares = split_into_squares(imgarray,size)
        compimg = []
        datarray = []
        testblock = [gen_block(c,s,e,size) for c in range(4) for s in range(10) for e in range(10)]
        for row in squares:
            comprow = []
            datrow=[]
            for square in row:
                quality_values = [calc_quality(square,block) for block in testblock]
                best_quality = quality_values.index(max(quality_values))
                comprow.append(testblock[best_quality])
                datrow.append(testdata[best_quality])
            compimg.append(comprow)
            datarray.append(datrow)
        compimg = fuse_squares(compimg)
        quality = calc_quality(imgarray,compimg)
        print("Size:{} Quality:{}".format(size,quality))
        size-=1
    return brightness_to_image(compimg),datarray,size+1

template = '''def s(d,s,e,z):
 x=range(z)
 return d<1 and[[int((z-r)*(e-s)/z+s)for c in x]for r in x]or d==1 and[[int((z-c)*(e-s)/z+s)for c in x]for r in x]or d==2 and[[int((2*z-r-c)/2*(e-s)/z+s)for c in x]for r in x]or d>2 and[[int((z-r+c)/2*(e-s)/z+s)for c in x] for r in x]
i=lambda a:'\\n'.join([''.join(map(lambda r:" `.,:;'+#@"[r],l))for l in a])
def f(a):
 o=[];c=0;s=0;r=0
 while r<len(a):
  if s<len(a[r][0]):
   o.append([])
   for q in a[r]:
    o[c].extend(q[s])
   s+=1;c+=1
  else:
   s=0;r+=1
 return o
t={};z={}
print(i(f([[s(D>>8,(D>>4)&15,D&15,z)for D in R]for R in t])))'''

template_size_1 = '''print("""{}""")'''   

def main(filename,threshold):
    print(filename+" "+str(threshold))
    file = open(filename,'r')
    compimg,datarray,size = main_calc(file.read(),threshold)
    file.close()
    textoutput = open(filename.split(".")[0]+"-"+str(threshold*100)+".txt",'w')
    textoutput.write(compimg)
    textoutput.close()
    compoutput = open(filename.split(".")[0]+"-"+str(threshold*100)+".py",'w')
    datarray = str(datarray).replace(" ","")
    code = ""
    if size==1:
        code = template_size_1.format(compimg)
    else:
        code= template.format(datarray,str(size))
    compoutput.write(code)
    compoutput.close()
    print("done")

if __name__ == "__main__":
    main(sys.argv[1],float(sys.argv[2]))

이 답변은 많은 개선 사항을 사용할 수 있으므로 주말에 더 많이 노력할 것입니다.

작동 원리 :

  • 이미지를 크기 블록으로 나눕니다 size.
  • 가장 일치하는 블록 찾기
    • 블록은 이제 그라디언트를 가질 수 있습니다!
  • 전체 이미지의 품질을 계산합니다 (공식에 따라).
  • 올바른 경우 압축 된 이미지를 파일에 씁니다.
  • 그렇지 않으면 감소 size하고 다시 시도하십시오.

이 알고리즘은 저품질 (0.5, 0.6)에서는 잘 작동하지만 고품질 이미지 (실제로 팽창)에서는 제대로 작동하지 않습니다. 또한 정말 느립니다.

여기 에는 생성 된 파일이 모두 있으므로 다시 생성 할 필요가 없습니다.


마지막으로 답변입니다! 이 도전 과제를 게시 한 후 Bubblegum을 만들었 기 때문에 기술적으로 비 경쟁적입니다. 나중에 점수 스크립트를 실행하고 덜 난해한 언어로 이식 할 것입니다.
Dennis

@Dennis Ah, 출력을 파이썬 스크립트로 포팅하는 것이 너무 어렵지 않아야합니다. 헤즈 업에 감사드립니다
Blue

난 그냥 내 도전을 다시 읽습니다 (1 년 후, 세부 사항에 약간의 퍼지가있었습니다). 컴프레서는 내장 바이트 스트림 압축기 (예 : gzip)를 사용할 수 있다고 말하지만 직접 구현해야합니다. 압축 이미지. 그것은 풍선 껌이 어쨌든 나가는 것을 의미합니다.
Dennis

나는 마침내 이것을 득점하겠다고 약속했다는 것을 기억했다. 지연 돼서 죄송합니다. 귀하의 코드에는 오타 comping가 있어야합니다 ( 이어야 함 compimg). 프로그램을 실행하도록 수정했습니다. 코드를 실행할 때 실수를하지 않는 한, 생성 된 이미지 중 일부의 크기가 올바르지 않습니다 (예 : image2.txt33,164 바이트, image2-50.0.txt33,329). 다른 프로그램은 생성 된 프로그램을 실행할 때 동일한 파일을 생성하지 않습니다 ( image3-50.0.txt품질은 0.5110 임) , 그러나 생성 된 프로그램을 실행하면 품질은 0.4508 입니다.
Dennis

부록 : image3-50.0.pyDropbox에서 다운로드 했으며 생성 한 파일과 일치합니다.
Dennis
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.