6

I have C language source code, for an embedded system, containing arrays of data for an 8-bit per pixel grayscale image. I'm in charge of documenting the software and I'd like to convert this source code to a JPEG (image) file.

Here is a code sample:

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;

Here are my questions: (yes, plural)

  1. What application(s) do you recommend for converting this source file to JPEG?
  2. Can GIMP or Paint import a CSV file of data?
  3. If I write this custom application, what Java libraries exist for JPEG?
  4. What libraries exist in C# for accomplishing this task?

I have the following resources at my disposal: MS Visio 2010, Gimp, Paint, Java, Eclipse, MS Visual Studio 2010 Professional, wxWidgets, wxFrameBuilder, Cygwin.
I can write the custom application in C#, Java, C or C++.

Thanks for your advice.

Thomas Matthews
  • 56,849
  • 17
  • 98
  • 154
  • 1
    Consider using PNG rather than JPEG for a small image like this. – Michael Brewer-Davis Aug 16 '11 at 17:15
  • 1
    I agree with @Michael . This fits a lossless format such as png much better than jpeg. The image seems to be small and has sharp edges which makes it fit png/gif more than jpeg. Jpeg doesn't deal well with sharp edges. – CodesInChaos Aug 16 '11 at 17:19

3 Answers3

2

The issue with using java will be to get the bytes as ints. While reading in you will need to convert to an int in order to capture values > 127 because java does not have unsigned bytes.

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);
Clint
  • 8,988
  • 1
  • 26
  • 40
1

I can answers question 4 and I can give you the code to do this in c#. It is very simple...

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);

You may also be able to optimise this code if you look around for bitmap optimization techniques (such as locking the bitmap memory)

EDIT: Alternative with bit locking (should be much faster)...

NOTE: I am not 100% sure about the PixelFormat used when creating the Bitmap object - was my best guess at the options available.

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;
musefan
  • 47,875
  • 21
  • 135
  • 185
0

You can just use the ImageIO class in 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);
Andrew
  • 13,757
  • 13
  • 66
  • 84
  • @musefan I read greyscale image and assumed it was an image byte array with metadata. – Andrew Aug 16 '11 at 16:09
  • I have assumed it does not contain metadata due to the fact the width and height were supplied separately. Also, JPeg file format starts with 0xFF 0xD8... perhaps something for the OP to clear up as this could well be dummy data for this post – musefan Aug 16 '11 at 16:28
  • @Andrew: Thanks for the answer, but how do I supply height and width? The data is just the image data, 256 shades of gray; pure and simple as a contiguous array. – Thomas Matthews Aug 16 '11 at 16:38