c\#에서 이미지 그 레이스 케 일 기술 에 대한 상세 한 설명 실현
예전 에 저희 가 웹 에 있 는 사용자 등록 을 할 때 보통 인증 코드 를 만 들 었 습 니 다.모두 가 폭력 등록 을 방지 하 는 데 사용 되 는 것 을 알 고 있 습 니 다.물론 인증 코드 를 언급 하면 모두 가 C\#안에 비트 맵 류 가 그림 을 처리 하 는 데 사용 되 는 것 을 알 고 있 습 니 다.좋 습 니 다.이 편 은 가장 간단 한'그림 그 레이스 케 일'부터 시작 하 겠 습 니 다.
그림 그 레이스 케 일
우 리 는 모두 비트 맵 이 하나의 픽 셀 점 으로 구성 되 어 있다 는 것 을 알 고 있다.픽 셀 점 은 빨간색,오렌지색,분홍색 등 일 수 있다.이런 색 들 은 우리 가 모두 RGB 로 표시 한 것 을 안다.
각 색상 의 분량 은 하나의 바이트(0-255)이기 때문에 일반적인 상황 에서 그림 의 픽 셀 점 은 24 자리 입 니 다.물론 32 자리,64 자리 도 있 습 니 다.RGB 가 0-255 사이 의 다른 값 일 때 이 픽 셀 점 은'알록달록'을 나타 내 고 RGB 가 같은 값 일 때 는 소점 처럼'회색'을 나타 내 며 CSS 를 해 보 셨 다 면...한 글자 에 주 는 color 는 보통\#9999999,\#666666,\#3333333 등 깊이 가 다른 회색 이라는 것 을 잘 알 고 있 을 것 이다.
1.계산 공식
다음은 합 리 적 인 그 레이스 케 일 값 을 어떻게 설정 해 야 합 니까?물론 현재 의 RGB 를 모델 로 하고 RGB 에 합 리 적 인 가중치 를 곱 하면 ok 입 니 다.
Gary(i,j)=0.299*R(i,j)+0.587*G(i,j)+0.114*B(i,j);
2.프로 그래 밍공식 이 있 으 면 실현 하 는 것 은 문제 가 되 지 않 는 다.Bitmap 클래스 에는 GetPixel/SetPixel 이 있 습 니 다.현재 픽 셀 점 을 가 져 오고 설정 할 수 있 습 니 다.
static void Main(string[] args)
{
Bitmap bitmap = new Bitmap(Environment.CurrentDirectory + "//1.jpg");
for (int i = 0; i < bitmap.Width; i++)
{
for (int j = 0; j < bitmap.Height; j++)
{
//
var color = bitmap.GetPixel(i, j);
var gray = (int)(color.R * 0.299 + color.G * 0.587 + color.B * 0.114);
//
bitmap.SetPixel(i, j, Color.FromArgb(gray, gray, gray));
}
}
bitmap.Save(Environment.CurrentDirectory + "//2.jpg");
}
3.개선
위의 방법 은 매우 간단 합 니 다.Get/Set 은 Ok 입 니 다.물론 이것 은 우리 가 화소 점 이라는 각도 에서 문 제 를 고려 하 는 것 입 니 다.O(N2)의 시간 만 있 으 면 KO 문 제 를 해결 할 수 있 을 것 같 습 니 다.그러나 Get/Set 은 O(1)가 아 닙 니 다.성능 을 고려 하면 우 리 는 더 좋 은 방법 이 있 을 수 있 습 니까?이때 우 리 는 바이트 라 는 각도 에서 생각 할 수 있 습 니 다.그러나 여기 서 우리 가 주의해 야 할 문 제 는 그림 의 width=21px 이다.하나의 픽 셀 점 은 3 개의 바이트 를 차지 하지만 21 개의 픽 셀 점 이 반드시 63 개의 바이트 를 차지 하 는 것 은 아니다.이것 은 시스템 이 성능 을 고려 하여 각 줄 에'사용 되 지 않 는 구역'을 저장 하여 그림 각 줄 의 byte 수가 4 의 배수 임 을 확보 하기 때문이다.그러면 어떻게 한 줄 의 바이트 수 를 읽 을 수 있 습 니까?
C\#안에 Stride 속성 이 하나 있 으 면 얻 을 수 있 습 니 다.간단 하 죠?
static void Main(string[] args)
{
Bitmap bitmap = new Bitmap(Environment.CurrentDirectory + "//1.jpg");
// bitmap rect
Rectangle rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
//
var bitmapData = bitmap.LockBits(rect, ImageLockMode.ReadWrite, bitmap.PixelFormat);
//
var ptr = bitmapData.Scan0;
//stride:
int len = bitmapData.Stride * bitmap.Height;
var bytes = new byte[len];
// copy byte
Marshal.Copy(ptr, bytes, 0, len);
for (int i = 0; i < bitmap.Height; i++)
{
for (int j = 0; j < bitmap.Width * 3; j = j + 3)
{
var color = bytes[i * bitmapData.Stride + j + 2] * 0.299
+ bytes[i * bitmapData.Stride + j + 1] * 0.597
+ bytes[i * bitmapData.Stride + j] * 0.114;
bytes[i * bitmapData.Stride + j]
= bytes[i * bitmapData.Stride + j + 1]
= bytes[i * bitmapData.Stride + j + 2] = (byte)color;
}
}
//copy
Marshal.Copy(bytes, 0, ptr, len);
//
bitmap.UnlockBits(bitmapData);
bitmap.Save(Environment.CurrentDirectory + "//3.jpg");
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
C#Task를 사용하여 비동기식 작업을 수행하는 방법라인이 완성된 후에 이 라인을 다시 시작할 수 없습니다.반대로 조인(Join)만 결합할 수 있습니다 (프로세스가 현재 라인을 막습니다). 임무는 조합할 수 있는 것이다. 연장을 사용하여 그것들을 한데 연결시키는 것이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.