Solved

creating a Bitmap or DIB from an Pixel Array

Posted on 1997-11-19
7
472 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
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
Secure Your WordPress Site: 5 Essential Approaches

WordPress is the web's most popular CMS, but its dominance also makes it a target for attackers. Our eBook will show you how to:

Prevent costly exploits of core and plugin vulnerabilities
Repel automated attacks
Lock down your dashboard, secure your code, and protect your users

 
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

Don't Cry: How Liquid Web is Ensuring Security

WannaCry is just the start. Read how Liquid Web is protecting itself and its customers against new threats.

Question has a verified solution.

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

Preface This is the third article about the EE Collaborative Login Project. A Better Website Login System (http://www.experts-exchange.com/A_2902.html) introduces the Login System and shows how to implement a login page. The EE Collaborative Logi…
Have you tried to learn about Unicode, UTF-8, and multibyte text encoding and all the articles are just too "academic" or too technical? This article aims to make the whole topic easy for just about anyone to understand.
The viewer will learn how to dynamically set the form action using jQuery.
The viewer will learn how to create and use a small PHP class to apply a watermark to an image. This video shows the viewer the setup for the PHP watermark as well as important coding language. Continue to Part 2 to learn the core code used in creat…

728 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