Solved

creating a Bitmap or DIB from an Pixel Array

Posted on 1997-11-19
7
444 Views
Last Modified: 2013-12-26
I've got an array of Bytes with i.e. 256x256 bytes that I'm receiving via TCP during program run, each byte representing one pixel with 256 grayscales. Now I want to put this array into a TBitmap or TDib instance, in order to be able to include it into a Window (TPictureWindow).
What must I do in order to get the pixel data into a defined structure of type TBitmap or TDib?
0
Comment
Question by:frane
7 Comments
 
LVL 3

Expert Comment

by:JPM
ID: 1299471
Have a look at SetDIBitsToDevice in the OWL API help
( put in a Paint Method )
0
 
LVL 3

Expert Comment

by:LucHoltkamp
ID: 1299472
Yes that should work nicely, however realcolor bitmaps (24 bits, no palette) crashes TDib. We couldn't get it to work and had to use DrawDib (MultiMedia API reference). This is intended for video, but is much more powerful than TDib when it comes to displaying bitmaps.
.luc.
0
 
LVL 3

Expert Comment

by:JPM
ID: 1299473
I have read my doc about image files :
"....24 bits...no color table....
 need a special hardware (sic!!!)
 time for displaying very high...."

I could recommend reading that book "
      Bitmapped Graphics programming in C++
       Mary Luse
           Addison Wesley

I got it a few years ago.
( ..I could have a look myself...)
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
LVL 3

Expert Comment

by:JPM
ID: 1299474
The  following code has been extracted from the book which title I gave.

pages 221/222 there are comments about 24 bits special code


//---------------------------
(C) Copyright Marv Luse
//--------------------------------------------------------//
//                                                        //
//   File:    IMGVIEWR.HPP                                //
//                                                        //
//   Desc:    Image viewer class                          //
//                                                        //
//--------------------------------------------------------//
#ifndef _IMGVIEWR_HPP_
#define _IMGVIEWR_HPP_

#include "color.hpp"               //    code  
#include "colormap.hpp"            //     not
#include "intenmap.hpp"            //     included
#include "dither.hpp"              //       in this "Comment"
#include "display.hpp"
#include "imgstore.hpp"

#ifndef _IMAGE_OPTIONS_
#define _IMAGE_OPTIONS_

//..................option values

#define  renderNONE    0x0000   // none specified
#define  renderMAP     0x0001   // palette mapping
#define  renderDITHER  0x0002   // dithering
#define  renderGRAY    0x0004   // force gray scale

#define  intensNONE    0x0000   // as-is
#define  intensICNT    0x0001   // increased contrast
#define  intensDCNT    0x0002   // decreased contrast
#define  intensIBRI    0x0004   // increased brightness
#define  intensDBRI    0x0008   // decreased brightness

#endif

//..................an image coordinate structure
struct ImCoord
{
   int xo;   // screen origin
   int yo;
   int x1;   // image upper left
   int y1;
   int x2;   // image lower right
   int y2;
};
//..................the image viewer class
class ImageViewer
{
   protected :
      // various stuff
      VgaDisplay    *disp;
      ImgStore      *image;
      Dither        *dit;
      // image and display palettes
      rgb           *imgpal;
      int            imgcnt;
      rgb           *devpal;
      int            devcnt;
      int           *clrmap;
      // display stuff
      int            scanwid;
      int            scanhgt;
      unsigned char *scanbuf;
      // options and flags
      int            rendopt;
      int            intnopt;
      int            status;
      int            panning;

   private:
      void mv_horz( ImCoord& ic, int dx );
      void mv_vert( ImCoord& ic, int dy );
      void go_home( ImCoord& ic );
      void go_end( ImCoord& ic );
      void alter_palette( rgb *pal, int npal );
      void erase( void );
      void draw( ImCoord& ic );

   public :
      ImageViewer( VgaDisplay *vga, ImgStore *map,
                   rgb *clrs, int nclrs,
                   int ropt, int iopt );
     ~ImageViewer( );
      int view( void );
};

#endif
//--------------------------------------------------------//
//                                                        //
//   File:    IMGVIEWR.CPP                                //
//                                                        //
//   Desc:    Image viewer class                          //
//                                                        //
//--------------------------------------------------------//
#include "stdlib.h"
#include "string.h"
#include "conio.h"

#include "imgviewr.hpp"

//..................keyboard interface stuff
enum ViewerCommands
{
   cmdError,
   cmdEscape,
   cmdEnter,
   cmdPanHalf,
   cmdPanFull,
   cmdHome,
   cmdEnd,
};
static int keys[] =
{
   0x1B, 0x0D,                  // esc, enter
   0x47, 0x4F,                  // home, end
   0x34, 0x4B, 0x36, 0x4D,      // left/right arrow
   0x38, 0x48, 0x32, 0x50,      // up/down arrow
   0x39, 0x49, 0x33, 0x51       // up/down page
};
static int keycmds[] =
{
   cmdEscape,  cmdEnter,
   cmdHome,    cmdEnd,
   cmdPanHalf, cmdPanFull, cmdPanHalf, cmdPanFull,
   cmdPanHalf, cmdPanFull, cmdPanHalf, cmdPanFull,
   cmdPanHalf, cmdPanFull, cmdPanHalf, cmdPanFull
};
static int keydxs[] =
{
    0,  0,
   -1,  1,
   -1, -2,  1,  2,
    0,  0,  0,  0,
    0,  0,  0,  0
};
static int keydys[] =
{
    0,  0,
   -1,  1,
    0,  0,  0,  0,
   -1, -2,  1,  2,
   -1, -2,  1,  2
};
static int nkeys = sizeof(keys) / sizeof(int);

static int getkey( int& dx, int& dy )
{
   while( 1 )
   {
      int k = getch();
      if( k == 0 ) k = getch();

      for( int i=0; i<nkeys; i++ )
         if( k == keys[i] )
         {
            dx = keydxs[i];
            dy = keydys[i];
            return keycmds[i];
         }
   }
}
//..................the viewer class
ImageViewer::ImageViewer( VgaDisplay *vga, ImgStore *map,
                          rgb *clrs, int nclrs,
                          int ropt, int iopt )
{
   disp    = vga;
   image   = map;
   dit     = 0;
   imgpal  = 0;
   imgcnt  = 0;
   devpal  = 0;
   devcnt  = 0;
   clrmap  = 0;
   rendopt = ropt;
   intnopt = iopt;
   status  = 0;
   panning = 0;

   // scan line buffer
   scanwid = disp->metric.ncolumns;
   scanhgt = disp->metric.nrows;
   scanbuf = new unsigned char [scanwid];
   if( scanbuf == 0 )
   {
      status = 1;
      return;
   }

   // allocate and initialize palettes
   // if image is palette based
   int i;
   if( nclrs > 0 )
   {
      imgpal = new rgb [nclrs];
      if( imgpal == 0 )
      {
         status = 1;
         return;
      }
      devpal = new rgb [nclrs];
      if( devpal == 0 )
      {
         status = 1;
         return;
      }
      clrmap = new int [nclrs];
      if( clrmap == 0 )
      {
         status = 1;
         return;
      }
      imgcnt = nclrs;
      for( i=0; i<imgcnt; i++ )
      {
         imgpal[i] = clrs[i];
         clrmap[i] = i;
      }

      // apply any requested palette modifications
      alter_palette( imgpal, imgcnt );

      // initialize device palette to image palette
      devcnt = imgcnt;
      for( i=0; i<imgcnt; i++ )
         devpal[i] = imgpal[i];
   }

   // nclrs == 0 implies a 24-bit color image,
   // which has no palette
   else
   {
      devcnt = ColorDiffusionSize(disp->metric.ncolors);
      devpal = new rgb [devcnt];
      if( devpal == 0 )
      {
         status = 1;
         return;
      }
      imgpal = new rgb [scanwid];
      if( imgpal == 0 )
      {
         status = 1;
         return;
      }
   }

   // if the image must be approximated...
   if( (disp->metric.ncolors < imgcnt) || (imgcnt == 0) )
   {
      if( (ropt & renderDITHER) || (imgcnt == 0) )
      {
         dit = new ColorDiffusionDither( scanwid,
                      imgpal, imgcnt,
                      ColorDiffusionPalette(),
                      ColorDiffusionSize(disp->metric.ncolors) );
         if( dit == 0 )
         {
            status = 1;
            return;
         }
         devcnt = ColorDiffusionSize(disp->metric.ncolors);
         for( i=0; i<devcnt; i++ )
            devpal[i] = ColorDiffusionPalette()[i];
      }
      else
      {
         devcnt = disp->metric.ncolors;
         reduce_palette( devpal, imgcnt, devcnt );
         color_map( imgpal, imgcnt, devpal, devcnt,
                    clrmap, 2 );
      }
   }

   // set the device palette
   disp->putpalette( devpal, devcnt );

   // panning necessary?
   if( (image->width() > scanwid) ||
       (image->height() > scanhgt) )
      panning = 1;
}

ImageViewer::~ImageViewer( )
{
   if( scanbuf ) delete [] scanbuf;
   if( imgpal )  delete [] imgpal;
   if( devpal )  delete [] devpal;
   if( clrmap )  delete [] clrmap;
   if( dit )     delete    dit;
}

void ImageViewer::alter_palette( rgb *pal, int npal )
{
   // apply any intensity mapping
   if( intnopt & intensICNT )
      contrast_alter( pal, npal, iMORE );
   if( intnopt & intensDCNT )
      contrast_alter( pal, npal, iLESS );
   if( intnopt & intensIBRI )
      brightness_alter( pal, npal, iMORE );
   if( intnopt & intensDBRI )
      brightness_alter( pal, npal, iLESS );

   // force grayscale?
   if( (rendopt & renderGRAY) || (disp->metric.ncolors == 2) )
   {
      for( int i=0; i<npal; i++ )
      {
         int g = pal[i].graylevel();
         pal[i] = rgb( g, g, g );
      }
   }
}

void ImageViewer::go_home( ImCoord& ic )
{
   if( image->width() > scanwid )
   {
      ic.xo = 0;
      ic.x1 = 0;
      ic.x2 = scanwid - 1;
   }
   else
   {
      ic.xo = (scanwid - image->width()) / 2;
      ic.x1 = 0;
      ic.x2 = image->width() - 1;
   }

   if( image->height() > scanhgt )
   {
      ic.yo = 0;
      ic.y1 = 0;
      ic.y2 = scanhgt - 1;
   }
   else
   {
      ic.yo = (scanhgt - image->height()) / 2;
      ic.y1 = 0;
      ic.y2 = image->height() - 1;
   }
}

void ImageViewer::go_end( ImCoord& ic )
{
   if( image->width() > scanwid )
   {
      ic.xo = 0;
      ic.x2 = image->width() - 1;
      ic.x1 = ic.x2 - scanwid + 1;
   }
   else
   {
      ic.xo = (scanwid - image->width()) / 2;
      ic.x1 = 0;
      ic.x2 = image->width() - 1;
   }

   if( image->height() > scanhgt )
   {
      ic.yo = 0;
      ic.y2 = image->height() - 1;
      ic.y1 = ic.y2 - scanhgt + 1;
   }
   else
   {
      ic.yo = (scanhgt - image->height()) / 2;
      ic.y1 = 0;
      ic.y2 = image->height() - 1;
   }
}

void ImageViewer::mv_horz( ImCoord& ic, int dx )
{
   int ds = scanwid - ic.xo - 1;
   if( (dx > 0) && (ic.x2 < image->width()-1) )
   {
      ic.x1 += dx;
      if( ic.x1 > ic.x2 )
          ic.x1 = ic.x2;
      ic.x2 = ic.x1 + ds;
      if( ic.x2 >= image->width() )
          ic.x2 = image->width() - 1;
   }
   else if( (dx < 0) && (ic.x1 > 0) )
   {
      ic.x1 += dx;
      if( ic.x1 < 0 )
          ic.x1 = 0;
      ic.x2 = ic.x1 + ds;
      if( ic.x2 >= image->width() )
          ic.x2 = image->width() - 1;
   }
}

void ImageViewer::mv_vert( ImCoord& ic, int dy )
{
   int ds = scanhgt - ic.yo - 1;
   if( (dy > 0) && (ic.y2 < image->height()-1) )
   {
      ic.y1 += dy;
      if( ic.y1 > ic.y2 )
          ic.y1 = ic.y2;
      ic.y2 = ic.y1 + ds;
      if( ic.y2 >= image->height() )
          ic.y2 = image->height() - 1;
   }
   else if( (dy < 0) && (ic.y1 > 0) )
   {
      ic.y1 += dy;
      if( ic.y1 < 0 )
          ic.y1 = 0;
      ic.y2 = ic.y1 + ds;
      if( ic.y2 >= image->height() )
          ic.y2 = image->height() - 1;
   }
}

void ImageViewer::erase( void )
{
   memset( scanbuf, 0, scanwid );
   for( int i=0; i<scanhgt; i++ )
      disp->putscanline( scanbuf, scanwid, 0, i );
}

void ImageViewer::draw( ImCoord& ic )
{
   int            n = ic.x2 - ic.x1 + 1;
   int            y = ic.yo;
   unsigned char *p = scanbuf;

   for( int i=ic.y1; i<=ic.y2; i++ )
   {
      if( dit )
      {
         if( imgcnt > 0 )
         {
            image->cpy( scanbuf, i, ic.x1, n );
            dit->dither( scanbuf, n );
         }
         else // 24-bit image
         {
            unsigned char *s;
            s = image->get( i ) + ic.x1*3;
            for( int j=0; j<n; j++ )
               imgpal[j] = rgb( *s++, *s++, *s++ );
            alter_palette( imgpal, n );
            ColorDiffusionDither *d =
            (ColorDiffusionDither *) dit;
            d->rgbdither( scanbuf, imgpal, n );
         }
      }
      else if( imgcnt > devcnt )
      {
         image->cpy( scanbuf, i, ic.x1, n );
         for( int j=0; j<n; j++ )
            scanbuf[j] = clrmap[scanbuf[j]];
      }
      else
      {
         p = image->get( i ) + ic.x1;
      }
      disp->putscanline( p, n, ic.xo, y++ );
   }
}

int ImageViewer::view( void )
{
   if( status != 0 ) return status;

   ImCoord ic;      // image/screen coords
   int     dx, dy;  // panning deltas

   erase();
   go_home( ic );
   draw( ic );

   while( status == 0 )
   {
      int k = getkey( dx, dy );

      if( (k==cmdEscape) || (k==cmdEnter) )
         status = k;

      else if( panning )
      {
         dx *= scanwid;  dx /= 2;
         dy *= scanhgt;  dy /= 2;

         // home
         if( (dx < 0) && (dy < 0) )
         {
            go_home( ic );
            erase();
            draw( ic );
         }

         // end
         else if( (dx > 0) && (dy > 0) )
         {
            go_end( ic );
            erase();
            draw( ic );
         }

         // pan left/right
         else if( ((dx > 0) && (ic.x2 < image->width()-1)) ||
                  ((dx < 0) && (ic.x1 > 0)) )
         {
            mv_horz( ic, dx );
            erase();
            draw( ic );
         }

         // pan left/right
         else if( ((dy > 0) && (ic.y2 < image->height()-1)) ||
                  ((dy < 0) && (ic.y1 > 0)) )
         {
            mv_vert( ic, dy );
            erase();
            draw( ic );
         }

         // anything else
         else
         {
            // printf( "\x07" );
         }
      }
   }

   return status;
}

0
 

Author Comment

by:frane
ID: 1299475
The answer doesn't match my question. I only want to know, how I can get the raw pixel data (an array of bytes, i.e. 256x256, each byte representing one grayscale pixel) into a TBitmap or TDib instance, because I don't know, how to tell the TBitmap or TDib instance, that this array represents the pixel data, with the method SetBitmapBits I didn't get it work. At the moment I don't need a paint routine. If I got the data into the TDib instance, the rest will work (hopefully).

0
 
LVL 3

Expert Comment

by:JPM
ID: 1299476
Sorry for the mistake, I didn't see the author of the comment wasn't the original !...ans obviously I was out!

Have you got a lok to the OWL API
        CreateDibSection
            BITMAPINFO
        CreateCompatibleBitmap
0
 
LVL 1

Accepted Solution

by:
tiago earned 100 total points
ID: 1299477
Just use the constructor:

    TBitmap(int width, int height, uint8 planes,
            uint8 count, void* bits=0);


Example: a 256x256 image with 24 bits true-color information on
     an array named pixels:

    TBitmap * bt = new TBitmap (256,256,1,24,(void *)pixels);

    Don't forget that the scanlines must be word aligned;
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
WSDL Soap Error 12 259
Format results with PHP 3 68
CSS: Element name is not scoping properly 4 73
CSS (line height?) issue 2 59
Introduction Knockoutjs (Knockout) is a JavaScript framework (Model View ViewModel or MVVM framework).   The main ideology behind Knockout is to control from JavaScript how a page looks whilst creating an engaging user experience in the least …
SASS allows you to treat your CSS code in a more OOP way. Let's have a look on how you can structure your code in order for it to be easily maintained and reused.
Viewers will learn about arithmetic and Boolean expressions in Java and the logical operators used to create Boolean expressions. We will cover the symbols used for arithmetic expressions and define each logical operator and how to use them in Boole…
Viewers will learn one way to get user input in Java. Introduce the Scanner object: Declare the variable that stores the user input: An example prompting the user for input: Methods you need to invoke in order to properly get  user input:

929 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

8 Experts available now in Live!

Get 1:1 Help Now