작성일: [[Date(2014-08-08T05:31:05)]] [[TableOfContents]] == 개요 == 어떤 게시판에서 학부생이 이미지 히스토그램을 만드는 질문 글을 올린 걸 봤는데 어렵지 않을 것 같아서 만들어봤다. 우선 생각해본 대로 만들어봤다. 1. 이미지를 비트맵으로 변환한다. 2. 비트맵 데이터를 가져온다. 3. 비트를 읽어 RGB 값을 카운트 한다. 4. 그래프를 찍어 그린다. 생각했던 대로 결과가 나와서 금방 만들었다. 처음 RGB 값을 화면에 그릴 때 카운트한 값의 최대를 그래프 높이로 두고 출력했다. 그 결과 히스토그램이 출력되기는 했는데 상용 소프트에서 보여주는 히스토그램과 같지 않았다 ^^Screenshot 1^^ . 상용 소프트의 히스토그램은 Raw한 값이 아닌 것 같았다 ^^Screenshot 2^^ . 모든 그래프가 보기 좋게 출력되는 비율 조정이 필요해 보였다. 생각해 봤는데 출력되는 최소 면적 기준으로 조정하면 되겠다 싶었다. 출력되는 그래프의 최소 면적을 전체 면적의 25%로 스레숄드를 주고 비율을 조절하니 보기 좋아졌다. 즉, 3. RGB 값을 카운트 한다. 3-1. 스케일을 조정한다. <-- 추가 4. 그래프를 찍어 그린다. 과정이 되었다. == Screenshots == attachment:140808_01.png 실제 히스토그램 attachment:140808_04.png 포토샵 히스토그램 attachment:140808_02.png 조정된 비율 attachment:140808_03.png ##attachment:140808_05.png == Code == {{{#!folding PrintHistogram {{{#!gcode void CRGBHistogramDlg::PrintHistogram() { CBitmap bitmap; if (m_hBitMap) { // Set Data bitmap.Attach(m_hBitMap); BITMAP bm_info; bitmap.GetBitmap(&bm_info); int bm_bps = bm_info.bmBitsPixel / 8; int bm_size = bm_info.bmWidth * bm_info.bmHeight * bm_bps; BYTE *p_bit_pattern = new BYTE[bm_size]; bitmap.GetBitmapBits(bm_size, p_bit_pattern); for (int pos = 0; pos < bm_size; pos += bm_bps) { ++m_Red[p_bit_pattern[2 + pos]]; ++m_Green[p_bit_pattern[1 + pos]]; ++m_Blue[p_bit_pattern[pos]]; } free(p_bit_pattern); } // Red DrawGraph(20, 10, m_Red, RGB(255, 0, 0)); // Green DrawGraph(20, 130, m_Green, RGB(0, 255, 0)); // Blue DrawGraph(20, 250, m_Blue, RGB(0, 0, 255)); } }}} }}} {{{#!folding DrawGraph {{{#!gcode void CRGBHistogramDlg::DrawGraph(int x, int y, unsigned int data[], const COLORREF rgb) { CClientDC dc(this); unsigned int width = 257; unsigned int height = 110; unsigned int data_print[256] = {0,}; // Draw Background CPen pen; pen.CreatePen(PS_SOLID, 1, RGB(150,150,150)); CPen *oldPen = dc.SelectObject(&pen); dc.Rectangle(x, y, x + width, y + height); dc.SelectObject(oldPen); // Normalize unsigned int max_n = 0; for (int i = 0; i < 256; ++i) if (data[i] > max_n) max_n = data[i]; double ratio = max_n ? (1.0 * (height - 1) / max_n) : 0.0; // Adjust Scale double adjust = 1.0; double min_threshold = 0.24; // 24% unsigned int min_threshold_cnt = (unsigned int)(height * width * min_threshold); unsigned int cnt = 0; while (1) { cnt = 0; for (int i = 0; i < 256; ++i) cnt += (unsigned int)((data[i] * adjust) * ratio); if (cnt == 0 || cnt > min_threshold_cnt) break; adjust += 0.1; } if (((CButton*)GetDlgItem(IDC_RADIO1))->GetCheck() == TRUE) adjust = 1.0; // Set data for (int i = 0; i < 256; ++i) data_print[i] = (unsigned int)((data[i] * adjust) * ratio); // Draw Graph CPen penData; penData.CreatePen(PS_SOLID, 1, rgb); oldPen = dc.SelectObject(&penData); for (int i = 0; i < 256; ++i) { if (data_print[i] == 0) continue; dc.MoveTo(x + i, y + height - 2); dc.LineTo(x + i, y + height - (data_print[i] > height ? height : data_print[i]) - 1); } dc.SelectObject(oldPen); } }}} }}} == Binary == attachment:rgb-histogram.zip ##attachment:RGB-Histogram-src.zip ---- CategoryApplication