Solved

It does not look like CopyImage help at all, Dan

Posted on 2001-07-26
27
247 Views
Last Modified: 2013-11-20
Dan:
It does not look like CopyImage help at all. I do appreciate your answer.
I use the following method to calculate each scan line width:
#define WIDTHBYTES(bits) (((bits) + 31) / 32 * 4)*lineWidth
is this not suitable for 16bpp?

chua
0
Comment
Question by:chual
  • 11
  • 8
  • 8
27 Comments
 
LVL 49

Expert Comment

by:DanRollins
ID: 6323913
the answer: No

Each 16-bit pixel describes its own color in an "abridged" RGB format.  So no palette is involved.

Is there a specific task you want to accomplish?  If so, state it and I will try to help.

-- Dan
0
 
LVL 1

Expert Comment

by:jizhang
ID: 6324600
It depends on what you are planning to do.

For 16 bit DIB, need no palette.

DIB can be  transported in 3 formats:
 Metafile in StretchDIBits()
 BMP file
 CF_DIB -- Clipboard format.

But If you want to create CBitmap class object, or HBITMAP object,
(both are DDB ) and then save to .bmp file.

  if( dc.GetDeviceCaps(RASTERCAPS) & RC_PALETTE ) {
       you have to create a logical Palette
      with 256 colors
};

Ji Zhang
0
 

Author Comment

by:chual
ID: 6324845
I am actually trying to get screen capture and save into a bitmap file. Somehow, the clipboard operation doesn not work for me. The steps I have done are:
1. created a compatible bitmap,
2. select the bitmap into a memory dc,
3. BitBlt to copy the captured data into the bitmap,
4. GetBitmapBits to copy each scan line into a buffer.
5. then save this buffer into a file.
I can make it work for 256 color using the RGBQUAD
for 16bpp 24bpp or 32bpp, I store their actually color bits into the file. It works fine for 24bpp and 32bpp, but the color get distorted on 16bpp. So looks like for 16bpp, simply saving the pixels into the file is not good enough.
Thanks
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 6325039
Looking for an quick solution... what if you use CopyImage to create a DIB?  There is a chance that this will end up with an acceptable image.

-- Dan
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 6327455
>>define WIDTHBYTES(bits) (((bits) + 31) / 32 * 4)*lineWidth
>>is this not suitable for 16bpp?

If the image looks OK, but only the colors are distorted, then your calculations should be fine.

Note that colors are certain to be a little bit off -- simply because the system will need to interpolate from the HighColor 6-5-5 RGB format to the 8-8-8 of TrueColor.

-- Dan

P.S.  In the future, please don't modify the question or the question title.  Just add a new post to the end.  That will avoid several kinds of confusion.
0
 

Author Comment

by:chual
ID: 6327521
To Dan:
Thanx, So is there a way to interpolate from HighColor to TrueColor or is there a different way of saving the bitmap such that windows will handle this situation for me?

chua
0
 
LVL 1

Expert Comment

by:jizhang
ID: 6327623
>>define WIDTHBYTES(bits) (((bits) + 31) / 32 * 4)>>*lineWidth
>>is this not suitable for 16bpp?

I guess:

define WIDTHBYTES(bits) (((bits * lineWidth) + 31) / 32 * 4)

so that
DWORD aligned for each scan line.

because of one DWORD == 32 bits == 4 BYTEs


0
 
LVL 49

Expert Comment

by:DanRollins
ID: 6329003
I think you are creating a "compatible" bitmap.  But if you create one that specifies the desired size and color depth, then perhaps when you bitblit the data to it, it will do the interpolation.  Just guessing tho.

-- Dan
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 6335520
hi chual,
Do you have any additional questions?  Do any comments need clarification?

-- Dan
0
 

Author Comment

by:chual
ID: 6335784
hi Dan,
Don't know yet. I have tried playing around with the BITMAPINFO structure. MSDN's documentation regarding 16bpp's implementation doesnot help at all. Looks like I have done nothing wrong with my code. But just don't know why it doesnot work.
I have also tried using clipboard operation, but even these simplest method could not sent the captured screen to the clipboard, too.
But the PRINT SCREEN key together with MS Paint is able to get it work. So I don't know how it was done. You have any idea?
chual
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 6340976
One thing about Ms Paint -- its Image Properties only let you choose color or mono ... when you choos colors, it sets up to use settings compatible with your current scree settings.  Thus, if you are currently set to 256-colors, and paste a screen dump into MS Paint, you will have a 256-color bmp.  If your screen is set to Hi-COlor (16bpp) then you will have a 16bpp bmp.

You can work around such oddities by changing the screen resolution Control Panel.  Grab an image into MS Paint, and save it.  Then switch resolutions and read the image back into MS Paint and save it with a new name.  Now you have the same image in two different bpp's for experimentation.

-- Dan
0
 
LVL 1

Expert Comment

by:jizhang
ID: 6341022
Have you tried RGB as 565 and 555, default is 555.

Set 65636 colors in control-panel-> display-settings->color palette
before doing capture may simplify your problem. color-depth would
 = 16bit -- need no change color depth.

for clipboard, I use:
       pWnd->OpenClipboard() ;
        EmptyClipboard() ;
        SetClipboardData (CF_BITMAP, bitmap.GetSafeHandle() ) ;
        CloseClipboard () ;
The key is use keyword "CF_BITMAP".
0
 

Author Comment

by:chual
ID: 6341985
I have tried both format for the RGB. None of them works. My application allows user to print a screen capture of the application. And I can't just tell them to change their screen resolution when using the feature. The clipboard operations I have tried out is exactly the same as what you show up there. But it did not work either. Anyway, thanx for the suggestionn. I will keep trying.
chual
0
6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

 

Author Comment

by:chual
ID: 6342080
Or do you happen to know how to convert a captured 16bpp bitmap in memory into other resolution like 4, 8, 24, or 32bpp. Then that will solve my problem. Thanx.
chual
0
 

Author Comment

by:chual
ID: 6342197
Maybe I should say how to map each 16bpp pixel into a pixel of different bit. Thanx
Brian
0
 
LVL 1

Expert Comment

by:jizhang
ID: 6342464
There is a class BitmapLib on codeguru site, which
can change BMP file color depth. I tried (from 32bit to 24 bit),
it works on Windows NT and 2000.
   ChangeColorDepth(bmpfilein, bmpfileout, depth, NULL);

The bpp of captured bitmap is depends on Device, in
my case, if set display to true color, I get 32 bit,
if set to 16 bit, I get 16 bit. CBitmap or HBITMAP are DDB.

For not compressed BMP, it should be easy to map 16 bit to 24,32
and write BMP file.

Resolution Bits per color Color Mask (RGB)
16bpp       5,5,5           0x00007c00 0x000003e0 0x0000001f
16bpp       5,6,5           0x0000f800 0x000007e0 0x0000001f
32bpp       8,8,8           0x00ff0000 0x0000ff00 0x000000ff

From 16 bit to lower, the colors could be lost, need to find "important"
colors and put into color table.

BMP struct
BITMAPFILEHEADER bmfh;
BITMAPINFOHEADER bmih;
RGBQUAD          aColors[];   may not have. table should appear in order of importance.
BYTE             aBitmapBits[];

scanline width should be:  integer * 4 BYTES, if not, fill zeros.
0
 

Author Comment

by:chual
ID: 6342702
-Dan, But Paint Brush will not let you save the file in 16bpp. You only get the 16bpp in memory.

-jiZhang, How do we make use of these masks anyway. Are we supposed to use the color mask with its own bpp? In 16bpp, If you AND each color component with the 16bpp mask, you just get your original value. while AND will set all pixel to WHITE. or is it that if i want to convert from 16bpp to 32 bpp, I will have to mask each color component(16bpp) with the 32bpp mask. But it does not make sense either (or should SHIFT operation be involved in this case?).

Thanx

chual
0
 

Author Comment

by:chual
ID: 6342759
-jiZhang, I meant OR the components of each 16bpp pixel with their respective masks with result in all WHITE pixel.
chual
0
 

Author Comment

by:chual
ID: 6343297
I think these masks are just for retrieving each color component from each pixel.
chual
0
 
LVL 1

Expert Comment

by:jizhang
ID: 6344540
If you use BYTE for the bitmapbits, convert 16 555 to 24 888:
color scale:  0 -> 0,  0x1f -> 0xff.

  loop scan line.
   get   Byte16[0] and Byte16[1]  (cast to int for calculation )
     Blue = (Byte16[1] & 0x1f) * 0xff / 0x1f
     Red = ((Byte16[0] & 0x7c) >> 2 ) * 0xff / 0x1f
     Green = {[(Byte16[0] & 0x03) << 3] + [(Byte16[1] & 0xe0 >> 5)]} * 0xff / 0x1f
   put   Byte24[0], Byte24[1], Byte24[2] with value Red, Green, Blue

   in this way, get each 2 BYTEs from 16 bitmap, convert to 3 BYTEs for 24 bit bitmap.

for 32 bit, output one more zero BYTE.
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 6347326
You really don't want (or need) to be messing with the raw image data.  

Just create an empty bitmap that is the right size and color depth, then use StretchBlit to copy it intelligently to the destination.  It will preserve whatever color it can.

Please restate your original question.  Describe exactly what you are trying to do -- that is, the *end result* (what the end user will see.)  Also increase the points.

-- Dan
0
 

Author Comment

by:chual
ID: 6365080
jizhang- i have to work on other stuff last weeks. Just had time to try out your algorithm yesterday. Your algorithm is wonderful. Theoretically, it should work great. The color is closer than what I had before but still too pale and I have to xchange Red and Green component ie. Byte24[0] = Green, Byte24[1] = Red, and Byte24[2] = Blue, in order to get green and blue displayed properly. otherwise green will be shown as blue and blue will be shown as green???

I was wondering if i should convert the color bit and map the color at all?
Here is my original codes (without converting the color bit), maybe you guys can figure out if there is something i have missed. Thanks.

// for color with 16bit and up
if (bm.CreateCompatibleBitmap(&dc, width, height))
{
  CBitmap* pOldBmp = dcMem.SelectObject(&bm);
  int iLnWidth = WIDTHBYTES((DWORD)width * Info.bmiHeader.biBitCount);
  bmInfo.bmiHeader.biCompression = BI_RGB;
  bmInfo.bmiHeader.biPlanes = 1;
  bmFH.bfType = DIB_HEADER_MARKER; //"BM"
  bmFH.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) +  sizeof(BITMAPINFO);
  bmFH.bfSize = bmFH.bfOffBits + WIDTHBYTES((DWORD)width * bmInfo.bmiHeader.biBitCount) * height;      
  file.Write((LPSTR)&bmFH, sizeof(bmFH));
  file.Write(&bmInfo.bmiHeader, sizeof(bmInfo.bmiHeader));

  LPVOID pBits = new BYTE[iLnWidth];
  for (int i = rect.Height()-1; i >= 0; i--)
  {
     dcMem.BitBlt(0, 0, width, 1, &dc, 0, i, SRCCOPY);
     bm.GetBitmapBits(iLnWidth, pBits);
     file.Write(pBits, iLnWidth);
  }
  ....
}
file.Close();

0
 
LVL 49

Expert Comment

by:DanRollins
ID: 6365400
>>I was wondering if i should convert the color bit and map the color at all?

No, you should not.  Messing around with the raw image data is inadvisable and rarely needed.  Let the system handle it, as I have explained.

-- Dan
0
 
LVL 1

Expert Comment

by:jizhang
ID: 6365674
> I was wondering if i should convert the color bit and map the color at all?

The color depth of the BMP you saved depends on DC, because
CBitmap object is DDB when you call CreateCompatibleBitmap,
the color depth is "compatible" with the DC.

If you want to get 16 bit depth, you need to set display-setting as 16 bit.

if a user use true color, then he/she will get 32 bit.
If you do not want to ask users to set display and stil want user  to get 16 bit,
then you have to deal with the converting.

I used to do is convert 32 bit to 24 bit (if the depth is 32 bit) only, because many
softwares can not display 32 bit bmp. In the 1992 bmp definition, it mentioned
1,4,8,24 bit, and said that would add 16 bit "in furtue", but did not mention 32 bit
at all.

Ji Zhang

 
0
 
LVL 1

Expert Comment

by:jizhang
ID: 6369040
For 24 bit bmp, the BYTE order is BGR,
the scanline is started from left-bottom corner.

Here is a prog in C  to write a 72x72 pixels with 24 color-bit BMP:

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

unsigned char img[15552];  /* 72 x 3 x 72  */

FILE * fout;


main()
{
char nameout[128];
BITMAPFILEHEADER  hdr;
BITMAPINFOHEADER  bi;
int i,j,k;

strcpy(nameout,"a24.bmp");
k =0;
/* BGR */
  for (j=0;j<24;j++) {
  for (i=0;i<24;i++) {
  img[k]= 0xff; img[k+1] = 0x00; img[k+2] = 0xff; k = k + 3;
  };
  for (i=0;i<24;i++) {
  img[k]= 0x00; img[k+1] = 0xff; img[k+2] = 0x80; k = k + 3;
  };
    for (i=0;i<24;i++) {
  img[k]= 0x00; img[k+1] = 0x80; img[k+2] = 0xff; k = k + 3;
  };
};

for (j=0;j<24;j++) {
  for (i=0;i<24;i++) {
  img[k]= 0xff; img[k+1] = 0xff; img[k+2] = 0x00; k = k + 3;
  };
  for (i=0;i<24;i++) {
  img[k]= 0x00; img[k+1] = 0x00; img[k+2] = 0x00; k = k + 3;
  };
    for (i=0;i<24;i++) {
  img[k]= 0x80; img[k+1] = 0xAf; img[k+2] = 0x40; k = k + 3;
  };
};
 

 for (j=0;j<24;j++) {
  for (i=0;i<24;i++) {
  img[k]= 0x00; img[k+1] = 0x00; img[k+2] = 0xff; k = k + 3;
  };
  for (i=0;i<24;i++) {
  img[k]= 0x00; img[k+1] = 0xff; img[k+2] = 0xff; k = k + 3;
  };
    for (i=0;i<24;i++) {
  img[k]= 0xff; img[k+1] = 0x00; img[k+2] = 0x00; k = k + 3;
  };
};

    hdr.bfType    = ((WORD) ('M' << 8) | 'B');    /* is always "BM"    */
    hdr.bfSize    = (DWORD)( 15552 + sizeof(BITMAPFILEHEADER) +  sizeof(BITMAPINFOHEADER));  
    hdr.bfReserved1  = 0;
    hdr.bfReserved2  = 0;
    hdr.bfOffBits  = (DWORD)( sizeof(BITMAPFILEHEADER) +  sizeof(BITMAPINFOHEADER));

      bi.biSize      = sizeof(BITMAPINFOHEADER);
      bi.biWidth    = 72;
      bi.biHeight   = 72;
      bi.biPlanes   = 1;
      bi.biBitCount       = 24 ;
      bi.biCompression   = BI_RGB ;
      bi.biSizeImage          = 0;
      bi.biXPelsPerMeter      = 0;  
      bi.biYPelsPerMeter      = 0;
      bi.biClrUsed            = 0;
      bi.biClrImportant       = 0;

   if ( (fout = fopen(nameout,"wb")) ==NULL ){      
      printf("\007Cann't open output file: %s ", nameout);
      exit(1);
      };
  fwrite( &hdr, sizeof(hdr),1,fout );
  fwrite( &bi, sizeof(bi),1,fout);
  fwrite( &img, sizeof(unsigned char),15552,fout);
  fclose(fout);
  printf("\007Output in %s\n",nameout);
 return 0;
}

Ji Zhang
0
 
LVL 1

Accepted Solution

by:
jizhang earned 100 total points
ID: 6373032
Pay attention to BYTE order in 16 bit BMP file

BYTE(LOW)  BYTE{HI) BYTE(LOW) BYTE{HI)
for 555, the bits order looks like:

 GGGBBBBB 0RRRRRGG -- one pixel

use the prog in my prev message to generate 16 bit BMP (same pic):

int x80 =  (BYTE)((int) 0x80 * (int) 0x1f / (int) 0xff );

k = 0;
  for (j=0;j<24;j++) {
  for (i=0;i<24;i++) {
  img[k+1] = 0x1f << 2; img[k] = 0x1f; k = k + 2;
  };
  for (i=0;i<24;i++) {
  img[k+1] = ( x80 << 2 ) + (0x1f >> 3); img[k] = (0x1f & 0x07) << 5;
  k = k + 2;
  };
    for (i=0;i<24;i++) {
    img[k+1] = (0x1f << 2) +  (x80 >> 3);  img[k] = (x80 & 0x07) << 5 ;
    k = k + 2;
  };
};
for (j=0;j<24;j++) {
  for (i=0;i<24;i++) {
  img[k+1] = 0x1f >> 3; img[k] = ((0x1f & 0x07) << 5) + 0x1f;  k = k + 2;
  };
  for (i=0;i<24;i++) {
  img[k+1] = 0x00; img[k] = 0x00; k = k + 2;
  };
  for (i=0;i<24;i++) {
  img[k+1] = ((x80 / 2) << 2) +  (BYTE) ((int)0xAf * (int)0x1f / (int)0xff) >> 3;
  img[k] =  ( ( (BYTE)((int)0xAf * (int)0x1f / (int)0xff) & 0x07) << 5) + x80;
  k = k + 2;
  };
};
 for (j=0;j<24;j++) {
  for (i=0;i<24;i++) {
  img[k+1] = 0x1f << 2;img[k]= 0x00; k = k + 2;
  };
  for (i=0;i<24;i++) {
  img[k+1] = (0x1f << 2) + (0x1f >> 3); img[k] = (0x1f & 0x07) << 5 ;
  k = k + 2;
  };
    for (i=0;i<24;i++) {
    img[k+1] = 0;   img[k] = 0x1f;  k = k + 2;
  };
};

/* size 10368 = 72 x 72 x 2  biBitCount 16, all other header para are same as 24 bit */
  hdr.bfSize    = (DWORD)( 10368 + sizeof(BITMAPFILEHEADER) +  sizeof(BITMAPINFOHEADER));  
  bi.biBitCount       = 16 ;

/* byte(k+1) =( r16 << 2) + (g16 >> 3)
   byte(k)     = (g16 & 0x07 << 5)  + b16
   r16 = r24 * 0x1f / 0xff,  g16 = g24 * 0x1f / 0xff,  b16 = b24 * 0x1f / 0xff
*/

0
 

Author Comment

by:chual
ID: 6391302
Thanks for you all you guys' help. All the information has been very helpful. But I have to work on other thing for now. I have been trying to convert 16bpp to 24bpp. Though the color is still a bit off and turn pale. But I think I am on the right path and I will stick to it later on. Thanks again for your help.
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
configuration management 2 100
Question regarding Copy/Paste 16 87
maxBlock challenge 30 100
Smart Camera scanning and reading information 3 86
Introduction: Hints for the grid button.  Nested classes, templated collections.  Squash that darned bug! Continuing from the sixth article about sudoku.   Open the project in visual studio. First we will finish with the SUD_SETVALUE messa…
If you use Adobe Reader X it is possible you can't open OLE PDF documents in the standard. The reason is the 'save box mode' in adobe reader X. Many people think the protected Mode of adobe reader x is only to stop the write access. But this fe…
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
Here's a very brief overview of the methods PRTG Network Monitor (https://www.paessler.com/prtg) offers for monitoring bandwidth, to help you decide which methods you´d like to investigate in more detail.  The methods are covered in more detail in o…

758 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

21 Experts available now in Live!

Get 1:1 Help Now