캐럿이란, 우리가 윈도우스에서 글을 사용할때, 해당 글의 위치를 표시하는 것이다.


 대표적으로 메모장이나 그런 것이 있다.


 이걸 이용하면, 메모장처럼 출력하는 부분을 표현 할 수도 있게 된다.


 현재, 설정한 것에서는 내용물을 표시하는 것까지만 하고 메모장을 표현하는게 아닌 예제이다.


 이것과 함께 키보드의 특수 키까지 표현을 하도록 만든다면, 메모장을 간단하게 제작이 가능할 것이다.


 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#include <stdio.h>
#include <stdlib.h>
 
#include <tchar.h>
#include <windows.h>
 
#include <string.h>
 
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
HINSTANCE g_hInst;
 
WNDCLASS WndClass;
 
int numbers = 0;
 
int WINAPI WinMain(HINSTANCE hInstance,
            HINSTANCE hPrevInstance,
            LPSTR lpszCmdParam,
            int nCmdShow)
{
    HWND hWnd;
    MSG Message;
    g_hInst = hInstance;
 
    WndClass.cbClsExtra=0;
    WndClass.cbWndExtra=0;
    WndClass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
    WndClass.hCursor=LoadCursor(NULL,IDC_ARROW);
    WndClass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
    WndClass.hInstance=hInstance;
    WndClass.lpfnWndProc=(WNDPROC)WndProc;
    WndClass.lpszClassName="ApiBase";
    WndClass.lpszMenuName=NULL;
    WndClass.style=CS_HREDRAW|CS_VREDRAW;
 
    RegisterClass(&WndClass);
    
    hWnd = CreateWindow("ApiBase",
                        "Test",
                        WS_OVERLAPPEDWINDOW,
                        10,// X
                        100,// Y
                        400,// Width
                        400,// Height
                        NULL,
                        (HMENU)NULL,
                        hInstance,
                        NULL);
 
                        
    ShowWindow(hWnd,nCmdShow);
    
    while(GetMessage(&Message,0,0,0))
    {
        TranslateMessage(&Message);
        DispatchMessage(&Message);
    }
    
    return Message.wParam;
}
 
LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{    
    HDC hdc;
    PAINTSTRUCT ps;
    static char strChar[MAX_PATH];
    int nlen = 0;
    static int pos = 0;
    SIZE size;
    
    switch(iMessage)
    {
        case WM_CREATE:
            strcpy(strChar, "");
            break;
        case WM_CHAR:
            //문자 크기 설정/내용 추가.
            nlen = strlen(strChar);
            strChar[nlen] = (char)wParam;
            strChar[nlen+1]=0;
            
            //문자 출력.
            pos++;
            hdc = GetDC(hWnd);
            GetTextExtentPoint(hdc, strChar, pos, &size);
            ReleaseDC(hWnd, hdc);
            
            //캐럿 위치 조절.
            SetCaretPos(size.cx + 100100);
            
            //다시 그리기 설정.
            InvalidateRect(hWnd, NULL, FALSE);
            break;
        case WM_SETFOCUS:
            hdc = GetDC(hWnd);
            CreateCaret(hWnd, NULL214); // 캐럿 생성
            ShowCaret(hWnd); // 캐럿 보이기
            SetCaretPos(100100); // 캐럿의 위치 설정
            break;
        case WM_KILLFOCUS:
            HideCaret(hWnd); // 캐럿 숨기기
            DestroyCaret(); // 캐럿 파괴
            break;
        case WM_PAINT:
            hdc = BeginPaint(hWnd, &ps);
            TextOut(hdc, 100100, strChar, strlen(strChar));
            EndPaint(hWnd, &ps);
            break;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
    }
    return DefWindowProc(hWnd,iMessage,wParam, lParam);
}
 
 
cs


Posted by JunkMam
,

 필자는 비디오 파일을 많이 가지고 있다.


 다른 분들 또한 비디오 파일을 많이 가지고 있을 거라고 생각이 든다.


 일단, 모든 비디오 파일은 무압축 영상은 없다.

 이유는 지금 화질을 중요시하면서 화소가 증가하고 있는 추세이다.

 화소의 증가는 하나의 프레임의 용량 증가를 뜻한다.

 프레임 또한 30에서 60프레임으로 맞춰 나간다.


 이렇게 본다면, 1초당 60프레임에 1080p 형태로 1시간 처리한다면, 무압축으로는 몇 TB 가까이가 될 수 있다.

 압축하지 않는 동영상 파일은 존재하지 않는다.


 무압축은 위키에서 찾아보면, 총 3가지이다.


 HuffYUV, Lagarith, MSU가 있다.


 이 3개는 거진 업그레이드가 없는데, 그 이유는 먼저 압축을 해도 용량이 손실 압축에 비해서 엄청 크다.


 그것 뿐만 아니라 압축을 풀기위해서 큰 데이터를 사용하기 때문에, 영상 처리 속도 느려지는 점이 있다.


 무손실은 어느정도의 한계점이 존재하기 때문에, 무손실 영상 압축은 거진 힘이 든다.(고화질 저용량 무손실 압축이 획기적 개발이 되지 않는다면...)


 그래서 우리가 알고 있는 영상들 대부분은 손실 압축이다.


 최근에는 4K의 영상을 제공하는 기기가 생성되고 있다.


 4K의 문제는 HD의 4배이상 해상도를 처리하는 것을 말한다.


 여기서 문제가 발생하는데, 동영상은 대부분 스트리밍 서비스가 대다수이다.(유튜브도 포함)


 스트리밍은 고용량의 파일이 실시간으로 보내지는 서비스이다. 그런데, 고용량일 경우에는 전송이 문제가 되고, 이것은 곧 높은 트래픽을 발생시킨다는 점이다.


 이 트래픽을 처리하기 위해서 최근에 개발된 H265가 있다.


 H265는 문제는 유료이다.


 그래서 무료형의 코덱을 개발하기 시작했는데, 그것이 VP8~VP9과 Daala가 있다.(VP10은 4K이상을 노린다고 한다.)


 Daala는 최근에(최근이라고 해도 5월달이다.) 꽤 높은 화질을 보여주고 있다.


 화질을 비교하기 위해서 참조 사이트

 https://people.xiph.org/~jm/daala/revisiting/


daala는 아직 개발 중이라서 차후에 높은 화질을 보여줄 수 있을 것같다.

Posted by JunkMam
,

 GPL을 따르는 MCM의 소스를 보고 일부 분석할려고 한다.


 여기서 HPP에 설정된 일부 소스만 작성할려고 한다.


 전체 소스

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
/*    MCM file compressor
    Copyright (C) 2013, Google Inc.
    Authors: Mathieu Chartier
    LICENSE
    This file is part of the MCM file compressor.
    MCM is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
    MCM is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
    You should have received a copy of the GNU General Public License
    along with MCM.  If not, see <http://www.gnu.org/licenses/>.
*/
 
#ifndef _UTIL_HPP_
#define _UTIL_HPP_
 
#include <cassert>
#include <ctime>
#include <emmintrin.h>
#include <iostream>
#include <mmintrin.h>
#include <mutex>
#include <ostream>
#include <stdint.h>
#include <sstream>
#include <string>
#include <vector>
 
#ifdef WIN32
#define forceinline __forceinline
#else
#define forceinline inline __attribute__((always_inline))
#endif
#define ALWAYS_INLINE forceinline
 
#define no_alias __restrict
 
#ifndef BYTE_DEFINED
#define BYTE_DEFINED
typedef unsigned char byte;
#endif
 
#ifndef UINT_DEFINED
#define UINT_DEFINED
typedef unsigned int uint;
#endif
 
#ifndef WORD_DEFINED
#define WORD_DEFINED
typedef unsigned short word;
#endif
 
// TODO: Implement these.
#define LIKELY(x) x
#define UNLIKELY(x) x
 
#ifdef _DEBUG
static const bool kIsDebugBuild = true;
#else
static const bool kIsDebugBuild = false;
#endif
 
#ifdef _MSC_VER
#define ASSUME(x) __assume(x)
#else
#define ASSUME(x)
#endif
    
typedef uint32_t hash_t;
 
static const uint64_t KB = 1024;
static const uint64_t MB = KB * KB;
static const uint64_t GB = KB * MB;
static const uint32_t kCacheLineSize = 64// Sandy bridge.
static const uint32_t kPageSize = 4 * KB;
static const uint32_t kBitsPerByte = 8;
 
forceinline void prefetch(const void* ptr) {
#ifdef WIN32
    _mm_prefetch((char*)ptr, _MM_HINT_T0);
#else
    __builtin_prefetch(ptr);
#endif
}
 
forceinline static bool isUpperCase(int c) {
    return c >= 'A' && c <= 'Z';
}
forceinline static bool isLowerCase(int c) {
    return c >= 'a' && c <= 'z';
}
forceinline static bool isWordChar(int c) {
    return isLowerCase(c) || isUpperCase(c) || c >= 128;
}
forceinline static int makeLowerCase(int c) {
    assert(isUpperCase(c));
    return c - 'A' + 'a';
}
forceinline static int makeUpperCase(int c) {
    assert(isLowerCase(c));
    return c - 'a' + 'A';
}
 
// Trust in the compiler
forceinline uint32_t rotate_left(uint32_t h, uint32_t bits) {
    return (h << bits) | (h >> (sizeof(h) * 8 - bits));
}
 
forceinline uint32_t rotate_right(uint32_t h, uint32_t bits) {
    return (h << (sizeof(h) * 8 - bits)) | (h >> bits);
}
 
#define check(c) while (!(c)) { std::cerr << "check failed " << #c << std::endl*reinterpret_cast<int*>(1234= 4321;}
#define dcheck(c) assert(c)
 
template <const uint32_t A, const uint32_t B, const uint32_t C, const uint32_t D>
struct shuffle {
    enum {
        value = (D << 6| (C << 4| (B << 2| A,
    };
};
 
forceinline bool isPowerOf2(uint32_t n) {
    return (n & (n - 1)) == 0;
}
 
forceinline uint bitSize(uint Value) {
    uint Total = 0;
    for (;Value;Value >>= 1, Total++);
    return Total;
}
 
template <typename T>
void printIndexedArray(const std::string& str, const T& arr) {
    uint32_t index = 0;
    std::cout << str << std::endl;
    for (const auto& it : arr) {
        if (it) {
            std::cout << index << ":" << it << std::endl;
        }
        index++;
    }
}
 
template <const uint64_t n>
struct _bitSize {static const uint64_t value = 1 + _bitSize</ 2>::value;};
 
template <>
struct _bitSize<0> {static const uint64_t value = 0;};
 
inline void fatalError(const std::string& message) {
    std::cerr << "Fatal error: " << message << std::endl;
    *reinterpret_cast<uint32_t*>(1234= 0;
}
 
inline void unimplementedError(const char* function) {
    std::ostringstream oss;
    oss << "Calling implemented function " << function;
    fatalError(oss.str());
}
 
inline uint32_t rand32() {
    return rand() ^ (rand() << 16);
}
 
forceinline int fastAbs(int n) {
    int mask = n >> 31;
    return (n ^ mask) - mask;
}
 
bool fileExists(const char* name);
 
class Closure {
public:
    virtual void run() = 0;
};
 
template <typename Container>
void deleteValues(Container& container) {
    for (auto* p : container) {
        delete p;
    }
    container.clear();
}
 
class ScopedLock {
public:
    ScopedLock(std::mutex& mutex) : mutex_(mutex) {
        mutex_.lock();
    }
 
    ~ScopedLock() {
        mutex_.unlock();
    }
 
private:
    std::mutex& mutex_;
};
 
forceinline void copy16bytes(byte* no_alias out, const byte* no_alias in, const byte* limit) {
    _mm_storeu_ps(reinterpret_cast<float*>(out), _mm_loadu_ps(reinterpret_cast<const float*>(in)));
}
 
forceinline static void memcpy16(void* dest, const void* src, size_t len) {
    uint8_t* no_alias dest_ptr = reinterpret_cast<uint8_t* no_alias>(dest);
    const uint8_t* no_alias src_ptr = reinterpret_cast<const uint8_t* no_alias>(src);
    const uint8_t* no_alias limit = dest_ptr + len;
    *dest_ptr++ = *src_ptr++;
    if (len >= sizeof(__m128)) {
        const byte* no_alias limit2 = limit - sizeof(__m128);
        do {
            copy16bytes(dest_ptr, src_ptr, limit);
            src_ptr += sizeof(__m128);
            dest_ptr += sizeof(__m128);
        } while (dest_ptr < limit2);
    }
    while (dest_ptr < limit) {
        *dest_ptr++ = *src_ptr++;
    }
}
 
template<typename CopyUnit>
forceinline void fastcopy(byte* no_alias out, const byte* no_alias in, const byte* limit) {
    do {
        *reinterpret_cast<CopyUnit* no_alias>(out) = *reinterpret_cast<const CopyUnit* no_alias>(in);
        out += sizeof(CopyUnit);
        in += sizeof(CopyUnit);
    } while (in < limit);
}
 
forceinline void memcpy16unsafe(byte* no_alias out, const byte* no_alias in, const byte* limit) {
    do {
        copy16bytes(out, in, limit);
        out += 16;
        in += 16;
    } while (out < limit);
}
 
template<uint32_t kMaxSize>
class FixedSizeByteBuffer {
public:
    uint32_t getMaxSize() const {
        return kMaxSize;
    }
 
protected:
    byte buffer_[kMaxSize];
};
 
// Move to front.
template <typename T>
class MTF {
    std::vector<T> data_;
public:
    void init(size_t n) {
        data_.resize(n);
        for (size_t i = 0; i < n; ++i) {
            data_[i] = static_cast<T>(n - 1 - i);
        }
    }
    size_t find(T value) {
        for (size_t i = 0; i < data_.size(); ++i) {
            if (data_[i] == value) {
                return i;
            }
        }
        return data_.size();
    }
    forceinline T back() const {
        return data_.back();
    }
    size_t size() const {
        return data_.size();
    }
    void moveToFront(size_t index) {
        auto old = data_[index];
        while (index) {
            data_[index] = data_[index - 1];
            --index;
        }
        data_[0= old;
    }
};
 
template <class T, size_t kSize>
class StaticArray {
public:
    StaticArray() {
    }
    ALWAYS_INLINE const T& operator[](size_t i) const {
        return data_[i];
    }
    ALWAYS_INLINE T& operator[](size_t i) {
        return data_[i];
    }
    ALWAYS_INLINE size_t size() const {
        return kSize;
    }
 
private:
    T data_[kSize];
};
 
template <class T, uint32_t kCapacity>
class StaticBuffer {
public:
    StaticBuffer() : pos_(0), size_(0) {
    }
    ALWAYS_INLINE const T& operator[](size_t i) const {
        return data_[i];
    }
    ALWAYS_INLINE T& operator[](size_t i) {
        return data_[i];
    }
    ALWAYS_INLINE size_t pos() const {
        return pos_;
    }
    ALWAYS_INLINE size_t size() const {
        return size_;
    }
    ALWAYS_INLINE size_t capacity() const {
        return kCapacity;
    }
    ALWAYS_INLINE size_t reamainCapacity() const {
        return capacity() - size();
    }
    ALWAYS_INLINE T get() {
        (pos_ < size_);
        return data_[pos_++];
    }
    ALWAYS_INLINE void read(T* ptr, size_t len) {
        dcheck(pos_ + len <= size_);
        std::copy(&data_[pos_], &data_[pos_ + len], &ptr[0]);
        pos_ += len;
    }
    ALWAYS_INLINE void put(T c) {
        dcheck(pos_ < size_);
        data_[pos_++= c;
    }
    ALWAYS_INLINE void write(const T* ptr, size_t len) {
        dcheck(pos_ + len <= size_);
        std::copy(&ptr[0], &ptr[len], &data_[pos_]);
        pos_ += len;
    }
    ALWAYS_INLINE size_t remain() const {
        return size_ - pos_;
    }
    void erase(size_t chars) {
        dcheck(chars <= pos());
        std::move(&data_[chars], &data_[size()], &data_[0]);
        pos_ -= std::min(pos_, chars);
        size_ -= std::min(size_, chars);
    }
    void addPos(size_t n) {
        pos_ += n;
        dcheck(pos_ <= size());
    }
    void addSize(size_t n) {
        size_ += n;
        dcheck(size_ <= capacity());
    }
    T* begin() {
        return &operator[](0);
    }
    T* end() {
        return &operator[](size_);
    }
    T* limit() {
        return &operator[](capacity());
    }
 
private:
    size_t pos_;
    size_t size_;
    T data_[kCapacity];
};
 
std::string prettySize(uint64_t size);
std::string formatNumber(uint64_t n);
double clockToSeconds(clock_t c);
std::string errstr(int err);
std::vector<byte> randomArray(size_t size);
uint64_t computeRate(uint64_t size, uint64_t delta_time);
std::vector<byte> loadFile(const std::string& name, uint32_t max_size = 0xFFFFFFF);
std::string trimExt(const std::string& str);
 
#endif
 
cs


 여기서 일부 자주 사용될 듯한 간단한 소스가 구현이 되어 있어서 설명을 넣을려고 한다.


1
2
3
static const uint64_t KB = 1024;
static const uint64_t MB = KB * KB;
static const uint64_t GB = KB * MB;
cs


 윗 소스는 메모리 크기의 KB및 MB, GB를 정의내리는 것이다.

 static이자 const이기 때문에, 매크로랑 유사하다. 라고 봐도 무관하다.


 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
forceinline static bool isUpperCase(int c) {
    return c >= 'A' && c <= 'Z';
}
forceinline static bool isLowerCase(int c) {
    return c >= 'a' && c <= 'z';
}
forceinline static bool isWordChar(int c) {
    return isLowerCase(c) || isUpperCase(c) || c >= 128;
}
forceinline static int makeLowerCase(int c) {
    assert(isUpperCase(c));
    return c - 'A' + 'a';
}
forceinline static int makeUpperCase(int c) {
    assert(isLowerCase(c));
    return c - 'a' + 'A';
}
 
// Trust in the compiler
forceinline uint32_t rotate_left(uint32_t h, uint32_t bits) {
    return (h << bits) | (h >> (sizeof(h) * 8 - bits));
}
 
forceinline uint32_t rotate_right(uint32_t h, uint32_t bits) {
    return (h << (sizeof(h) * 8 - bits)) | (h >> bits);
}
cs



 isUpperCase라는 것은 함수명에 설명 되어있듯, 대문자인지를 확인하는 소스이다.

 isLowerCase라는 것은 함수명에 설명 되어있듯, 소문자인지를 확인하는 소스이다.

 isWordChar라는 것은 함수명에 설명 되어있듯, 문자인지를 확인하는 소스이다.


 makeLowerCase라는 것은 함수명에 설명 되어있듯, 대문자를 소문자로 바꾸는 소스이다.

 makeUpperCase라는 것은 함수명에 설명 되어있듯, 소문자를 대문자로 바꾸는 소스이다.


rotate_left라는 것은 함수명에 설명 되어있듯, 왼쪽으로 회전, right는 오른쪽으로 회전 소스이다. 

Posted by JunkMam
,

 ffmpeg를 이용해서 영상에 있는 소리를 mp3로 추출하는 방법이다.


 

1
ffmpeg -i input.mp4 -codec:a libmp3lame -qscale:a 2 output.mp3
cs



 여기서 mp3로 변환하기 위해서 libmp3lame이라는 라이브러리를 사용하였다.


 qscale는 퀄리티이다. 얼마나 좋음 음색을 표현하는가? 라고 이해하면 될 것 같다.


 여기서 mp3등 연속적인 데이터를 저장시키는 스트림 파일들의 특징은 bitrate라는 것을 가진다.


 bitrate란, bit 데이터 전송률이라고 한다.


 이 데이터가 높으면 높을수록 전송 속도가 빠르고, 효과가 좋다.(하지만, 원본 보다 상향되진 않는다.)

Posted by JunkMam
,

 현재 인공지능을 이용해서 파일을 압축하는 프로그램이 나왔다.

 대표적인 방법으로는 paq라는 프로그램이다.[각주:1]



 paq를 개량해서 lite paq, fast paq 등 경량화 및 속도를 올린 paq 프로그램들이 나왔고, 혹은 paq 방식의 알고리즘인 CM(Context Mixing)을 이용해서 만든 프로그램이 있다.


 여기서 MCM또한 CM 알고리즘을 이용해서 만들어낸 프로그램이다.


 MCM를 사용하는 방법을 작성할려고한다.


 MCM은 일단, 폴더를 제작해서 압축하는 방식이 없다.(단일 파일만 압축할 수 있다는 뜻이다.)


 일단, 각각의 파일을 압축해서 합치는 방식은 오히려 파일 용량의 압축이 적으니 단일 파일을 압축시키는 것이 좋은 경우가 많이 발견되었다.


 MCM을 사용할려면 기본적으로 기준 환경을 맞춰줘야지 속도가 잘 나온다.


 환경

 Memory 최대 8G 이상.


 최고 압축을 사용할려면, Memory가 최대 8G 이상이 아니라면, 오히려 설명이 되어 있는 파일보다 속도가 제대로 안나온다.(페이징 작업에 의해서 속도가 감소하는 걸 느낄 수 있다.)


 paq보다 mcm가 메모리 사용량과 속도명에서 좀 더 좋은 점이 있다.(drt|lpaq을 이용하면 더 낫다 라는 설명이 되어 있지만, drt랑 lpaq가 제대로 안 돌아갔다.)


 아직까진 미완성이지만, mcm를 잘만 사용한다면, 용량을 줄여서 들고 다닐 수 있을 것이라고 나는 생각하고 있다.


 그럼, 이제 MCM을 사용하는 방법을 설명할려고 한다.


 mcm을 친다면, 다음과 같은 문장이 나오는 걸 알 수 있다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Error, input or output files missing
======================================================================
mcm compressor v0.83, by Mathieu Chartier (c)2015 Google Inc.
Experimental, may contain bugs. Contact mathieu.a.chartier@gmail.com
Special thanks to: Matt Mahoney, Stephan Busch, Christopher Mattern.
======================================================================
Caution: Experimental, use only for testing!
Usage: mcm.exe [command] [options] <infile> <outfile>
Options: d for decompress
-{t|f|m|h|x}{1 .. 11} compression option
t is turbo, f is fast, m is mid, h is high, x is max (default mid)
0 .. 11 specifies memory with 32mb .. 5gb per thread (default 6)
10 and 11 are only supported on 64 bits
-test tests the file after compression is done
Examples:
Compress: mcm.exe -m9 enwik8 enwik8.mcm
Decompress: mcm.exe d enwik8.mcm enwik8.ref
Failed to parse arguments
cs


 MCM은 총 4가지의 설정과 0~11까지 설정하는 것이 있다.


 t는 turbo, f는 fast, m는 mid, h는 high, x는 Max이다.(기본적으로 mid로 설정되어 있다.)


 t에서 x로 가면 갈 수록 속도가 느리고, 압축률이 높아진다.


 0~11의 설정이 되는데, 이것은 32Mb에서 5~6GByte까지 사용이 된다.


 여기서 10과 11은 64Bit에서만 지원이 가능하므로, 주의를 요한다. 라고 되어있다.


 그리고 압축을 풀려면, d을 사용하면, decompression이라고 할 수 있다.


 압축/풀기 예제

1
2
mcm -x11 enwik8 enwik8.mcm
mcm d enwik8.mcm enwki8
cs

 

 이렇게 해서 사용을 할 수 있게 된다.


 이것이 조금 더 발전을 해서 압축율이 높은 프로그램이 완성이 되었으면 한다.

  1. 참조 : https://en.wikipedia.org/wiki/PAQ(2016-07-08) [본문으로]
Posted by JunkMam
,

 ffmpeg을 병합이 있다면, 잘라내는 방법이 있어야 될 것이다.


 이것 또한, ffmpeg wiki에 들어간다면, 찾을 수 있을 것이다.



 ffmpeg는 병합과 다른 점이 하나의 문서 파일을 이용하는 것이 아닌, 각각의 파일로 처리하는 것이다.


 파일로 출력하는 방식은 다음과 같다.


 

1
ffmpeg -i 자를영상.mp4 -ss 0 -62 -vcodec copy -acodec copy 잘려진 결과.mp4 -y
cs


 여기서 -i는 입력 파일을 뜻하고, -ss는 Start Second, -t는 해당 파일 범위를 뜻한다.


 -t는 Second 단위를 뜻한다.


 -vcodec 혹은 -c:v로도 표현이 가능한 것으로 video codec 혹은 codec : video를 뜻한다.


 -acodec 혹은 -c:a는 audio codec을 뜻한다. codec : audio를 뜻하기도 한다.


 여기서 각각 copy라는 뜻은 잘려나가는 영상의 코덱과 오디오의 설정을 동일화시킨거라도 이해하면 된다.


 -y는 동일 파일을 가지고 있을 경우에는 항상 덮어씌우는 작업을 뜻한다.


 그래서 위의 예제는 자를영상.mp4에서 0초에서 62초까지 잘라서 잘려진 결과.mp4라는 파일이 나오게 되는 것이다.

Posted by JunkMam
,

 ffmpeg을 병합해야되는 경우가 있다.

 병합을 하게 된다면, 용량이 증가하는 경우가 많다. 그래서 병합을 할려면, 한번에 볼려고 생각하는거 아닌이상, 병합을 하지 않는게 나은 것이다.


 ffmpeg의 사용법이 영어로는 존재한다.[각주:1]


 먼저 ffmpeg의 병합을 하기 위해서는 먼저 텍스트 파일로 만들어야한다.


 list.txt

 

1
2
3
4
# this is a comment
file '/path/to/file1'
file '/path/to/file2'
file '/path/to/file3'
cs



 이렇게 제작한다.


 여기서 '#'은 주석처리하는 것이다.


 file '파일명' 으로 설정을 할 수 있다.


 이렇게해서 list.txt을 넣어서 처리하면 된다.


 그런데, 이것이 영상파일이 아닌 정보를 병합하는 것이다. 라는걸 표시해야된다.


 

1
ffmpeg -f concat -i list.txt -c copy output
cs


 이렇게 사용해줘야한다.


 그리고 list.txt을 만드는 방법은 bash shell을 이용해서 넣는 것이다.


 컴퓨터 command을 이용해서 명령어를 이용해서 만들어 낼 수 있다.


 

1
(for %i in (*.wav) do @echo file '%i') > list.txt

cs


 이런식으로 말이다.


 powershell을 이용해서 만드는 것이라면, 다음과 같은 방식으로 표현을 할 수 있다.


 

1
2
3
4
$n=((Get-childItem ./*.mp4).name);
for($i=0; $i -le $n.length; $i++){
    $n[$i]>>list.txt
}
cs


 이렇게하면, 이름순으로 나와서 영상의 이름을 순차적으로 처리해줘야한다.

  1. https://trac.ffmpeg.org/wiki/Concatenate(2016-07-05) [본문으로]
Posted by JunkMam
,

콘솔 위치 옮기기.

연습 2016. 7. 12. 00:00


 윈도우에서 콘솔을 컨롤하기 위해서는 출력부분을 초기에 받아서 사용한다.


 중요한 것은 컴퓨터에서 기본적으로 밖으로 출력하는 부분을 가지고오는 것인데, 이 함수는 다음과 같은 함수를 사용한다.


 GetStdHandle();[각주:1]


 이 함수는 핸들을 받아와서 개발자가 컨트롤을 할 수 있게 해주는 함수이다.


 GetStdHandle외에도 SetStdHandle이라고 해서 기본 핸들러를 수정할 수 있게 한다.


 여기서 StdHandle이란, 기본적으로 컴퓨터가 실행이 될때 설정이 되는 핸들이다.


 대표적으로 우리가 모니터에서 화면을 출력하게 만드는 것은 컴퓨터가 기본적으로 모니터에 출력값을 처리 할 수 있게 만들어 주기 때문이다.


 키보드와 마우스 또한, 컴퓨터에 입력을 받기 위해서 사용한다. 이게 가능한 것은 컴퓨터가 키보드의 입력을 기본적으로 받아들여서 처리하도록 입력이 받아져 있기 때문이다.


 그래서 출력하는 부분을 개발자가 받아서 이 것을 수정하도록 만들면 우리가 원하는 위치에 문자가 나오게 하거나, 커서가 이동되는 효과를 얻을 수 있게 되는 것이다.


 예제

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>
 
#include <stdlib.h>
 
#include <windows.h>
 
int main(int argc, char* argv[]){
    int x = 10;
    int y = 1;
    
    COORD pos = {x, y};
    
    HANDLE stdHandle = GetStdHandle(STD_OUTPUT_HANDLE);
    
    SetConsoleCursorPosition(stdHandle, pos);
    printf("#\n");
    
    system("pause");
    
    return 0;
}
cs



 여기서 GetStdHandle이라는 것이 핸들을 반환한다고 했기 때문에, 우리는 HANDLE 형태의 변수를 사용해야된다. 그리고, 평면위의 위치이기에. x, y라는 독립 변수가 2개를 가지는 변수 pos을 가지고 있어야된다.


 이제, 캔퍼스와 연필을 얻었으니, 점을 직어야 될 것이다.


 이러한 행동을 하는 함수가 바로 SetConsoleCursorPosition이다.


 핸들과 위치를 가지고 위치가 이동되는걸 알 수 있다.


 이렇게 해서 로그라이크의 이동을 표현 할 수 있게되고, 로그라이크에서 기본적으로 이걸 이용해서 제작하는 경우도 있다.


 리눅스에서는 SetConsoleCursorPosition이라는 함수는 없기에 이와 유사한 함수가 있는 라이브러리를 사용한다.


 그것을 curses와 ncurses라는 라이브러리이다.

  1. https://msdn.microsoft.com/ko-kr/library/windows/desktop/ms683231(v=vs.85).aspx [본문으로]
Posted by JunkMam
,

C언어 키 눌음 처리.

연습 2016. 7. 11. 00:00

 키 눌음 처리 이벤트로 하는 방법과 kbhit() 함수를 사용하는 방법. GetAsyncKeyState()을 이용하는 방법이 있다.


 이벤트는 앞써 설명한 방법으로 WM_KEYDOWN과 WM_KEYUP등을 이용한 방법이다.


 kbhit()은 키보드에 입력을 받았는지 확인하는 방식으로 다음과 같이 사용이 가능하다.


 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
#include <conio.h>
 
int main()
{
    int key;
 
    if(kbhit() != 0)
    {
        key = getch();
    }
 
    return 0;
}
cs


 GetAsyncKeyState()는 윈도우스에서 키가 눌러졌는지 확인 하는 것으로, 위에 설명한 방식은 다중 키 입력을 받을 수 없다. 하지만, 이 함수를 사용한다면, 다중으로 다운을 받을 수 있게 된다.


 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <stdio.h>
#include <stdlib.h>
 
#include <windows.h>
 
int main(int argc, char** argv)
{
    while(1)
    {
        if(GetAsyncKeyState(VK_UP)!=0)
        {
            printf("Key Down : UP\n");
        }
        if(GetAsyncKeyState(0x41)!=0)
        {
            printf("Key Down : A\n");
        }
        if(GetAsyncKeyState(0x1B)!=0)
        {
            break;
        }
    }
    return 0;
}
 
cs


Posted by JunkMam
,

 Win32에서는 키보드 입력 메시지또한 처리 할 수 있다.


 C언어에서는 kbhit()라는 함수등을 사용한다.


 키보드는 키를 눌렀을때, 떼었을때, 문자일때로 나뉘어 져있다.


 키보드의 정보는 Virtual-Key라는 것을 이용해서 구분을 짓는다.[각주:1]


 예제

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#include <stdio.h>
#include <stdlib.h>
 
#include <tchar.h>
#include <windows.h>
 
#include <string.h>
 
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
HINSTANCE g_hInst;
 
WNDCLASS WndClass;
 
int numbers = 0;
 
int WINAPI WinMain(HINSTANCE hInstance,
            HINSTANCE hPrevInstance,
            LPSTR lpszCmdParam,
            int nCmdShow)
{
    HWND hWnd;
    MSG Message;
    g_hInst = hInstance;
 
    WndClass.cbClsExtra=0;
    WndClass.cbWndExtra=0;
    WndClass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
    WndClass.hCursor=LoadCursor(NULL,IDC_ARROW);
    WndClass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
    WndClass.hInstance=hInstance;
    WndClass.lpfnWndProc=(WNDPROC)WndProc;
    WndClass.lpszClassName="ApiBase";
    WndClass.lpszMenuName=NULL;
    WndClass.style=CS_HREDRAW|CS_VREDRAW;
 
    RegisterClass(&WndClass);
    
    hWnd = CreateWindow("ApiBase",
                        "Test",
                        WS_OVERLAPPEDWINDOW,
                        10,// X
                        100,// Y
                        400,// Width
                        400,// Height
                        NULL,
                        (HMENU)NULL,
                        hInstance,
                        NULL);
 
                        
    ShowWindow(hWnd,nCmdShow);
    
    while(GetMessage(&Message,0,0,0))
    {
        TranslateMessage(&Message);
        DispatchMessage(&Message);
    }
    
    return Message.wParam;
}
 
LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{    
    switch(iMessage)
    {
        case WM_CREATE:
            strcpy(strTemp, "");
            break;
        case WM_KEYDOWN:
            switch(wParam)
            {
                case VK_HOME:
                    printf("Home\n");
                    break;
                case VK_END:
                    printf("End\n");
                    break;
                case VK_UP:
                    printf("Up Key\n");
                    break;
                case VK_F1:
                    printf("F1\n");
                    break;
                case 0x41:
                    printf("A\n");
                    break;
            }
            break;
        case WM_LBUTTONUP:
            printf("%d\n",ReleaseCapture());
            break;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
    }
    return DefWindowProc(hWnd,iMessage,wParam, lParam);
}
 
cs


 하지만, 키보드 메시지를 사용한다면, 연속적으로 눌은 키에 대한 정보는 처리가 되지 않는다.


 쉽게 말해서 노트패드에 정보를 입력해보자.


 동시다발적으로 여러 키를 눌을 경우에, 해당 키의 정보를 다 읽지 못하고, 하나의 키만 처리하는걸 알 수 있을 것이다.(노트패드에서 이렇게 처리할 경우가 있을리도 만무하다.)


 이유는 메시지가 하나의 값만 계속 받아서 처리하기 떄문일것이다.


 그럴때는 어떻게 하는가?


 이것은 다음 네이버 카페에서 도움을 받았었다.[각주:2]


 여기서, GetKeyState 라는 함수를 사용하면 된다.[각주:3]


 해당 함수는 키의 눌음을 인식하는 함수이다.

  1. 참조 : https://msdn.microsoft.com/ko-kr/library/windows/desktop/dd375731(v=vs.85).aspx (2016-07-05) [본문으로]
  2. http://cafe.naver.com/cafec [본문으로]
  3. https://msdn.microsoft.com/ko-kr/library/windows/desktop/ms646301(v=vs.85).aspx [본문으로]
Posted by JunkMam
,