2011-08-16 14 views
6

Posiadam kod źródłowy języka C, dla systemu wbudowanego, zawierający tablice danych dla 8-bitowego na pikselowy obraz w skali szarości. Jestem odpowiedzialny za dokumentowanie oprogramowania i chciałbym przekonwertować ten kod źródłowy na plik JPEG (obraz).Konwertuj binarny plik w skali szarości na JPEG

Oto przykładowy kod:

const unsigned char grayscale_image[] = { 
0, 0, 0, 0, 0, 0, 0, 74, 106, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 
159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 146, 93, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
//... 
}; 
const unsigned int height = 41; 
const unsigned int width = 20; 

Oto moje pytania: (tak, liczba mnoga)

  1. Co aplikacji (s) polecacie do konwersji tego pliku źródłowego do JPEG?
  2. Czy GIMP lub Paint może zaimportować plik CSV z danymi?
  3. Jeśli napiszę tę niestandardową aplikację, jakie biblioteki Java istnieją dla JPEG?
  4. Jakie biblioteki istnieją w języku C# do wykonania tego zadania?

Mam do dyspozycji następujące zasoby: MS Visio 2010, Gimp, Paint, Java, Eclipse, MS Visual Studio 2010 Professional, wxWidgets, wxFrameBuilder, Cygwin.
Potrafię napisać niestandardową aplikację w języku C#, Java, C lub C++.

Dzięki za porady.

+1

Należy rozważyć użycie PNG zamiast JPEG dla małego obrazu takiego jak ten. –

+1

Zgadzam się z @Michael. To pasuje do formatu bezstratnego, takiego jak png o wiele lepiej niż jpeg. Obraz wydaje się mały i ma ostre krawędzie, co sprawia, że ​​pasuje on do png/gif bardziej niż jpeg. Jpeg nie radzi sobie z ostrymi krawędziami. – CodesInChaos

Odpowiedz

1

Problem z używaniem java polega na uzyskaniu bajtów jako ints. Podczas czytania musisz przekonwertować wartość na int, aby przechwycić wartości> 127, ponieważ java nie ma niepodpisanych bajtów.

int height=41; 
int width=20; 
int[] data = {...}; 

BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY); 
for (int x = 0; x < width; x++) { 
    for (int y = 0; y < height; y++) { 
    // fix this based on your rastering order 
    final int c = data[ y * width + x ]; 
    // all of the components set to the same will be gray 
    bi.setRGB(x,y,new Color(c,c,c).getRGB()); 
    } 
} 
File out = new File("image.jpg"); 
ImageIO.write(bi, "jpg", out); 
0

Możesz po prostu użyć klasy ImageIO w java.

BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GREY); 

Graphics2D g2 = bi.createGraphics(); 

//loop through and draw the pixels here 

File out = new File("Myimage.jpg"); 
ImageIO.write(bi, "jpg", out); 
+0

Czy to działa? skąd będzie wiedział wysokość i szerokość? – musefan

+0

@musefan Czytam obraz w skali szarości i zakładam, że był to tablica bajtów obrazu z metadanymi. – Andrew

+0

Założono, że nie zawiera metadanych ze względu na fakt, że szerokość i wysokość zostały dostarczone osobno. Również format pliku JPeg zaczyna się od 0xFF 0xD8 ... może coś dla OP do wyjaśnienia, ponieważ może to być również dane fikcyjne dla tego postu – musefan

1

Potrafię odpowiedzieć na pytanie 4 i mogę podać kod do zrobienia tego w języku C#. Jest to bardzo proste ...

int width = 20, height = 41; 
byte[] grayscale_image = {0, 0, 0, ...}; 
System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(width, height); 
int x = 0; 
int y = 0; 
foreach (int i in grayscale_image) 
{ 
    bitmap.SetPixel(x, y, System.Drawing.Color.FromArgb(i, i, i)); 
    x++; 
    if (x >= 41) 
    { 
     x = 0; 
     y++; 
    } 
} 
bitmap.Save("output.jpg", System.Drawing.Imaging.ImageFormat.Jpeg); 

może także być w stanie zoptymalizować ten kod, jeśli rozejrzeć się za technik optymalizacji bitmap (takie jak blokowanie pamięci bitmapy)

EDIT: Alternatywny z bitem blokowanie (powinno być znacznie szybsze) ...

UWAGA: Nie jestem w 100% pewny co do PixelFormat użytego przy tworzeniu obiektu Bitmap - było moim zdaniem najlepsze z dostępnych opcji.

int width = 20, height = 41; 
byte[] grayscale_image = {0, 0, 0, ...}; 
System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(width, height, PixelFormat.Format8bppIndexed); 

System.Drawing.Imaging.BitmapData bmpData = bitmap.LockBits(
        new Rectangle(0, 0, bitmap.Width, bitmap.Height), 
        ImageLockMode.WriteOnly, bitmap.PixelFormat); 

System.Runtime.InteropServices.Marshal.Copy(bytes, 0, bmpData.Scan0, bytes.Length); 

bitmap.UnlockBits(bmpData); 

return bitmap; 
+0

Dzięki za przykład. Nie ma żadnych kryteriów wydajności, ponieważ aplikacja będzie uruchamiana na komputerze. –

+0

Czy to może być aplikacja "konsolowa", czy też wymaga GUI? –

+1

@Thomas może to być aplikacja konsolowa, ale musisz dodać odniesienie do pliku 'System.Drawing.dll'. – CodesInChaos

Powiązane problemy