DICOM 통신에 기본이 되는 PDU와 PDV에 대해 알아봅니다.

 

1. PDU - Protocol Data Unit

 

https://www.dicomstandard.org/current

 

위의 그림은 DICOM UL 중 A-ASSOCIATE-RQ PDU와 A-ASSOCIATE-AC PDU의 PDU 인코딩의 예시입니다.

 

PDU(Protocol Data Unit)는 계층 내의 피어 엔터티 간에 교환되는 메시지 형식입니다. PDU는 프로토콜 제어 정보와 사용자 데이터로 구성됩니다. PDU는 필수 고정 필드와 하나 이상의 항목 및/또는 하위 항목을 포함하는 선택적 가변 필드로 구성됩니다. 

 

정리하자면

* PDU는 네트워크 통신에서 데이터를 전송하는 데 사용되는 단위입니다.
* DICOM에서 PDU는 네트워크 상에서 DICOM 메시지를 나타내는 단위를 말합니다.
* PDU는 DICOM 메시지의 헤더 정보와 함께 전송되어야 합니다.
* DICOM 네트워크 프로토콜에서는 PDU가 통신의 기본적인 단위로 사용되며, 여러 종류의 PDU가 정의되어 있습니다.

 

 

 

2. PDV - Presentation-data-value

 

PDV는 DICOM 메시지의 일부로, 특히 DICOM 데이터를 전송하는 데 사용됩니다. DICOM 메시지는 PDU (Protocol Data Unit)의 일부로 전송되며, PDU에는 여러 PDV가 포함될 수 있습니다. 

 

PDV는 실제 DICOM 데이터를 담고 있는 부분으로 다양한 종류의 PDV가 존재하고, 각 PDV 유형은 특정한 역할을 수행합니다.

 

정리하자면

* PDV는 PDU 내에서 실제 데이터를 포함하는 부분을 나타냅니다.
* PDU는 여러 PDV를 포함할 수 있습니다.
* PDV는 DICOM 메시지의 일부로, 실제 DICOM 데이터를 포함하고 있습니다.
* PDV는 PDU의 일부로 전송되어, 네트워크 상에서 DICOM 데이터의 전송을 담당합니다.

 

 

 

 

 

 

 

 

반응형

 

DICOM 태그를 다루던 중 태그 타입에 1C라고 적혀있는 걸 보고 문득 TagType의 정확한 정의가 궁금해져서 알아본 후 작성한 글입니다.

 

 

 

Data Element Type

 

 

DICOM에서 태그 타입 ‘1C’는 조건적으로 필수인 타입 1이지만 비어있거나 존재하지 않을 수 있는 타입 2가 포함된 데이터 요소입니다.

 

다른 말로 태그 타입 ‘1C’는 데이터 요소가 필수로 DICOM 객체에 나타나야 하지만 특정 환경이나 다른 연관된 태그의 값에 따라 값을 가지고 있지 않을 수 있는 태그 타입을 가리킵니다. 만약 연관된 데이터 요소가 특정 값을 갖는다면 ‘1C’ 데이터 요소는 반드시 값을 가져야 하지만 연관된 데이터 요소가 특정한 값을 갖지 않는 다면 ‘1C’ 데이터 요소는 값을 빈값으로 갖거나 태그가 없을 수 있습니다.

 

DICOM 표준에서는 세 개의 데이터 요소 타입을 정의하고 있습니다:

  • 타입 1: 값을 반드시 가져야 하는 필수 요소.
  • 타입 2: 다른 연관된 요소에 따라 값을 가질 수도 가지지 않을 수도 있는 조건적으로 필요한 요소
  • 타입 3: 값을 가질 수도 가지지 않을 수도 있는 선택적 요소.

 

'1C' 태그 타입은 유형 1과 유형 2의 조합으로, 특정 조건에서는 요소가 값을 가져야 하지만 다른 조건에서는 비어 있거나 존재하지 않을 수 있는 태그 타입입니다. DICOM 파일을 읽거나 쓸 때 '1C' 데이터 요소를 올바르게 처리하여 해당 요소에 대해 정의된 조건에 따라 데이터가 적절하게 해석되고 처리되도록 해야 합니다.

 

 

참조

https://dicom.nema.org/medical/dicom/current/output/chtml/part05/sect_7.4.html

https://dicom.nema.org/medical/dicom/current/output/chtml/part05/sect_7.4.2.html

https://dicom.nema.org/medical/dicom/current/output/chtml/part05/sect_7.4.3.html

https://dicom.nema.org/medical/dicom/current/output/chtml/part05/sect_7.4.5.html

 

 

 

 

반응형

 

 

 

DICOM 태그를 다루면서 종종 간과하는 사실 중 하나가 태그 값의 길이입니다.

 

DICOM 태그 값의 길이는 항상 짝수입니다. 

 

홀수 길이의 DICOM 태그 값에 대한 제한은 짝수 길이 값을 기반으로 하는 DICOM 데이터의 형식 및 구조 때문입니다. 

 

1. 길이가 짝수인 태그 값의 표준화를 통해 DICOM 데이터를 여러 시스템 및 소프트웨어 애플리케이션에서 효율적이고 일관되게 구문 분석하고 처리할 수 있습니다.

2. 모호하거나 호환되지 않는 데이터 형식으로 인해 발생할 수 있는 오류 및 상호 운용성 문제를 방지하는 데 도움이 됩니다.

3. 길이가 짝수인 태그 값을 사용하면 DICOM 데이터를 저장하고 전송하는 프로세스가 간소화됩니다.

4. 데이터를 고정 길이 필드로 보다 효율적으로 압축하고 컴퓨터에서 더 빠르게 처리할 수 있습니다.

 

따라서 이러한 제한은 DICOM내에서 데이터의 효율적이고 일관된 처리를 가능하게 하고 오류 및 상호 운용성 문제를 방지하는 데 도움이 됩니다.

 

 

 

 

 

반응형

 

 

 

DICOM Modality Worklist (MWL)은 의료 영상에서 환자 정보 및 검사 요청을 병원의 방사선 정보 시스템(RIS)이나 병원 정보 시스템(HIS)에서 가져와 CT, MRI, X-ray 및 초음파 등의 영상 장비에 표시하는 표준 프로토콜입니다.

 

HIS(병원 정보 시스템), RIS(방사선 정보 시스템) 및 EMR/EHR 솔루션은 환자 인구 통계 및 검사 일정 정보의 마스터 인덱스를 제공합니다. Modality Worklist는 환자 주문, 검사 요청 및 환자 이름, ID, 검사 유형 및 일정 정보와 같은 관련 정보 목록을 제공합니다.

 

Modality worklist는 필요한 환자 데이터와 검사 세부 정보를 검색하기 위해 모달리티 워크리스트에 액세스 할 수 있으며, 이를 통해 수동 입력의 필요성을 제거합니다. MWL이 없으면 양식은 환자 건강 관리 정보(PHI)를 가져와 양식에 수동으로 입력해야 합니다. 이 프로세스는 추가 수작업과 인적 오류의 위험을 초래할 수 있습니다.

 

DICOM Modality Worklist를 사용하면 방사선과 기술자는 올바른 환자에게 올바른 검사를 수행하고 참조 의사나 환자 치료에 참여하는 기타 의료 전문가로부터 특정 지시사항이나 특별 요청 사항을 볼 수 있습니다. 모달리티 워크리스트는 작업 흐름 및 효율성을 향상시키고 검사 지연을 줄이며 환자 안전을 향상시킬 수도 있습니다.

 

 

 

References:

DICOM Modality Worklist

DICOM Modality Worklist & MPPS

 

 

 

반응형

 

입력받은 string 타입의 TransferSyntaxUid를 TrasnferSyntax 타입으로 변환하고 파일의 TransferSyntax와 비교하는 방법에 대해 알아봅니다.

 

 

 

1. Fo-DICOM NuGet패키지 설치

 

Nuget 패키지 관리자를 통해 사용할 프로젝트에 패키지를 설치합니다. 

 

 

프레임워크는 .Net 6을 사용했습니다.

 

 

 

2. 소스코드

 

소스코드는 아래와 같습니다. 주석을 같이 작성하였으니 설명은 주석을 참고해 주시기 바랍니다.

 

private bool CompareDicomTransferSyntaxSample(string dcmFilePath)
{
    DicomTransferSyntax dcmTransferSyntax, inputTransferSyntax;
    //  비교할 Explicit VR Little Endian TransferSyntaxUid를 string 타입으로 지정합니다. 
    string dcmTransferSyntaxUid = "1.2.840.10008.1.2.1";
    // string 타입의 TransferSyntaxUid를 사용해 DicomUID 타입으로 변환합니다.
    DicomUID dicomUID = DicomUID.Parse(dcmTransferSyntaxUid);
    // 변환한 DicomUID 타입의 TransferSyntaxUid를 DicomTransferSyntax 타입으로 변환합니다.
    inputTransferSyntax = DicomTransferSyntax.Query(dicomUID);
    try
    {
        DicomFile dicomFile = DicomFile.Open(dcmFilePath, FileReadOption.SkipLargeTags);
        // DicomFile내의 FileMetaInfo에서 파일의 TransferSyntax를 가져옵니다.
        dcmTransferSyntax = dicomFile.FileMetaInfo.TransferSyntax;
        // 두 값을 비교해 bool 타입을 리턴합니다.
        return inputTransferSyntax == dcmTransferSyntax;
    }
    catch (Exception ex)
    {
        // DICOM 파일 형식 오류.
        return false;
    }
}

 

 

 

 

 

 

반응형

'Trunk > DICOM' 카테고리의 다른 글

[DICOM] DICOM Tag 값의 길이에 대해  (0) 2023.03.08
[DICOM] MWL: Modality Worklist  (0) 2023.02.18
[C#|FO-DICOM] DICOM 파일을 로드 해 태그 추출하기.  (0) 2022.05.03
[DCMTK] MEPG2와 프레임  (0) 2022.05.03
[DICOM] VR PN: PersonName  (0) 2021.10.19

 

FO-DICOM을 사용해 C#에서 DICOM 파일을 로드하고 태그를 추출하는 방법에 대해 알아봅니다.

 

 

 

1. Fo-DICOM NuGet패키지 설치

 

Nuget 패키지 관리자를 통해 사용할 프로젝트에 패키지를 설치합니다. 

 

 

프레임워크는 .Net 6을 사용했습니다.

 

 

 

2. 소스코드

 

소스코드는 아래와 같습니다. 주석을 같이 작성하였으니 설명은 주석을 참고해 주시기 바랍니다.

 

private void GetDicomTagSample(string dcmFilePath)
{
    string modalityCode;
    try
    {
    	// Open DICOM File.
        DicomFile dicomFile = DicomFile.Open(dcmFilePath, FileReadOption.SkipLargeTags);
        // Load DICOM tags to DicomDataSet.
        DicomDataset ds = dicomFile.Dataset;
        try
        {
        	//Get Modality tag from the DicomDataSet.
            modalityCode = ds.GetString(DicomTag.Modality);
        }
        catch (DicomDataException ex)
        {
            // The dataset does not contain tag.
        }
    }
    catch(Exception ex)
    {
        // Invalid DICOM file.
    }
}

 

 

 

 

 

 

 

 

반응형

 

 

 

DICOM 영상의 프레임 정보를 추출하다 에러가 발생해 원인을 확인하다 찾아본 내용을 정리해 둡니다. 영상처리에선 어찌 보면 기본적인 내용일 수도 있지만 혹시 제가 겪은 문제와 유사한 경험을 하시는 분들에게 도움이 되었으면 합니다.

 

 

 

1.  문제: Offset 정보 추출 실패

 

시작은 DICOM 영상의 offset 정보를 추출하는 것으로부터 시작되었습니다. 영상을 정상적으로 로드해왔으나 DcmPixelSequence에서 getItem을 해오는 과정에서 이상한 현상이 발생하였습니다.

 

 

 

2. 현상

 

해당 영상을 Weasis로 오픈해 TransferSyntax를 확인한 결과 MPEG2 영상으로 확인되었습니다.

DICOM 영상의 TransferSyntax

DICOM 파일에서 영상만 추출해 ffmpeg로 모든 프레임을 추출한 결과 총 360장의 프레임을 추출할 수 있었습니다. 따라서 내부 로직에서 프레임의 개수는 360이 되어야 한다고 추측하고 있었습니다.

영상에서 추출해낸 프레임

하지만 DCMTK 디버그 결과 첫 번째 프레임에서 모든 영상의 크기만큼의 바이트를 불러오고 두 번째 프레임에선 null을 리턴하고 있었습니다.

추출한 MPEG2 영상의 파일 크기
첫번째 오프셋 추출 정보.

위의 사진에서 확인하듯이 첫 번째 오프셋에서 모든 길이를 다 가져오고 있었으며 아래의 사진에서 볼 수 있듯이 두 번째 오프셋에서는 NULL값을 확인할 수 있었습니다.

두번 째 오프셋 추출 정보.

 

 

 

3. 원인: MEPG2

 

확인 후 결론부터 말씀드리자면 해당 동작은 정상이었으며 DCMTK와 MPEG2의 특징을 잘 이해하지 못한 제가 오류로 인식하고 있던 상황이었습니다.

 

https://forum.dcmtk.org/viewtopic.php?p=9897#p9897 

 

how to extract frames from DICOM "Mpeg2 Main Profile @ Main Level" file - DICOM @ OFFIS

All other questions regarding DCMTK Moderator: Moderator Team Ro2a Posts: 9 Joined: Fri, 2010-09-17, 17:14 #1 Post by Ro2a » Tue, 2010-09-21, 00:24 Hello I want to develope a programe using VS c++ and dcmtk that can load a dicom file which has the followi

forum.dcmtk.org

위 링크의 답변을 인용해 보자면 다음과 같습니다.

 

For compressed pixel data you have to use the DcmPixelSequence class due to the internal structure of the compressed PixelData element. This gives you acccess to the included offset table (empty for MPEG2) and all frames. However, for MPEG2 there is only a single "frame" containing all MPEG2 data as a blob. You won't be able to access individual frames with DCMTK because DCMTK does not know how to decompress MPEG2 data and hence is not able to find out where a specific frame begins.

So you have to get the complete MPEG2 data, and then decompress it using another library. I will post an example how to do that soon in the wiki and reference here in the forum topic.

 

DCMTK에서 MPEG2의 오프셋 정보를 얻기 위해선 MPEG2 영상의 BLOB 데이터를 로드해 온 뒤 FFMPEG와 같은 외부 라이브러리를 사용해 압축을 풀고 난 뒤에야 오프셋 정보 추출을 시도할 수 있었습니다.

 

 

 

기반 지식이 얼마나 중요한지 다시 깨달아 가는 문제였습니다. 오늘도 하나 더 배우고 갑니다.

 

 

 

 

 

반응형

 

 

이 글은 NEMA의 DICOM 표준 중 6.2 Value Representation (VR)에서 PN을 정리한 글입니다. 원문은 아래의 링크를 통해 확인해 주시기 바랍니다.

http://dicom.nema.org/medical/dicom/current/output/chtml/part05/sect_6.2.html#sect_6.2

 

6.2 Value Representation (VR)

A character string that may contain one or more paragraphs. It may contain the Graphic Character set and the Control Characters, CR, LF, FF, and ESC. It may be padded with trailing spaces, which may be ignored, but leading spaces are considered to be signi

dicom.nema.org

 

 

6.2. Value Representation (VR) - PN: PersonName

5개의 구성으로 이루어진 규칙을 사용해 인코딩 된 문자열입니다.

문자코드 5CH(ISO-IR 6에서의 백 슬래시"\")는 멀티 밸류 데이터에서 구분 기호로 사용되기 때문에 존재하면 안 됩니다.

해당 문자열의 뒷부분은 공백으로 채워질 수 있습니다.

사람에게 사용되는 경우 순서에 따라 5개로 구성됩니다: 성, 이름, 중간 이름, 접두사, 접미사.

 

노트: HL7은 구성요소 내에서 선행 공백을 금지합니다. DICOM은 선행 및 후행 공백을 허용하며 중요하지 않은 것으로 간주합니다.

 

5개의 구성요소 중 일부는 공백일 수 있습니다.

해당 구성 요소 간의 구분 기호는 캐럿("^") 문자입니다.

구분 기호는 4개 이하입니다. 즉 모든 구성 요소가 존재하는 경우 마지막의 구분 기호는 필요하지 않습니다.

내부에 NULL값이 있는 경우 구분 기호가 필요하지만 마지막이 NULL값인 경우 구분 기호는 생략할 수 있습니다.

각각의 구성요소마다 여러 개의 항목이 허용되며 사람이 선호하는 형식으로 문자열을 통해 인코딩 됩니다.

 

수의학적으로 사용되는 경우 순서에 따라 다섯 개의 구성 요소 중 처음 두 개는 책임 담당자의 성 또는 조직 이름과 환자 이름이 됩니다. 나머지 구성요소는 사용되지 않으면 존재하지 않아야 합니다.

 

위와 같은 다섯 가지 구성 요소의 그룹을 개인 이름 구성 요소 그룹(Person Name component group)이라고 합니다.

 

표의 문자와 음성 기호로 이름을 쓸 목적으로 최대 3개의 구성요소 그룹(부록 H, I, J 참조)을 사용할 수 있습니다.

구성요소 그룹의 구분 기호는 등호("=", 3DH) 문자입니다.

구성 요소 그룹의 구분 기호는 두 개 이하여야 합니다. 즉 모든 구성 요소 그룹이 있는 경우 마지막 구성 요소 그룹 뒤의 구분 기호는 생략됩니다. 

순서에 따른 구성 요소 그룹은 알파벳, 표의문자, 음성 기호 순서입니다.

 

첫 번째 구성 요소 그룹을 포함하여 모든 구성 요소 그룹이 없을 수도 있습니다. 

이 경우 사람의 이름은 하나 이상의 등호("=") 구분 기호로 시작할 수 있습니다.

내부에 NULL 구성 요소 그룹이 있는 경우 구분 기호가 필요합니다. 

가장 뒤의 구성 요소 그룹이 NULL인 경우 구분 기호는 생략될 수 있습니다.

 

정확한 의미는 각 구성 요소 그룹에 정의되어 있습니다. 섹션 6.2.1.2를 참고하시기 바랍니다.

 

예제 및 참고사항은 섹션 6.2.1.1을 참고하시기 바랍니다.

 

 

 

6.2.1.1 Examples of PN VR and Notes

 

Rev. John Robert Quincy Adams, B.A. M.Div. ⇒ Adams^John Robert Quincy^^Rev.^B.A. M.Div.

성 1개, 이름 3개, 중간 이름 0개, 접두사 1개, 접미사 2개

 

Susan Morrison-Jones, Ph.D., Chief Executive Officer ⇒ Morrison-Jones^Susan^^^Ph.D., Chief Executive Officer

성 2개, 이름 1개, 중간 이름 0개, 접두사 0개, 접미사 2개

 

John Doe ⇒ Doe^John

성 1개, 이름 1개, 중간 이름, 접두사, 접미사 0개(모든 후행 구성요소가 NULL이므로 구분 기호 생략)

 

Smith^Fluffy

책임자의 성이 Smith, 이름이 Fluffy인 고양이

 

ABC Farms^Running on Water

ABC Farms 소속의 이름이 Running on Water인 말

 

 

 

 

 

반응형

'Trunk > DICOM' 카테고리의 다른 글

[C#|FO-DICOM] DICOM 파일을 로드 해 태그 추출하기.  (0) 2022.05.03
[DCMTK] MEPG2와 프레임  (0) 2022.05.03
[DICOM] Modality(0008, 0060) tag list.  (0) 2020.12.02
[DICOM] DIMSE란?  (1) 2020.11.25
[DICOM] DICOM이란?  (0) 2020.11.25

 

DICOM Tag 중 하나인 Modality(0008, 0060)에 저장되는 값에 대해 알아봅니다.

 

 

 

Modality(0008, 0060)

 

  • AU - Audio ECG
  • BI - Biomagnetic Imaging
  • CD - Color flow Doppler
  • CR - Computed Radiography
  • CT - Computed Tomography
  • DD - Duplex Doppler
  • DG - Diaphanography
  • DOC - Document
  • DX - Digital Radiography
  • EP - Cardiac Electrophysiology Waveform
  • EPS - Cardiac Electrophysiology
  • ES - Endoscopy
  • GM - General Microscopy
  • HC - Hard Copy
  • HD - Hemodynamic Waveform
  • IO - Intra-oral Radiography
  • IVUS - Intravascular Ultrasound
  • LS - Laser Surface Sacn
  • MG - Mammography
  • MR - Magnetic Resonance
  • NM - Nuclear Medicine
  • OP - Ophthalmic Photography
  • OT - Other
  • PR - Presentation State
  • PT - Positron Emission Tomography(PET)
  • PX - Panoramic X-Ray
  • RF - Radio Fluoroscopy
  • RG - Radiographic Image(Conventional film/screen)
  • RT - Radiation Therapy Image
  • RTDOSE - Radiotherapy Dose
  • RTIMAGE - Radiotherapy Image
  • RTPLAN - Radiotherapy Plan
  • RTRECORD - RT Threatment Record
  • RTSTRUCT - Radiotherapy Structure Set
  • SC - Secondaty Capture Image
  • SM - Slide Microscopy
  • SMR - Stereomitric Relationship
  • ST - Single-photon Emission Computed Tomography(SPECT)
  • TG - Thermography
  • US - Ultrasound
  • XA - X-Ray Angiography
  • XC - External-camara Photography
  • XRF - XA/RF

 

 

 

 

 

 

반응형

'Trunk > DICOM' 카테고리의 다른 글

[C#|FO-DICOM] DICOM 파일을 로드 해 태그 추출하기.  (0) 2022.05.03
[DCMTK] MEPG2와 프레임  (0) 2022.05.03
[DICOM] VR PN: PersonName  (0) 2021.10.19
[DICOM] DIMSE란?  (1) 2020.11.25
[DICOM] DICOM이란?  (0) 2020.11.25

DIMSE가 무엇인지에 대해 알아봅니다.

 

 

 

1. DIMSE란?

 

https://www.dicomstandard.org/

 

DICOM 표준을 잘 보다 보면 여러 가지 표준을 정의해 둔 것을 확인할 수 있습니다. 의료 영상에 대한 표준 규격부터 네트워크 상의 데이터 호환을 위한 정보 모델뿐 아니라 네트워크 상에서의 통신 프로토콜까지 정의가 되어 있습니다. 네트워크 상에서 DICOM을 송수신하기 위해서는 인터넷 환경에서의 표준을 준수해야 합니다. 이는 DICOM IOD(Informtion Object Definition)에 따라 구현됩니다.

 

CT Image IOD (https://bit.ly/3nY9Vpl)

 

위의 표와 같이 이미지마다 정의된 표준에 에 맞춰 필요한 정보를 사용해 IOD를 구성합니다. 그리고 DICOM 통신 시 데이터 전송을 위한 메시지 교환 규격에 따라 데이터를 전송합니다. 이를 DIMSE(DICOM Message Service Element)라고 부릅니다. 

 

 

 

2. DIMSE의 구분

 

DIMSE는 Composite service와 Normalized service에 따라 DIMSE-C와 DIMSE-N으로 구분됩니다. DIMSE-C 서비스는 DICOM 애플리케이션 엔티티가 Composite SOP 인스턴스에서 다른 DICOM 애플리케이션 엔티티의 작업을 명시 적으로 요청할 수 있도록 하는 서비스입니다. DIMSE-C는 운영 서비스만을 제공하고 DIMSE-N 서비스는 Normalized SOP 인스턴스에 적용할 수 있는 알림 및 운영 서비스를 모두 제공합니다.

 

DIMSE-C

  • C-STORE: 이미지를 저장(stroage)하는 동작.
  • C-FIND: 이미지를 찾는(query) 동작.
  • C-GET: 이미지를 가져오는(retrieve) 동작.
  • C-MOVE: 이미지를 전송(transfer)하는 동작.

 

DIMSE-N

  • N-CREATE: SOP 클래스의 인스턴스를 생성(create)하는 동작.
  • N-DELETE: SOP 클래스의 인스턴스를 삭제(delete)하는 동작.
  • N-SET: 정보 수정(update)을 요청하는 동작
  • N-GET: 정보 검색(retrieve)을 요청하는 동작.
  • N-ACTION: 작업 수행(domain-specific-operation)을 요청하는 동작.
  • N-EVENT_NOTIFY: 인스턴스에 대한 이벤트를 보고(notification)하는 알림.

 

 

 

 

 

반응형

'Trunk > DICOM' 카테고리의 다른 글

[C#|FO-DICOM] DICOM 파일을 로드 해 태그 추출하기.  (0) 2022.05.03
[DCMTK] MEPG2와 프레임  (0) 2022.05.03
[DICOM] VR PN: PersonName  (0) 2021.10.19
[DICOM] Modality(0008, 0060) tag list.  (0) 2020.12.02
[DICOM] DICOM이란?  (0) 2020.11.25

+ Recent posts