'분류 전체보기'에 해당되는 글 18건
- 2020.08.11 임시보관
- 2019.07.07 고스트로 복사한 윈도우SSD가 부팅되지 않을 때!
- 2015.04.21 윈도 부팅시 파란화면 에러. V3 복구를 의심해봐야
- 2014.09.29 미디. 채널과 동시 음
- 2014.07.16 윈도우XP 지원 종료를 보면서 느끼는 수익모델 문제
- 2014.07.02 자바스크립트, 스네이크 업로드 테스트. 수동으로 붙여넣어야함.
- 2014.05.12 템플릿 함수 접근의 이점
- 2014.05.09 template, class VS typename
- 2014.04.08 파티션 조정 후 에러 발생, hal.dll
- 2014.03.26 MMORPG의 문제 = 도전 문제
- 2013.09.14 스마트폰
- 2013.02.25 윈도우로 보는 소프트웨어 수익모델 문제
- 2012.03.09 함수자+강제 인라인+템플릿
- 2012.02.10 하드디스크 복구, 파티션 에러, TESTDISK 강추
- 2011.05.11 디스어셈블, gcc보다는 objdump가 나은듯 하다.
- 2011.05.06 인라인 함수 강제로 적용 __attribute__((always_inline))
- 2010.11.14 속도VS공간
- 2010.11.04 gif 디코딩, breakdown(?) 문제 해결
결론부터 짧게.
씽크패드의 사용 중인 윈도 SSD를 다른 SSD에 복제했는데 부팅이 되지 않는다면 이 방법을 써라.
특히 다른 PC등에서 인식이 잘 되는데, Disk read error와 함께 막힌다면.
1. 대상이 될 빈 하드디스크는 씽크패드의 하드 슬롯에 장착한다.
2. 원본은 외장 하드 케이스에 넣어 USB슬롯에 연결한다.
3. 사용하는 복사 프로그램이 든 씨디, USB로 부팅(이 경우는 도스 부팅 후 고스트를 사용했다)
4. 복사한다.
5. 원본과 복사 프로그램을 제거하고 재부팅하면 OK
요점은 1번이다. 씽크패드의 하드디스크 슬롯에 장착한 채로 복사한다는 것.
다른 랩탑, 노트북에도 같은 문제가 있는지 모르겠지만
위의 SSD도 해당 씽크패드X200이 아니라 데스크톱에서는 인식되고 부팅이 잘 됐었다.
하지만 자기 HDD슬롯이 아닌 곳에서 복제된 경우에는 어떤 툴, 어떤 연결법을 쓰던
Disk Read Error와 함께 부팅이 되지 않았다.
나는 이 문제로 일주일을 날렸지만, 혹여 나 같은 경우가 있다면 도움이 되기를 바란다.
윈도우를 사용하다보면, 간혹 파란화면이 뜨고 무한 재부팅이 되는 문제가 생기는 경우가 있다.
그 원인이나 해결책은 다양하지만, 노트북과 같이 이미 복구 시스템이 설치되어 있는데
V3의 복구 기능을 설치하고 부팅이 안된다면 이 방법을 적용할 것.
해결책은 간단하다. V3의 복구 알림창이 뜰 때, Ctrl + Alt + 백스페이스키를 누르면,
비밀번호 입력 창이 뜨는데 기본값인 0000을 입력한 후,
선택 항목 중 현재 상태를 저장하고 제거를 선택하면 된다. (이 때 처리에 잠시 시간이 걸린다.)
참고로 fixboot + fixmbr + chkdsk 해법을 써야 될 때도 있는 모양.
PS. 고치기 전에 데이터 백업을 하는 건 필수. 잘 안될 수도 있으니까.
GM, 일반 미디 규격에 따르면
신디사이저는 16개의 채널을 가져야 되고
채널별로 최소 16~24음을 동시에 낼 수 있어야 된다고 되어 있었다.
그러면 최대 16x16~24음을 내는거니까, 256~768음이 동시에 발생할 수 있다는거다.
윈도우의 소프트웨어 미디 음은 어떨까? 아무래도 대다수 유저는 이걸 쓰겠지.
의문1: 채널마다 한 악기의 음만 낼 수 있는가?
그건 아니다. 여러 악기의 소리도 난다. 하지만 음 높이가 겹치면 안 된다.
즉 피아노와 바이올린이 동시에 도 소리를 내는 건 불가능하다는 의미다.
음이 겹치면 기존의 음은 사라진다.
동시 발생음, poluphoniy라고 하는데, notes가 여러개 연주된다고 하는게 이런 의미인듯.
의문2: 타이밍은? 1/4음표의 1/24간격으로 클럭이 전송된다.
4*24=96분 음표까지 나타낼수 있는셈.
120bpm의 경우 1초에 2개씩 재생하는 샘.
1초를 48개로 분할하면 된다.
1000/48=약20~21ms간격으로 체크하면 된다.
보간에 브레센햄에서 쓰던 방식을 쓰면 되려나.
glut의 경우는 진행ms를 비교하면 된다.
굳이 윈도 미디 함수를 안 쓰고, 직접 음을 합성하면 더 여유로울 수도 있다.
최근 내장 사운드도 최소 24비트는 지원하니까.
쓰던 OS가 지원이 종료되는 건 이번이 처음이 아니다.
도스에서 윈도우95로
95에서 98로
98에서 2000, XP로 이미 지나왔다.
왜 이미 확보해둔 시장을 버려야 하는가?
하드웨어의 변화, 소프트웨어의 노화..
내가 보는 문제는 수익모델이다. MS는 OS소프트웨어를 팔아야 돈을 번다.
그러니 더 이상 OS가 안 팔리면 지원중단을 선언하는 수 밖에 없는거다.
희귀하게도 영국에서는 의료장비의 서비스를 연장하는 댓가로 연간 100, 200, 400$ 이런 식으로
추가 비용을 받고 지원을 연장한다고 한다. 결국 돈이 문제인거다.
프로그램 자체가 낡으면 사실 고치는것 보다 새로 만드는 게 낫다.
하지만 돈이 된다면 새로 만들면서 기존 틀에 맞춰서 만들 수도 있지.
새 버전으로의 교체가 간단하고, 마치 USB나 롬팩 갈아끼듯이.
기존 '유저의 데이터'를 별 신경안쓰고 쓸 수 있다면,
기존 틀을 유지한 신 버전을 계속 파는게 괜찮지 않을까.
OS는 몰라도, 일부 어플리케이션은 UI나 뭐나 손댈 필요가 없는 걸 건드리기도 한다.
게임은 어떨까. 실행 프로그램은 달라지지만 유저가 참가하는 게임은 불변해야 한다.
스타크래프트1같은 것 껍질만 바꿔 재발매를 했어도 괜찮았으리라 생각한다.
(1)기존 틀 유지
(2)유저 데이터 보존
(3)지속 판매
흠. 아주 이상적인 목표같은데, 실현가능할까 궁금하다.
PS. 데이터란 게 참 애매한데, 기존에는 문서, 그림같은 걸 의미했다.
하지만 포터블툴들이 많이 나오고, 에뮬레이터나 가상머신이 흔한 지금,
소프트웨어 그 자체는 어떨까.
클래스나 구조체 내의 어떤 멤버 변수나 가상값에 접근하기 위한 템플릿 함수를 생각했다.
template<class type, class member>
member& getX( type& src );
왜 굳이 템플릿 함수를 사용하는가.
템플릿을 쓰면 불특정 대상이 해당 기능을 제공하기만 하면 작동한다.
대상 클래스를 바꿀 필요가 없다.
템플릿 특수화를 쓰면, 만약 내부에 변수가 없거나 특수하게 저장되어 있더라도
'일반적'으로 찾아오거나 찾아오는 기능을 외부에서 지시할 수 있다.
상속을 통해 기능을 확장해가는 것과는 좀 반대되는 접근같기도 하지만,
한 클래스를 쓰는 방법을 다양화시키는 식으로 기능을 확장시켜나간다는 점에서는
큰 차이는 없는것 같다.
template< class T >
혹은
template< typename T >
이렇게 class와 typename을 선택해서 쓸 수 있다.
나는 주로 class를 사용한다.
그냥 짧아서라는게 주요 이유겠지만,
사실 typename에 거부감이 들어서라는게 맞을것이다.
C++은 객체지향 언어고, 템플릿도 그 기능을 확장하기 위해서 들어온거다.
템플릿을 단순히 매크로로 취급한다면 typename이 맞겠지만, 객체를 취급하는 상황에서는
object라고 하는게 더 어울렸겠지만, class라고 하는게 typename보다는 나은거 같다.
파티션 매직이나 다른 툴로 파티션 관련 처리를 하고 나서 생기는 문제.
내 경우에는 새로 파티션을 하나 만들고 난 뒤에 문제가 생겼다.
이런 메시지가 나온다. 나도 그랬지만 이런 상황이 생기면 엄청 놀라게 될 것이다.
중요한 자료가 가득찬 하드를 포멧할지 모르니 말이다.
하지만 이건 기존 파티션 번호가 바뀌어서 부트로더가 파티션을 찾지 못해 생긴 문제였다.
보통 C드라이브의 boot.ini가 있는데, 부팅할 파티션이 위치가 기록되어 있다.
default=multi(0)disk(0)rdisk(0)partition(2)\WINDOWS
이런 부분이 보이는데, 밑줄친 부분이 파티션의 번호다.
파티션을 추가하거나 삭제한 경우, 그에 맞게 이 번호를 증감시켜주면 다음번에 제대로 부팅되는 걸 볼 수 있을것이다.
국산 MMORPG가 저물어가는 느낌이다.
다른 건 둘째치고, 별 기대도 없고 하고 싶지도 않다는거다.
삼국지같은 경우, 쉽게 하려면 쉽게 할 수도 있었다.
그냥 조조를 선택하면 땅도 넓고 유리하며 유능한 장수도 넘친다.
하지만 점점 룰을 잘 알게되고 더 큰 도전을 찾게되면 신군주나 열악한 군주를 선택하게 된다.
물론 주인공의 발전이란 개념이 매력적인 건 사실이다.
하지만 그건 더 큰 도전이 뒷받침될 때 의미가 있다.
그냥 무작정 게임이 쉬워지기만 하면 재미가 없다.
골수 게이머는 MMORPG의 수익원으로서는 별로다.
하지만 게임플레이를 창조하고 도전거리를 찾아내는건 잘 한다.
그리고 이런 게이머들이 다른 유저들을 불러들인다.
MMORPG에는 골수 게이머들이 파고들 건덕지가 남아있지 않다.
보통 스마트폰이라고 하면, 넓은 화면에 터치식 인터페이스를 갖춘 게 많다.
하지만 정말 스마트한 것은 쓰는 사람이 소프트웨어를 작성할 수 있다는거다.
모양은 전화기답게 생기는게 좋다고 생각한다.
휴대하기 편하게 작고, 전화번호를 누를 수 있는 큰 자판이 달려있는것이다.
소프트웨어란 것은 실체가 없다. 그래서 실제 물건의 판매와는 돈 버는 방법이 좀 달라진다.
그 중 대표적인 것이 패키지 형태로 판매하는 방식이다.
그리고 그런 제품 중 가장 많이 팔린 게 바로 윈도우 운영체제가 아닌가 싶다.
이 수익모델의 단점은 살 사람이 다 사면 수익이 급감한다는 점이다.
그리고 유지보수 비용은 받을 수 없다는 것도 문제다.
그래서 MS가 택한 전략은 주기적으로 신 버전의 OS를 내놓는 것이었다.
하지만 사용자 입장에서는 이것만큼 불편한게 없었다.
같은 컴퓨터의 사용법을 매번 다시 배워야했으니 말이다.
도스, 윈도우3.0, 윈도우95, 윈도우98, 윈도우2000, 윈도우XP, 윈도우7, 윈도우8
꼭 매번 새로운 OS로 나왔어야했는가 의문이다.
소프트웨어는 모두 일종의 플랫폼이다. 생각의 '받침대'란 의미에서 더 그렇지.
이게 자꾸 바뀌는 건 받아들이기 어렵다. 나아가서는 괴롭다.
게다가 기존 소프트웨어에 새 기능을 추가하는 건 그다지 어렵지 않고 말이지.
효율성은 좀 떨어지더라도 쓸 수만 있으면 되니까.
다시 수익모델 문제로 돌아와서, 지속적인 유지비용을 받는다면 이런 틀 변화는 굳이 필요가 없다.
하지만 왠지 사람들의 불안감을 자극한다.
패키지 방식 판매가 참 깔끔하긴 한데, 확장팩을 파는 식으로 유지비용을 받는다면 어떨지.
딜레마가 아닐 수 없다. 시장에 경쟁자가 넘치는데, 어떤 기능에 돈을 받고 어떤 기능은 공짜로 제공할지가.
최근 구글의 광고중심 무료어플리케이션은 그런 의미에서 괜찮기는 하다.
많은 사람들이 쓰면 광고 효과도 높아지니 공짜로 뿌리더라도 수익성은 더 좋아지게 된다.
하지만 모든 일에는 장단점이 있고, 좋아만 보이던 MMOPRG의 부분유료화도 사행성이란 문제에 부딪히니까.
일단 굳어진 수익모델은 바꾸기가 어렵다. 무료로 끌어모은 사용자를 유료화시 잃는 것도 그렇고,
데몬툴즈의 사례도 있고.
광고는.. 쓰는 사람이 귀찮기도 하고 신뢰도도 떨어뜨린다. 광고주가 누가 될거냐는 문제도 있고.
돈버는 일은 참 깔끔하지가 않다. 가치를 인정받고 가치에 해당하는 돈을 받는것은 언제나 어려운 것 같다.
함수자+강제 인라인+템플릿을 써야 한다.
하지만 효율이 걱정되는 부분이 있었다.
클래스 함수를 호출할 때, this를 전달하는 오버헤드라던가 인라인 함수가 잘 될까 하는 부분이라던가.
그리고 템플릿을 사용한 함수자가 컴파일이 잘 안되는 문제 등.
1. 컴파일 문제는 컴파일러 버전 문제로, 템플릿 함수자는 gcc 3.x 버전에서
"function body not available" 이란 에러를 냈었다. 4.x에서 이 문제는 해결됐으며 잘 되는 걸 확인했다.
2. 인라인이 함수자와도 잘 맞을까 하는 걱정도 없어졌다.
test2( a, 8 ); //class Functor의 op()로 만든 함수자
c9: c7 44 24 10 08 00 00 mov DWORD PTR [esp+0x10],0x8
d0: 00
d1: 8b 44 24 10 mov eax,DWORD PTR [esp+0x10]
d5: a3 00 00 00 00 mov ds:0x0,eax
이렇게 3줄로 번역되었고, this 전달은 일어나지 않았다.
지금은 정확히 상황이 기억이 안 나는데, 토렌트로 뭔가를 받던 도중
갑자기 디스크 쓰기 에러가 발생해서 껐다가 켰다.
윈도우가 무사히 부팅되길래 별일 아닌가 했는데, 데이터가 보관된 디스크가 통째로 사라진것.
정확히는 FAT32로 포멧된 200기가 정도 하드가 갑자기 FAT16으로 잡히는 것이었다.
게다가 윈도우XP 프로그램들도 사라져서 난감해졌다.
http://www.cgsecurity.org/wiki/TestDisk
결론부터 말하면, TESTDISK라는 공개 디스크 복구 도구를 사용해서 일단 데이터를 살렸다.
내 경우는 좀 어려웠는데, 파티션이 완전히 사라진 게 아니라 이상한 FAT16파티션이 생겨 있었고,
부트 섹터( 부팅 디스크가 아니더라도 데이터를 읽으려면 필요하다고 한다)가 손상되어 있었기 때문이다.
처음엔 어려웠는데 윈도우XP로 부팅된 상태에서는 수정된 파티션을 쓸 수가 없었기 때문.
결국 부팅디스크(이번엔 USB로, 플로피나 CD도 되는 모양이다)를 만들어 재부팅을 해서
TESTDISK를 실행해야 했다.
복구 과정 자체는 엄청 단순하다. 외국의 어떤 분은 이거(TESTDISK) 찾는데 2주가 걸렸는데,
정작 되살리는 데는 2분이 걸렸다고 말하는 사람도 있다.
1. 프로그램 실행
2. 디스크 선택
3. 현재 파티션 정보를 보고
4. 파티션이 없다면 Search로 찾는다.
5. 그래도 안 나오면 다음 단계에서 Deep Search를 한다.
6. 발견된 결과에서 파일을 볼 수 있다(귀한 파일을 다시 보면 10년 감수의 기분!)
7. 이 때 조심스레 파티션 정보를 수정해서 되살리고 저장( Write )
8. 내 경우에는 부팅 섹터가 손상되어 있었다. 어드밴스드에 들어가서 부트섹터 복구
(FAT32는 단순했는데, NTFS나 다른 것들은 방법이 좀 다른 모양이다)
9. 저장하고 재부팅하니 완전히 복원되어 있었다.
이런 좋은 도구가 완전 공개에 소스까지 공개되어 있다. 정말 감사하지 않을 수 없다.
아예 인식이 안되거나, 틱틱 소리가 나는 기계 고장이 아니라면 사용을 추천.
PS. 파티션 손상의 주범으로 바이러스가 의심되는데, 이제 알아보러 가야겠다.
결론부터 말하면, 컴파일된 오브젝트 파일( *.o )을 objdump로 보는게 gcc의 옵션을 통해 출력하는 것보다 낫다는 것이다.
gcc의 출력은 일단 좀 산만하기도 하고, C++ 코드와 어셈블리 루틴이 정확히 매치되지 않아서 좀 보기가 힘들다.
아래의 예를 보면, C++ 구문 아래에 번역된 어셈블리 결과가 매치되어 보이는 걸 알 수 있다.
-Mintel 옵션을 붙이면, 인텔 문법의 어셈블리가 나오고,
-C 옵션을 붙이면, 함수 이름이 demangle되서 우리가 알아볼 수 있게 나온다.
하지만 인라인 함수 알아보기 힘든건 여전함.
ps. gcc로 컴파일할 때, -g 옵션을 붙여 디버깅 정보를 넘겨줘야 한다. 안그러면 C++코드가 안나오네.
인라인 함수 강제로 적용 __attribute__((always_inline))
인라인 함수 강제로 적용 __attribute__((always_inline)) 카테고리 없음 2011. 5. 6. 22:15inline 키워드는 GCC에서는 강제가 아니다. 그건 괜찮은데, 최적화 레벨을 높이지 않으면 간단한 메소드도 인라인하지 않는다.
최적화 레벨을 높이는 것이 어렵진 않지만, 흠, 개발 중엔 최적화 플래그를 안 쓰는데 인라인이 안 되다니 찝찝하다.
inline __attribute__((always_inline)) void func(){ printf("always_inline!\n"); }
__attribute__((always_inline)) 이 키워드를 써 줌으로써 최적화 레벨에 상관없이 함수를 인라인한다.
/main.cpp----------------------------------------------------------------------/
#include <cstdlib>
#include <iostream>
using namespace std;
inline __attribute__((always_inline)) void func(){ printf("always_inline!\n"); }
inline void func2(){ printf("inline!\n"); }
void func3(){ printf("normal function!\n"); }
int main(int argc, char *argv[])
{
func();
func2();
func3();
system("PAUSE");
return EXIT_SUCCESS;
}
/---------------------------------------------------------------------------/
위와 같은 코드를 컴파일하면, 아래와 같은 결과가 나온다.
call ___main
movl $LC1, (%esp) //강제 인라인한 메소드, 직접 어셈블리로 번역되었다.
call _printf
call __Z5func2v //일반 인라인인 경우, 번역않고 CALL을 한다.
call __Z5func3v //일반 함수의 경우 당연히 CALL
movl $LC2, (%esp)
call _system
movl $0, %eax
즉, 최적화 플래그 (-Ox )를 쓰지 않고도 인라인 함수 기능을 쓸 수 있다는 것. 명령어가 좀 길지만,
#define macro inline __attribute__((always_inline))
식으로 정의해서 쓰면 괜찮을 듯 하다.
PS.인라인 함수 안에 인라인 함수를 쓰거나 순환 관계가 생기거나 하면 컴파일하다 재난이 발생하는 모양이니
생각보다 복잡한 기능인가 보다.
비트필드를 불리언으로 쓰는게 좋은가에 대한 글을 봤는데.
최근 CPU가 16, 32비트 단위로 일을하는 경우가 많아서
잘라내고 하는 등 부가적인 처리를 하면
오히려 성능에 나쁘지 않을까 하는 이야기를 봤다.
*일단 비트를 잘라내는 건, 생각보다 쉽다. 미리 준비해둔 마스크( unsigned char maskType=0x0100; )과
AND를 하면 쉽고 빠르게 체크를 할 수 있다. 경우에 따라 여러 플래그를 동시에 체크할 수도 있고.
*한편 CPU속도가 빨라진만큼, 공간을 아끼는게 좋은 경우도 많다. 좋은 예는 동영상과 음성파일이다.
*디아블로2같은 경우, 무기의 성능에 비트단위로 자른 스텟을 붙이는 걸 봤다.
아마 서버에 저장해야되는 아이템의 정보를 절약하려면 필수적인 조치였던거 같다.
*한편, 무작정 공간을 낭비하는 방향을 잡으면 오히려 역효과가 날 수도 있다.
1메가에 넣을 자료를 8메가에 넣고, 1기가에 들어갈 자료를 8기가에 넣는다고 생각해보자.
로딩이나 메모리 복사 등에 걸리는 시간도 길어지고, 메모리 안에서 다 할일도 로딩을 반복해야할 수도 있다.
공간을 희생해서 속도를 얻는다는 목표에서 어긋나게 되는것.
*결국은 프로그램의 용도가 중요하다고 하겠다. 비트단위로 아낄 수 있는 용량이 많다면
써야 될 거고, 득이 크지 않으면 안써야겠지.
*흠. 비트단위로 들어갈 정보를 묶어서 넣는게 일반적이지만, 남는 공간을 활용하는 것도 좋을거 같다.
예를 들어 인간의 나이는 7비트로 충분하다. 남는 1비트를 쓸 수 있는것.
http://www.martinreddy.net/gfx/2d/GIF-comp.txt
본문중
Now let's consider the possibility that <code> is not in the string table.
이제 <코드>가 테이블에 없는 경우를 생각해보자.
Think back to compression, and try to understand what happens
when you have a string like P[...]P[...]PQ appear in the charstream.
압축 과정으로 돌아가서 생각해보자. 만약 당신이 "P[...]P[...]PQ"란 문자열을
보게 되었을때 어떻게 될지 살펴보자.
Suppose P[...] is already in the string table, but P[...]P is not.
"P[...]" 는 이미 테이블에 있지만, P[...]P는 아직 없다고 해보자.
Thecompressor will parse out P[...], and find that P[...]P is not in the string table.
압축기는 P[...]를 분리해내고, P[...]P가 아직 테이블에 없다는 걸 발견한다.
It will output the code for P[...], and add P[...]P to the string table.
그러면 P[...]의 코드를 출력한 다음, P[...]P를 테이블에 추가할 것이다.
Then it will get up to P[...]P for the next string,
그리고는 다음 문자열에서 P[...]P를 마주치게 된다.
and find that P[...]P is in the table, as the code just added.
그리고 방금 테이블에 추가된 P[...]P의 코드를 찾게된다.
So it will output the code for P[...]P if it finds that P[...]PQ is not in the table.
그러고 P[...]PQ는 테이블에 없다는 걸 알고 P[...]P의 코드를 출력한다.
The decompressor is always "one step behind" the compressor.
해제기는 항상 압축기보다 한 발 처져있다.
When the decompressor sees the code for P[...]P, it will not have added that code to it's string table yet because it
해제기가 P[...]P의 코드를 봤을 때, 그것은 아직 테이블에 추가하기 전일 것이다.
needed the beginning character of P[...]P to add to the string for the last code, P[...], to form the code for P[...]P.
왜냐하면 P[...]P의 시작문자를 마지막 코드의 문자열, P[...], 뒤에 덧붙여야 P[...]P의 코드를 얻을 수 있기 때문이다.
However, when a decompressor finds a code that it doesn't know yet, it will always be the very next one to be added to the string table. So it can guess at what the string for the code should be, and, in fact, it will always be correct.
그렇지만, 해제기가 아직 모르는 코드를 발견했다면 그건 항상 바로 다음번에 테이블에 추가될 코드다.
그러니 그 코드를 위한 문자열이 무엇이 되어야 할지 짐작할 수 있고, 사실 그건 항상 옳다.
(즉 마지막으로 사용한 문자열의 첫 문자를 끝에 붙인 문자열이 새 코드에 해당된다는것.
좀 이상한 논리지만, 반복되는 부분이 많은게 이미지 파일의 특성이니 어찌보면 자연스럽다.)
If I am a decompressor, and I see code#124, and yet my string table has entries only up to code#123, I can figure out what
code#124 must be, add it to my string table, and output the string. If code#123 generated the string, which I will refer to here as a prefix, [...], then code#124, in this special case, will be [...] plus the first character of [...].
해제기의 입장에서 보자면, 내가 [124]란 코드를 발견했는데 아직 테이블은 [123]까지 밖에 없다. 그러면 나는 [124]가 뭐가
되야할지 알 수 있고, 그걸 테이블에 추가한 후 출력한다. 만약 코드[123]이 문자열을 만들어냈다면, 내가 접두사로 찾을 것은,
[...]에서, 그리고 코드[124]란 경우에는, [...]에다가 [...]의 첫 문자를 더하면 된다.
So just add the first character of [...] to the end of itself. Not too bad.
그러니 그냥 [...]의 첫문자만 끝에 추가하면 된다. 별거 아니군.
As an example (and a very common one)
예를 들어보자
of this special case, let's assume we have a raster image in which the
first three pixels have the same color value. That is, my charstream
looks like: QQQ....
3픽셀이 같은 값을 갖고 있는 특수한 경우에 대해서.
문자열로 보면 이렇게 보일 것이다: QQQ...
For the sake of argument, let's say we have 32 colors, and Q is the
color#12. The compressor will generate the code sequence 12,32,....
우리가 32색으로 작업하고 있다고 가정하자. 그리고 Q는 색번호 12번이다.
압축기는 [12],[32] 라는 코드들을 만들어 낼 것이다.
(if you don't know why, take a minute to understand it.) Remember that
(당신이 아직 이유를 모른다해도, 잠깐 생각해보면 이해할 것이다.) 기억하라
#32 is not in the initial table, which goes from #0 to #31. The
[32]란 코드는 초기 테이블, 32색이므로 0~31까지 있는, 에 없다.
decompressor will see #12 and translate it just fine as color Q. Then
압축해제기는 [12]란 코드를 보고 Q로 해석할 것이다.
it will see #32 and not yet know what that means. But if it thinks
그리고는 [32]란 코드를 보게 되는데 아직 그 의미를 모른다.
about it long enough, it can figure out that QQ should be entry#32 in
그러나 잠시 생각해보면, [32]란 코드에 맞는 건 "QQ"밖에 없고
the table and QQ should be the next string output. So the
테이블의 그 자리에 들어갈 것은 QQ이며 출력할 문자열도 그것이 되어야 한다는걸 알아낼 수 있다.
decompression pseudo-code goes something like:
그래서 압축해제 알고리즘은 다음과 같을 것이다...