2014-11-04 6 views
0

비트 맵 이미지를 반복하고 값을 1 씩 증가 시키길 원하지만 현재 이미지가 메모리 스트림에서 이전보다 품질이 떨어지며 변경 사항이 부드럽 지 않습니다. 조금도.이미지 픽셀 반복 및 색상 교체

private static Bitmap CyclePalette(Bitmap original) 
    { 
     using (var bitMapStream = new MemoryStream()) 
     { 
      original.Save(bitMapStream, format: ImageFormat.Gif); 
      var newBitmap = new Bitmap(bitMapStream); 

      var newPalette = newBitmap.Palette; 

      for (var i = 0; i < newPalette.Entries.Length - 5; i++) 
      { 

       var oldColor = newPalette.Entries[i]; 
       newPalette.Entries[i] = newPalette.Entries[i + 1]; 
       newPalette.Entries[i + 1] = oldColor; 

      } 
      newBitmap.Palette = newPalette; 
      return newBitmap; 
     } 
    } 
+0

내가 원하는 것을하기 위해 Bitmap.Clone()을 어떻게 사용합니까? –

+1

또한 GIF는 [일반적으로 256 색만 지원합니다] (http://en.wikipedia.org/wiki/Graphics_Interchange_Format#Palettes). 비트 맵에 비트 맵이 더 많으면 아마 문제를 설명 할 것입니다. [MemoryBmp] (http://msdn.microsoft.com/en-us/library/system.drawing.imaging.imageformat.memorybmp%28v=90.aspx) 또는 [Png] (http : //msdn.microsoft.com/en-us/library/system.drawing.imaging.imageformat.png%28v=vs.90%29.aspx) 더 좋을 것입니다. – dbc

+0

OP에 따르면 * 이미지 픽셀을 반복 *하지만 색상 자체를 변경하지 않고 팔레트 할당을 한 곳으로 이동하여 색인 값을 증가 시켰습니다. 팔레트가 완벽한 시각적으로 가까운 순서로 배열되어 있지 않으면 이미지가 저하됩니다. 팔레트 순서가 임의이면 이미지가 시각적으로 엉뚱한 의미가됩니다. –

답변

1

처음에는 GIF 파일과 원래 솔루션에 대한 내용입니다.

정말 빠르고 쉽게 실행할 수 있지만 재미있을 때 나는 웃어야 만했습니다. 이제는 당신이 의미하는 바를 알고 있습니다. 품질이 저하되었습니다 .. !!

설명하자 : GIF 파일에는 몇 가지 옵션이 있지만 중요한 것은 디더링되었는지 여부입니다.

나는 이미 256 색만을 가지고 있다고 언급했다; 그들이 적어도 멀리서, 정상적인 GIF 파일은 트릭을 사용하여 멋지게 보입니다 : They 디더 색상의 혼합을 보여주는 블럭! 이것은 꽤 잘 작동하지만 색상 회전을 위해 팔레트를 사용하는 것을 완전히 금지합니다 ..

물론 디더링을 해제 할 수 있지만 그 결과는 매우 거칠고 픽셀 화되지 않을뿐만 아니라, 적절한 팔레트를 사용하면 회전을 수행 할 수 있지만 최상의 결과는 평범합니다. 나는 함수 palRotate에서 코드를 추가했다.

내 제안을 남겨 둡니다. GIF를 잊어 버리면 ARGB 컬러 교체가 필요합니다. 이것은 또한 계산 된 전체 범위의 K로 작업 할 수있게 해줍니다. 그러나 빠르게 실행하려면 엄격한 코드가 필요합니다.

여기에 LockBits를 사용하여 데이터를로드하고 풀 컬러 사이클링을 수행하는 완전한 테스트 베드가 있습니다. PictureBox, ButtonTimer을 양식에 추가해야합니다. 데이터의 크기는 PictureBox의 크기와 같아야합니다. 500x500 테스트 데이터 파일을 포함 시켰습니다.

using System.Drawing.Imaging; 
using System.Runtime.InteropServices; 
using System.IO; 
//.. 

// the data array 
int[,] Ks; 
// the offset for cycling 
int koffset = 0; 
// a list of colors 
List<Color> colors = new List<Color>(); 

public void paintKs() 
{ 
    if (Ks == null) return; 

    Size s1 = pb_image.ClientSize; 
    pb_image.Image = new Bitmap(s1.Width, s1.Height); 
    Bitmap bmp = new Bitmap(pb_image.Image); 

    PixelFormat fmt1 = bmp.PixelFormat; 
    byte bpp1 = 4; 

    Rectangle rect = new Rectangle(Point.Empty, s1); 
    BitmapData bmpData = bmp.LockBits(rect, ImageLockMode.ReadOnly, fmt1); 

    int size1 = bmpData.Stride * bmpData.Height; 
    byte[] data = new byte[size1]; 
    System.Runtime.InteropServices.Marshal.Copy(bmpData.Scan0, data, 0, size1); 

    for (int y = 0; y < s1.Height; y++) 
    { 
     for (int x = 0; x < s1.Width; x++) 
     { 
      int index = y * bmpData.Stride + x * bpp1; 
      Color c = colors[(Ks[x, y] + koffset) % (colors.Count)]; 
      if (Ks[x, y] == 0) c = Color.Black; 
      data[index + 0] = c.B; 
      data[index + 1] = c.G; 
      data[index + 2] = c.R; 
      data[index + 3] = 255; 
     } 
    } 

    System.Runtime.InteropServices.Marshal.Copy(data, 0, bmpData.Scan0, data.Length); 
    bmp.UnlockBits(bmpData); 

    pb_image.Image = bmp; 
} 

void saveKs(string dataFile) 
{ 
    using (BinaryWriter writer = new BinaryWriter(File.Open(dataFile, FileMode.Create))) 
    { 
     for (int y = 0; y < Ks.GetLength(0); y++) 
      for (int x = 0; x < Ks.GetLength(1); x++) 
       writer.Write((Int16)Ks[x, y]); 
    } 
} 

void loadKs(string dataFile) 
{ 
    int w = pb_image.ClientSize.Width; 
    if (Ks == null) Ks = new int[w, w]; 

    using (BinaryReader reader = new BinaryReader(File.Open(dataFile, FileMode.Open))) 
    { 
     for (int y = 0; y < Ks.GetLength(0); y++) 
      for (int x = 0; x < Ks.GetLength(1); x++) 
       Ks[x, y] = reader.ReadInt16(); 
    } 

} 

private void Test_Click(object sender, EventArgs e) 
{ 
    loadKs("fractalData021.dat"); 
    for (int i = 0; i < 256; i++) 
    { 
     // a very simple and rather awful palette! 
     for (int i = 0; i < 256; i++) 
      colors.Add(Color.FromArgb(255, i, i, 255 - i)); 
     for (int i = 0; i < 100; i++) 
      colors.Add(Color.FromArgb(255, i + 100, 255 -i, 155 - i)); 
     for (int i = 0; i < 100; i++) 
      colors.Add(Color.FromArgb(255, i + i+ 50, 255 - i - i, 155 - i/2)); 
    } 
    paintKs(); 
    timer1.Intervall = 33; // 30 fps 
    timer1.Start(); 
} 

private void timer1_Tick(object sender, EventArgs e) 
{ 
    koffset++; 
    if (koffset >= colors.Count) koffset = 0;; 
    paintKs(); 
} 

다음은 테스트 데이터가있는 파일입니다. 테스트 파일은 500x500 픽셀의 크기가 :

http://www.file-upload.net/download-9796723/fractalData021.dat.html

http://www.file-upload.net/download-9796722/fractalData021.jpg.html

http://www.file-upload.net/download-9796721/fractalData021.txt.html

업데이트 :

다음

비 디더링 GIF 파일에 plaette 회전을 수행하는 코드 .

void palRotate() 
{ 
    Bitmap bmp = (Bitmap)pb_image.Image; 
    var pal = bmp.Palette; 
    for (int i = 0; i < 256; i++) pal.Entries[(i + koffset) % 256] = colors[i]; 
    bmp.Palette = pal; 
    pb_image.Image = bmp; 
} 

준비를 위해 이러한 호출은 색상 목록에 원래 팔레트 색상을 추출 할 :

pb_image.Image = new Bitmap("d:\\fff.gif"); 
Bitmap bmp = (Bitmap)pb_image.Image; 
var pal = bmp.Palette; 
for (int i = 0; i < 256; i++) colors.Add(pal.Entries[i]); 

이 아무것도 볼 것이 아니라 완전히 엉터리 파레트 순서의 어떤 종류를해야 들어; 그러나 픽셀 화 된 이미지는 애처로운 것처럼 보일 것입니다.

koffset 변수를 발전시키는 타이머의 다른 회전 코드와 비슷한 방식으로 호출됩니다.

0

이렇게하면 색상을 부드럽게 회전시키는 팔레트가 만들어집니다. Mset 픽셀에 대해 1 * 팔레트 항목을 남기는 3 * 85 = 255가 발생합니다. 나는 당신의 플랫폼에 맞게 코드화하지 않았다. (그리고 구조체 배열로 코딩하는 것이 더 낫다.)하지만 한 번에 2 개의 프라이 머리를 사라지게한다. 이렇게하면 진흙 같은 색을 피할 수 있습니다.

#include <stdio.h> 
#include <memory.h> 

#define MAXITER 1000 // iteration depth 

unsigned char pal [256][3]; 

int Mandelplot (int x, int y) { 
    // return (palette) colour for pixel 
    int c, i=iterate (x, y);  // your iteration function 
    if (i >= MAXITER) 
     c = 255; 
    else 
     c = i % 255; 
    return c; 
} 

void rotate_palette (void) { 
    // leaves index 255 unchanged for Mset pixels 
    unsigned char r=pal[0][0], g=pal[0][1], b=pal[0][2]; 
    memcpy (&pal[0][0], &pal[1][0], 254 * 3 * sizeof(unsigned char)); 
    pal[254][0] = r; 
    pal[254][1] = g; 
    pal[254][2] = b; 
} 

int main (void) { 
    unsigned char r=0, g=0, b=255; 
    int i; 

    for (i=0; i<85; i++) { 
     pal [i][0]= r; 
     pal [i][1]= g; 
     pal [i][2]= b; 
     b -= 3; 
     g += 3; 
    } 

    for (i=85; i<170; i++) { 
     pal [i][0]= r; 
     pal [i][1]= g; 
     pal [i][2]= b; 
     g -= 3; 
     r += 3; 
    } 

    for (i=170; i<255; i++) { 
     pal [i][0]= r; 
     pal [i][1]= g; 
     pal [i][2]= b; 
     r -= 3; 
     b += 3; 
    } 

    pal [255][0] = 0; // black on the Mset 
    pal [255][1] = 0; 
    pal [255][2] = 0; 

    for (i=0; i<256; i++) 
     printf ("%02X %02X %02X, ", pal[i][0], pal[i][1], pal[i][2]); 

    return 0; 
}