Что такое код stretchbit
Возвращаемое значение
Отлично от нуля, если точечный рисунок выведен, иначе 0.
Параметры
x
Определяет x-координату (в логических модулях) левого верхнего угла прямоугольника адресата.
y
Определяет y-координату (в логических модулях) левого верхнего угла прямоугольника адресата.
nWidth
Определяет ширину (в логических модулях) прямоугольника адресата.
nHeight
Определяет высоту (в логических модулях) прямоугольника адресата.
pSrcDC
Определяет исходный контекст устройства.
xSrc
Определяет x-координату (в логических модулях) левого верхнего угла исходного прямоугольника.
ySrc
Определяет x-координату (в логических модулях) левого верхнего угла исходного прямоугольника.
nSrcWidth
Определяет ширину (в логических модулях) исходного прямоугольника.
nSrcHeight
Определяет высоту (в логических модулях) исходного прямоугольника.
Specifies
Определяет растровую операцию, которую нужно выполнить. Растровые коды операции определяют, как GDI объединяет цвета в операциях вывода, которые включают текущую кисть, возможный исходный точечный рисунок, и точечный рисунок адресата. Этот параметр может быть одно из следующих значений:
- BLACKNESS — Растровая карта выводиться черным.
- DSTINVERT — Инвертирует точечный рисунок адресата.
- MERGECOPY — Объединяет образец и исходный точечный рисунок, использующий Булевый и (AND) оператор.
- MERGEPAINT — Объединяет инвертированный исходный точечный рисунок с точечным рисунком адресата используя Булевый или (OR) оператор.
- NOTSRCCOPY — Копирует инвертированный исходный точечный рисунок адресату.
- NOTSRCERASE — Инвертирует результат объединения адресата и исходных точечных рисунков, используя Булевый и(AND) оператор.
- PATCOPY — Копирует образец к точечному рисунку адресата.
- PATINVERT — Объединяет точечный рисунок адресата с образцом, используя Булевый оператора XOR.
- PATPAINT — Объединяет инвертированный исходный точечный рисунок с образцом, используя Булевый или(OR) оператор. Объединяет результат этой операции с точечным рисунком адресата используя Булевый или (OR) оператор.
- SRCAND — Объединяет пиксели адресата и исходных точечных рисунков, используя Булевый и (AND) оператор.
- SRCCOPY — Копирует исходный точечный рисунок к точечному рисунку адресата.
- SRCERASE — Инвертирует точечный рисунок и объединяет результат с исходным точечным рисунком, используя Булевый и (AND) оператор.
- SRCINVERT — Объединяет пиксели адресата и исходных точечных рисунков, используя Булевый оператора XOR.
- SRCPAINT — Объединяет пиксели адресата и исходных точечных рисунков, используя Булевый или (OR) оператор.
- WHITENESS — Вся растровая карта белая.
Замечания
Копирует точечный рисунок с исходного прямоугольника в прямоугольник адресата, растягивая или сжимая точечный рисунок в случае необходимости, чтобы приспособить размерности прямоугольника адресата. Функция использует режим протяжения контекста устройства адресата (установленный SetStretchBltMode) чтобы определить, как растягивать или сжать точечный рисунок.
Функция StretchBlt перемещает точечный рисунок из исходного устройства, данного pSrcDC на устройство адресата, представляемое объектом контекста устройства, чья функция вызвана. xSrc, ySrc, nSrcWidth, и nSrcHeight параметры определяют левый верхний угол и размерности исходного прямоугольника. x, y, nWidth, и nHeight параметры дают левый верхний угол и размерности прямоугольника адресата. Растровая операция, определенная dwRop определяет, как исходный точечный рисунок и биты уже на устройстве адресата объединены.
Что такое код stretchbit
Не получается вывести картинку в заданные координаты с заданными размерами.
За основу взял пример по DirectDraw из WM6 SDK.
//
// Get size of the bitmap
//
GetObject(hbm, sizeof(bm), &bm);
dx = dx == 0 ? bm.bmWidth : dx; // Use the passed size, unless zero
dy = dy == 0 ? bm.bmHeight : dy;
//
// Get size of surface.
//
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_HEIGHT | DDSD_WIDTH;
pdds->GetSurfaceDesc(&ddsd);
Данный код выводит любую картинку на весь экран. Мне же нужно вывести в координаты 20,20 с размерами 20 на 20 пикселей.
Задаю x = y = dx = dy = 20; В результате картинка уезжает за левый верхний край экран и становится еще большей чем была.
В чем может быть проблема?
Все параметры для StretchBlt задаются в logical units. Что это, пиксели или какие то другие юниты?
Правильно комбинируйте StretchBlt и TransparentBlt, чтобы можно было правильно создать прозрачное растровое изображение
ВВЕДЕНИЕ И СООТВЕТСТВУЮЩАЯ ИНФОРМАЦИЯ:
Недавно я задал здесь, в SO, вопрос о правильном масштабировании растрового изображения, чтобы оно могло сохранять качество изображения:
Я попытался использовать предложение, сделанное в комментарии, для использования `StretchBlt, поэтому я создал небольшую демонстрационную программу.
Это улучшило резкость растровых изображений после того, как я установил режим растяжения на BLACKONWHITE ,
Я хотел бы попытаться сделать прозрачной часть растрового изображения с определенным цветом, скажем, черным.
Я использовал TransparentBlt раньше, но я не знаю, как это сделать сейчас.
ПРОБЛЕМА:
Чтобы сохранить резкость картинки, мне нужно StretchBlt это в памяти DC, с режимом растяжения BLACKONWHITE ,
Проблема в том, что я не знаю, как Blt это прозрачно в главном окне DC.
Вот фрагмент кода из демо-приложения:
ВОПРОС:
Как изменить приведенный выше код, чтобы растровое изображение могло быть прозрачным, чтобы была видна тестовая кисть?
Исходное изображение ниже.
Мне просто нужно использовать TransparentBlt( . RGB( 0, 0, 0 ) ); сделать его прозрачным в черных областях.
Пример изображения, на котором показан результат:
МОИ УСИЛИЯ:
Просматривая Интернет, я нашел только простые уроки, касающиеся двойной буферизации.
Я не нашел ничего подобного, но, если честно, я неопытный в WIN32 API, поэтому я не знаю, как правильно сформулировать вопрос, чтобы получить лучшие результаты поиска.
Если потребуется дополнительная информация, попросите ее, и я предоставлю ее.
Что такое код stretchbit
Использую Printer для печати графического изображения.
При использовании Printer.Canvas.Pixels[i,j] все печатается ок (правда в уменьшенном масштабе и жутко медленно), а вот API-функции BitBtl(), SttretchBLT() на Printer.Canvas.Handle печатают пустой лист. Подскажите, в чем может быть проблема. GetDeviceCaps выдает capability RC_BITBLT и RC_STRETCHBLT
А ты как эти функции юзаешь ?
Т.е как потом присваеваешь канвасу принтера ?
.
StretchBlt(Printer.Canvas.Handle, 0,0, 500,500, Image2.Canvas.Handle, 0, 0, 300, 300, SRCCOPY);
А чем не устраивает этот вариант ?
printer.Canvas.StretchDraw(Image1.ClientRect,Image1.Picture.Bitmap);
а он тоже не работает поэтому перешел на API
как это не работает ?
Как вы картинку загружаете ?
Код в студию. Чуть шо ICQ№ 926-571
Да, привидите код пожайлуста, а то не видно как вызваются функции StartDoc, EndDoc.
ок. тестовый пример, который не работает:
.
for i := 0 to 300 do
for j := 0 to 300 do
if (i mod 2) = 0 then
Image2.Canvas.Pixels[i,j] := clBlack;
.
StretchBlt(Printer.Canvas.Handle, 0,0, 500,500, Image2.Canvas.Handle, 0, 0, 300, 300, SRCCOPY)
ну или
printer.Canvas.StretchDraw(Image2.ClientRect,Image2.Picture.Bitmap);
> [7] Anatoly © (17.08.05 18:01)
> ок. тестовый пример, который не работает:
Это не тестовый пример. Это мелкий кусок кода.
2Applet
Вызов StretchBlt заключен между вызовами StartDoc EndDoc
2KilkennyCat
он такой и есть, но должен работать
Как распечатать картинку?
Своим кодом делится Олег Кулабухов:
type
PPalEntriesArray = ^TPalEntriesArray;
TPalEntriesArray = array[0..0] of TPaletteEntry;
if IsPaletteDevice then
BitmapInfoSize := sizeof(TBitmapInfo) + (sizeof(TRGBQUAD) * 255)
else
BitmapInfoSize := sizeof(TBitmapInfo);
GetMem(lpBitmapInfo, BitmapInfoSize);
lpBitmapInfo^.bmiHeader.biSize := sizeof(TBitmapInfoHeader);
lpBitmapInfo^.bmiHeader.biW >lpBitmapInfo^.bmiHeader.biHeight := bm.Height;
lpBitmapInfo^.bmiHeader.biPlanes := 1;
if IsPaletteDevice then
lpBitmapInfo^.bmiHeader.biBitCount := 8
else
lpBitmapInfo^.bmiHeader.biBitCount := 24;
lpBitmapInfo^.bmiHeader.biCompression := BI_RGB;
lpBitmapInfo^.bmiHeader.biSizeImage :=
((lpBitmapInfo^.bmiHeader.biWidth *
longint(lpBitmapInfo^.bmiHeader.biBitCount)) div *
lpBitmapInfo^.bmiHeader.biHeight;
lpBitmapInfo^.bmiHeader.biXPelsPerMeter := 0;
lpBitmapInfo^.bmiHeader.biYPelsPerMeter := 0;
if IsPaletteDevice then begin
lpBitmapInfo^.bmiHeader.biClrUsed := 256;
lpBitmapInfo^.bmiHeader.biClrImportant := 256;
end else begin
lpBitmapInfo^.bmiHeader.biClrUsed := 0;
lpBitmapInfo^.bmiHeader.biClrImportant := 0;
end;
hBits := GlobalAlloc(GMEM_MOVEABLE,
lpBitmapInfo^.bmiHeader.biSizeImage);
pBits := GlobalLock(hBits);
GetDiBits(dc,
hBm,
0,
lpBitmapInfo^.bmiHeader.biHeight,
pBits,
TBitmapInfo(lpBitmapInfo^),
DIB_RGB_COLORS);
if IsPaletteDevice then begin
GetMem(lPPalEntriesArray, sizeof(TPaletteEntry) * 256);
<$IFDEF VER100>
NumPalEntries := GetPaletteEntries(hPal,
0,
256,
lPPalEntriesArray^);
<$ELSE>
NumPalEntries := GetSystemPaletteEntries(dc,
0,
256,
lPPalEntriesArray^);
<$ENDIF>
for i := 0 to (NumPalEntries — 1) do begin
lpBitmapInfo^.bmiColors[i].rgbRed :=
lPPalEntriesArray^[i].peRed;
lpBitmapInfo^.bmiColors[i].rgbGreen :=
lPPalEntriesArray^[i].peGreen;
lpBitmapInfo^.bmiColors[i].rgbBlue :=
lPPalEntriesArray^[i].peBlue;
end;
FreeMem(lPPalEntriesArray, sizeof(TPaletteEntry) * 256);
end;
IsDestPaletteDevice :=
GetDeviceCaps(DestDc, RASTERCAPS) and RC_PALETTE = RC_PALETTE;
if IsDestPaletteDevice then begin
procedure TForm1.Button1Click(Sender: TObject);
begin
if PrintDialog1.Execute then begin
Printer.BeginDoc;
BltTBitmapAsDib(Printer.Canvas.Handle,
0,
0,
Image1.Picture.Bitmap.Width,
Image1.Picture.Bitmap.Height,
Image1.Picture.Bitmap);
Printer.EndDoc;
end;
end;
Anatoly © (17.08.05 18:09) [10]
Пожайлуста код целиком, попорядку. Или на крайний случай статусы завершения всех операций (Win2k/XP — use GetLastError).
Извините за страшный формат, копи-пасте как-то не так сработал.
2KilkennyCat Спасибо, попробую
procedure TForm1.Button12Click(Sender: TObject);
var
i, j: integer;
begin
for i := 0 to 300 do
for j := 0 to 300 do
if (i mod 2) = 0 then
Image2.Canvas.Pixels[i,j] := clBlack;
end;
procedure TForm1.Button9Click(Sender: TObject);
begin
Printer.BeginDoc;
StretchBlt(Printer.Canvas.Handle, 0,0, 500,500, Image2.Canvas.Handle, 0, 0, 300, 300, SRCCOPY)
Printer.EndDoc;
end;
procedure Tmform.sbPrintClick(Sender: TObject);
var dst, src: TRect;
begin
with Printer do
try
BeginDoc;
img.Picture.LoadFromFile («c:\doc\16colors.bmp»);
SetRect (dst, 0, 0, PageWidth — 1, PageHeight — 1);
SetRect (src, 0, 0, img.Width — 1, img.Height — 1);
Canvas.CopyRect(dst, img.Canvas, src);
EndDoc;
except
end;
P.S: У меня нет принтера, но зато смог получить 171Мбайтный .ps (PostScript), через печать в файл. Посмотрел в GSView — вроде то что нужно. Попробуй этот код.
ок, спасибо, попробую
Вообще печать такими большими блоками не рекомендуется. Советую найти книгу Фень Юаня «Программирование Графики для Windows», там все хорошо расписано.
CDC::StretchBlt
Nonzero if the bitmap is drawn; otherwise 0.
Specifies the x-coordinate (in logical units) of the upper-left corner of the destination rectangle.
Specifies the y-coordinate (in logical units) of the upper-left corner of the destination rectangle.
Specifies the width (in logical units) of the destination rectangle.
Specifies the height (in logical units) of the destination rectangle.
Specifies the source device context.
Specifies the x-coordinate (in logical units) of the upper-left corner of the source rectangle.
Specifies the x-coordinate (in logical units) of the upper-left corner of the source rectangle.
Specifies the width (in logical units) of the source rectangle.
Specifies the height (in logical units) of the source rectangle.
Specifies the raster operation to be performed. Raster operation codes define how GDI combines colors in output operations that involve a current brush, a possible source bitmap, and a destination bitmap. This parameter may be one of the following values:
-
BLACKNESS Turns all output black.
DSTINVERT Inverts the destination bitmap.
MERGECOPY Combines the pattern and the source bitmap using the Boolean AND operator.
MERGEPAINT Combines the inverted source bitmap with the destination bitmap using the Boolean OR operator.
NOTSRCCOPY Copies the inverted source bitmap to the destination.
NOTSRCERASE Inverts the result of combining the destination and source bitmaps using the Boolean OR operator.
PATCOPY Copies the pattern to the destination bitmap.
PATINVERT Combines the destination bitmap with the pattern using the Boolean XOR operator.
PATPAINT Combines the inverted source bitmap with the pattern using the Boolean OR operator. Combines the result of this operation with the destination bitmap using the Boolean OR operator.
SRCAND Combines pixels of the destination and source bitmaps using the Boolean AND operator.
SRCCOPY Copies the source bitmap to the destination bitmap.
SRCERASE Inverts the destination bitmap and combines the result with the source bitmap using the Boolean AND operator.
SRCINVERT Combines pixels of the destination and source bitmaps using the Boolean XOR operator.
SRCPAINT Combines pixels of the destination and source bitmaps using the Boolean OR operator.
Copies a bitmap from a source rectangle into a destination rectangle, stretching or compressing the bitmap if necessary to fit the dimensions of the destination rectangle. The function uses the stretching mode of the destination device context (set by SetStretchBltMode) to determine how to stretch or compress the bitmap.
The StretchBlt function moves the bitmap from the source device given by pSrcDC to the destination device represented by the device-context object whose member function is being called. The xSrc, ySrc, nSrcWidth, and nSrcHeight parameters define the upper-left corner and dimensions of the source rectangle. The x, y, nWidth, and nHeight parameters give the upper-left corner and dimensions of the destination rectangle. The raster operation specified by dwRop defines how the source bitmap and the bits already on the destination device are combined.
The StretchBlt function creates a mirror image of a bitmap if the signs of the nSrcWidth and nWidth or nSrcHeight and nHeight parameters differ. If nSrcWidth and nWidth have different signs, the function creates a mirror image of the bitmap along the x-axis. If nSrcHeight and nHeight have different signs, the function creates a mirror image of the bitmap along the y-axis.
The StretchBlt function stretches or compresses the source bitmap in memory and then copies the result to the destination. If a pattern is to be merged with the result, it is not merged until the stretched source bitmap is copied to the destination. If a brush is used, it is the selected brush in the destination device context. The destination coordinates are transformed according to the destination device context; the source coordinates are transformed according to the source device context.
If the destination, source, and pattern bitmaps do not have the same color format, StretchBlt converts the source and pattern bitmaps to match the destination bitmaps. The foreground and background colors of the destination device context are used in the conversion.
If StretchBlt must convert a monochrome bitmap to color, it sets white bits (1) to the background color and black bits (0) to the foreground color. To convert color to monochrome, it sets pixels that match the background color to white (1) and sets all other pixels to black (0). The foreground and background colors of the device context with color are used.
Not all devices support the StretchBlt function. To determine whether a device supports StretchBlt, call the GetDeviceCaps member function with the RASTERCAPS index and check the return value for the RC_STRETCHBLT flag.
StretchBlt работает не на всех компах
Здравствуйте. Обнаружил в программе глюк — во время печати используется функция StretchBlt() в контекст принтера. Корректно работает только на тех компах, где либо установлена Вижуал Студия, либо установлена Виндоу 7. На ВинХР без установленной «вижуал студии» не работает.
Причем, все остальное, то что выводится не через StretchBlt(), а функциями рисования — работает везде.
Свел код вот к такому минимуму. Есть какое-то окно, производное от CWnd, в котором делается прорисовка на экран.
При печати вывожу на принтер информацию из этого окна с помощью StretchBlt(), а дополнительную информацию вывожу функциями рисования (типа TextOut(), LineTo() и др.) напрямую в контексте принтера.
Собственно, сам код:
Вот это класс, в котором что-то рисую на экране:
А это уже код, с помощью которого вывожу содержимое окна на печать.
Подскажите, в чем может быть проблема?
Прикладываю тестовый проект с исходниками. (Печать по кнопочке «StretchBlt to printer context»).
778 — CDC::StretchBlt / MFC Справка / Visual C++
Шаг 778 — CDC::StretchBlt
Возвращаемое значение
Отлично от нуля, если точечный рисунок выведен, иначе 0.
Параметры
x
Определяет x-координату (в логических модулях) левого верхнего угла прямоугольника адресата.
y
Определяет y-координату (в логических модулях) левого верхнего угла прямоугольника адресата.
nWidth
Определяет ширину (в логических модулях) прямоугольника адресата.
nHeight
Определяет высоту (в логических модулях) прямоугольника адресата.
pSrcDC
Определяет исходный контекст устройства.
xSrc
Определяет x-координату (в логических модулях) левого верхнего угла исходного прямоугольника.
ySrc
Определяет x-координату (в логических модулях) левого верхнего угла исходного прямоугольника.
nSrcWidth
Определяет ширину (в логических модулях) исходного прямоугольника.
nSrcHeight
Определяет высоту (в логических модулях) исходного прямоугольника.
Specifies
Определяет растровую операцию, которую нужно выполнить. Растровые коды операции определяют, как GDI объединяет цвета в операциях вывода, которые включают текущую кисть, возможный исходный точечный рисунок, и точечный рисунок адресата. Этот параметр может быть одно из следующих значений:
- BLACKNESS — Растровая карта выводиться черным.
- DSTINVERT — Инвертирует точечный рисунок адресата.
- MERGECOPY — Объединяет образец и исходный точечный рисунок, использующий Булевый и (AND) оператор.
- MERGEPAINT — Объединяет инвертированный исходный точечный рисунок с точечным рисунком адресата используя Булевый или (OR) оператор.
- NOTSRCCOPY — Копирует инвертированный исходный точечный рисунок адресату.
- NOTSRCERASE — Инвертирует результат объединения адресата и исходных точечных рисунков, используя Булевый и(AND) оператор.
- PATCOPY — Копирует образец к точечному рисунку адресата.
- PATINVERT — Объединяет точечный рисунок адресата с образцом, используя Булевый оператора XOR.
- PATPAINT — Объединяет инвертированный исходный точечный рисунок с образцом, используя Булевый или(OR) оператор. Объединяет результат этой операции с точечным рисунком адресата используя Булевый или (OR) оператор.
- SRCAND — Объединяет пиксели адресата и исходных точечных рисунков, используя Булевый и (AND) оператор.
- SRCCOPY — Копирует исходный точечный рисунок к точечному рисунку адресата.
- SRCERASE — Инвертирует точечный рисунок и объединяет результат с исходным точечным рисунком, используя Булевый и (AND) оператор.
- SRCINVERT — Объединяет пиксели адресата и исходных точечных рисунков, используя Булевый оператора XOR.
- SRCPAINT — Объединяет пиксели адресата и исходных точечных рисунков, используя Булевый или (OR) оператор.
- WHITENESS — Вся растровая карта белая.
Замечания
Копирует точечный рисунок с исходного прямоугольника в прямоугольник адресата, растягивая или сжимая точечный рисунок в случае необходимости, чтобы приспособить размерности прямоугольника адресата. Функция использует режим протяжения контекста устройства адресата (установленный SetStretchBltMode) чтобы определить, как растягивать или сжать точечный рисунок.
Функция StretchBlt перемещает точечный рисунок из исходного устройства, данного pSrcDC на устройство адресата, представляемое объектом контекста устройства, чья функция вызвана. xSrc, ySrc, nSrcWidth, и nSrcHeight параметры определяют левый верхний угол и размерности исходного прямоугольника. x, y, nWidth, и nHeight параметры дают левый верхний угол и размерности прямоугольника адресата. Растровая операция, определенная dwRop определяет, как исходный точечный рисунок и биты уже на устройстве адресата объединены.
Графический интерфейс GDI в Microsoft Windows
4.1. Битовые изображения в формате DDB
Как мы уже говорили, битовые изображения в формате DDB являются аппаратно-зависимыми. Поэтому структура изображения в оперативной памяти зависит от особенностей аппаратуры.
В предыдущих томах «Библиотеки системного программиста» мы использовали изображения DDB и даже приводили исходный текст функции DrawBitmap, с помощью которой можно нарисовать такое изображение на экране.
Как правило, изображения DDB либо загружаются из ресурсов приложения, либо создаются непосредственно в оперативной памяти. Для вывода изображений DDB на экран используются такие функции, как BitBlt и StretchBlt.
Изображения DIB, в отличие от изображений DDB, являются аппаратно-независимыми, поэтому без дополнительного преобразования их нельзя отображать на экране с помощью функций BitBlt и StretchBlt. В операционной системе Windows версий 3.х битовые изображения хранятся в файлах с расширением имени bmp, при этом используется аппаратно-независимый формат DIB.
Загрузка изображений из ресурсов приложения
Самый простой способ использования битовых изображений в приложениях Windows заключается в том, что изображение создается графическим редактором в виде bmp-файла и описывается в файле определения ресурсов приложения при помощи оператора BITMAP:
Созданное таким образом битовое изображение можно загрузить в память при помощи функции LoadBitmap :
Параметр hinst определяет идентификатор копии приложения, из ресурсов которого нужно загрузить изображение. Идентификатор ресурса изображения задан параметром lpszBitmap. Функция LoadBitmap возвращает идентификатор загруженного изображения или NULL при ошибке.
После использования приложение должно удалить битовое изображение. Для этого лучше всего воспользоваться макрокомандой DeleteBitmap , описанной в файле windowsx.h следующим образом:
В качестве параметра этой макрокоманде нужно передать идентификатор удаляемого изображения.
Приложение может определить параметры загруженного изображения, вызвав функцию GetObject :
С помощью этой функции можно получить разнообразную информацию об объектах GDI, таких, как логические перья, кисти, шрифты или битовые изображения.
Для нас интересно использование этой функции с целью получения параметров изображения. Идентификатор изображения должен передаваться через параметр hgdiobj. Параметр lpvObject должен указывать на структуру типа BITMAP, в которую будут записаны сведения об изображении. Через параметр cbBuffer следует передать размер структуры BITMAP:
Структура BITMAP и указатели на нее описаны в файле windows.h:
Опишем назначение отдельных полей этой структуры.
Поле | Описание |
bmType | Тип битового изображения. Должен быть равен 0 |
bmWidth | Ширина битового изображения в пикселах, должна быть больше 0 |
bmHeight | Высота битового изображения в пикселах, должна быть больше 0 |
bmWidthBytes | Размер памяти, занимаемый одной строкой растра битового изображения. Это значение должно быть четным, так как массив изображения состоит из целых чисел размером 16 бит. Таким образом, произведение bmWidthBytes*8 должно быть кратно 16. Кроме того, это произведение должно быть больше или равно произведению bmWidth*bmBitsPixel |
bmPlanes | Количество плоскостей в битовом изображении. В зависимости от типа видеоадаптера и его режима работы для представления цвета одного пиксела может использоваться несколько бит, расположенных в одной или нескольких плоскостях видеопамяти (подробное описание структуры видеопамяти в различных режимах вы можете найти в 3 томе «Библиотеки системного программиста») |
bmBitsPixel | Количество битов, используемых для представления цвета пиксела. Если используется несколько плоскостей, то это поле содержит количество бит одной плоскости, используемых для представления цвета пиксела |
bmBits | Дальний указатель на массив, содержащий биты изображения |
Загрузив битовое изображение из ресурсов приложения, вы можете определить его размеры, узнать количество цветовых плоскостей и количество бит в одной плоскости, определяющих цвет пиксела. Кроме этого, вы можете получить указатель на область памяти, содержащую биты изображения.
Для монохромных битовых изображений используется одна плоскость. Для определения цвета пиксела (черный или белый) используется один бит памяти. Размер памяти, занимаемый одной строкой растра битового изображения, кратен величине 16 бит.
Пусть, например, вы подготовили с помощью графического редактора, входящего в состав приложения Resource Workshop, битовое изображение, показанное на рис. 4.1. Для наглядности каждая строка растра этого изображения пронумерована.
Рис. 4.1. Черно-белое битовое изображение
Этому представлению соответствует дамп памяти, представленный ниже:
Так как буфер, в котором хранится строка, должен иметь длину, кратную длине слова (два байта), буфер каждой строки дополняется нулем.
Обратите внимание, что для изображений DDB используется система координат, соответствующая режиму отображения MM_TEXT, т. е. система координат, принятая для устройства отображения.
Рисование изображения DDB
Итак, мы загрузили битовое изображение в память и определили его параметры. Теперь наша задача заключается в том, чтобы нарисовать загруженное изображение в окне приложения.
Как мы уже говорили, в программном интерфейсе Windows (а точнее, в программном интерфейсе GDI) нет функции, предназначенной для рисования битовых изображений. Как же быть?
Используется следующая последовательность действий.
Прежде всего надо создать контекст памяти, совместимый с контекстом отображения реального устройства вывода. Для этого следует воспользоваться функцией CreateCompatibleDC.
Далее необходимо выбрать предварительно загруженное битовое изображение в контекст памяти с помощью функции SelectObject, указав ей в качестве параметров идентификатор контекста памяти и идентификатор загруженного изображения.
Затем нужно скопировать биты изображения из контекста памяти в контекст отображения, вызвав функцию BitBlt или StretchBlt. При этом изображение будет нарисовано на устройстве вывода, которое соответствует контексту отображения.
Рассмотрим реализацию этой последовательности действий на примере функции DrawBitmap , которую мы использовали в приложениях, описанных в предыдущих томах «Библиотеки системного программиста»:
В качестве параметров этой функции передается идентификатор контекста отображения hDC, в котором необходимо нарисовать изображение, координаты x и y верхнего левого угла прямоугольной области, в которой будет нарисовано изображение, а также идентификатор самого изображения hBitmap.
Прежде всего функция DrawBitmap создает контекст памяти, совместимый с контекстом отображения, передаваемого через параметр hDC:
В качестве параметра для этой функции можно использовать значение NULL. В этом случае будет создан контекст памяти, совместимый с экраном видеомонитора. Функция возвращает идентификатор созданного контекста или NULL при ошибке.
Далее функция DrawBitmap выбирает изображение в созданный контекст памяти:
Функция SelectObject возвращает идентификатор битового изображения, которое было выбрано в контекст памяти раньше. Так как мы только что создали контекст памяти, мы получим идентификатор битового изображения, выбранного в контекст памяти по умолчанию. Это монохромное изображение, состоящее из одного пиксела. Контекст памяти необходимо удалить после использования. Перед удалением мы должны выбрать в него изображение, которое было выбрано при создании, т. е. изображение с идентификатором hOldbm.
Теперь мы выбрали наше изображение в контекст памяти и готовы выполнить копирование в контекст отображения. Однако перед этим необходимы некоторые подготовительные действия.
Прежде всего нужно сделать так, чтобы в контексте памяти использовался тот же режим отображения, что и в контексте отображения. По умолчанию при создании контекста памяти (как и любого другого контекста) устанавливается режим отображения MM_TEXT. Однако в контексте отображения, идентификатор которого передается функции DrawBitmap, может быть установлен любой режим отображения, например, метрический. Для обеспечения соответствия режимов отображения удобно использовать функции GetMapMode и SetMapMode :
Функция GetMapMode возвращает код режима отображения, установленного в контексте отображения. Этот код передается в качестве второго параметра функции SetMapMode, которая устанавливает такой же режим отображения в контексте памяти.
Так как функции BitBlt , копирующей биты изображения, необходимо указать координаты прямоугольной области, занимаемой изображением в контексте памяти, следует определить размеры изображения. Это можно сделать с помощью функции GetObject, которую мы только что описали:
В данном случае нас интересуют ширина и высота изображения в пикселах:
Так как в контексте отображения может быть выбран любой режим отображения, размеры изображения необходимо преобразовать в логические, вызвав функцию DPtoLP:
Об этой функции мы рассказывали в разделе, посвященной режимам отображения.
Для копирования битов изображения из контекста памяти в контекст отображения функция DrawBitmap использует функцию BitBlt (читается как «бит-блит»):
Функция копирует битовое изображение из исходного контекста hdcSrc в контекст отображения hdcDest. Возвращаемое значение равно TRUE при успешном завершении или FALSE при ошибке.
Размеры копируемого изображения задаются парамерами nWidth и nHeight. Координаты левого верхнего угла изображения в исходном контексте определяются параметрами nXSrc и nYSrc, а в контексте, куда копируется изображение, параметрами nXDest и nYDest.
Последний параметр dwRop определяет растровую операцию, используемую для копирования.
Отметим, что размеры и координаты необходимо задавать в логических единицах, соответствующих выбранному режиму отображения.
В нашем случае изображение копируется из точки (0,0) в физической системе координат в точку (x,y) в логической системе координат. Поэтому перед копированием изображения необходимо выполнить преобразование физических координат (0,0) в логические, вызвав функцию DPtoLP:
После этого можно вызывать функцию BitBlt:
Эта функция копирует битовое изображение, имеющее размеры ptSize, из контекста памяти hMemDC в контекст отображения hDC. При этом логические координаты верхнего левого угла изображения в контексте памяти находятся в структуре ptOrg. Координаты верхнего левого угла прямоугольной области в контексте отображения, куда будет копироваться изображение, передаются через параметры x и y.
После рисования битового изображения функция DrawBitmap выбирает в контекст памяти первоначально выбранное при его создании изображение, состоящее из одного монохромного пиксела, и затем удаляет контекст памяти:
В качестве кода растровой операции используется константа SRCCOPY. При этом цвет пикселов копируемого изображения полностью замещает цвет соответствующих пикселов контекста отображения.
Мы уже говорили об использовании растровых операций для рисования линий и закрашивания областей. При рисовании битовых изображений вы также можете использовать растровые операции, причем цвет полученного изображения в зависимости от выбранной растровой операции может определяться цветом исходного изображения, цветом поверхности, на которой выполняется рисование, и цветом кисти, выбранной в контекст отображения.
Чаще всего используется код растровой операции SRCCOPY. В этом случае цвет кисти, выбранной в контекст отображения, не имеет значения, так как ни цвет кисти, ни цвет фона не влияют на цвет нарисованного изображения.
Однако вы можете использовать и другие коды растровых операций (всего их 256). В этом случае для вычисления цвета полученного после рисования пиксела можно выбрать практически любое логическое выражение, учитывающее цвет фона, цвет кисти и цвет пиксела изображения.
В файле windows.h описаны константы для наиболее полезных кодов растровых операций. Мы опишем эти константы вместе с соответствующими логическими выражениями. При этом символом S мы будем обозначать цвет исходного изображения, символом D — цвет фона на котором выполняется рисование, и P — цвет кисти, выбранной в контекст отображения.
Код растровой операции | Логическое выражение | Описание |
SRCCOPY | S | Исходное изображение копируется в контекст отображения |
SRCPAINT | S | D | Цвет полученного изображения определяется при помощи логической операции ИЛИ над цветом изображения и цветом фона |
SRCAND | S & D | Цвет полученного изображения определяется при помощи логической операции И над цветом изображения и цветом фона |
SRCINVERT | S ^ D | Цвет полученного изображения определяется при помощи логической операции ИСКЛЮЧАЮЩЕЕ ИЛИ над цветом изображения и цветом фона |
SRCERASE | S &
D |
Цвет фона инвертируется, затем выполняется операция И над результатом и цветом исходного изображения |
NOTSRCCOPY | После рисования цвет изображения получается инвертированием цвета исходного изображения | |
NOTSRCERASE | Цвет полученного изображения получается инвертированием результата логической операции ИЛИ над цветом изображения и цветом фона | |
MERGECOPY | P & S | Выполняется логическая операции И над цветом исходного изображения и цветом кисти |
MERGEPAINT | Выполняется логическая операции ИЛИ над инвертированным цветом исходного изображения и цветом фона | |
PATCOPY | P | Выполняется копирование цвета кисти |
PATPAINT | P |
S | D |
Цвет кисти комбинируется с инвертированным цветом исходного изображения, при этом используется логическая операция ИЛИ. Полученный результат комбинируется с цветом фона, также с помощью логической операции ИЛИ |
PATINVERT | P ^ D | Цвет полученного изображения определяется при помощи логической операции ИСКЛЮЧАЮЩЕЕ ИЛИ над цветом кисти и цветом фона |
DSTINVERT | Инвертируется цвет фона | |
BLACKNESS | Область закрашивается черным цветом | |
WHITENESS | 1 | Область закрашивается белым цветом |
Остальные коды приведены в документации, которая поставляется вместе с SDK. В более удобном виде все коды растровых операций приведены в приложении к книге «Developing Windows 3.1 Application whit Microsoft C/C++» (автором которой является Brent Rector). Мы не будем воспроизводить полную таблицу для кодов растровых операций, так как во-первых, эти операции редко используются, а во-вторых, таблица занимает много места.
Для рисования битовых изображений можно использовать вместо функции BitBlt функцию StretchBlt , с помощью которой можно выполнить масштабирование (сжатие или растяжение) битовых изображений:
Параметры этой функции аналогичны параметрам функции BitBlt, за исключением того, что ширина и высота исходного и полученного изображения должна определяться отдельно. Размеры исходного изображения (логические) задаются параметрами nWidthSrc и nHeightSrc, размеры нарисованного изображения задаются параметрами nWidthDest и nHeightDest.
Возвращаемое значение равно TRUE при успешном завершении или FALSE при ошибке.
Следует упомянуть также еще одну функцию, которая сама по себе не может рисовать битовые изображения, но часто используется для закраски прямоугольных областей экрана. Эта функция имеет имя PatBlt :
При использовании этой функции вы можете закрашивать области экрана с использованием следующих кодов растровых операций: PATCOPY, PATINVERT, PATPAINT, DSTINVERT, BLACKNESS, WHITENESS.
Возвращаемое функцией PatBlt значение равно TRUE при успешном завершении или FALSE при ошибке.
Создание изображений в памяти
Другой способ работы с изображениями в формате DDB заключается в создании их непосредственно в оперативной памяти.
Вы должны подготовить массив, содержащий биты изображения, заполнить структуру типа BITMAP, которая описывает изображение, и затем вызвать функцию CreateBitmapIndirect , указав ей в качестве единственного параметра указатель lpbm на заполненную структуру типа BITMAP:
Функция вернет идентификатор битового изображения, который вы можете использовать обычным способом.
Как правило, в памяти создаются монохромные изображения небольших размеров. В этом случае структура битов изображения является достаточно простой.
Например, пусть нам надо нарисовать битовое изображение, показанное в увеличенном виде на рис. 4.2.
Рис. 4.2. Битовое изображение
Подготовим в памяти массив, описывающий это изображение. Каждая строка массива соответствует одной строке сканирования битового изображения:
При этом нам необходимо принимать во внимание, что размер одной строки сканирования изображения должен быть кратен 16 битам, т. е. двум байтам.
Однако сам по себе приведенный выше массив бит не содержит информации о размере изображения или о количестве бит, обозначающих цвет одного пиксела. Для формирования битового изображения необходимо подготовить структуру типа BITMAP, содержащую все необходимые сведения:
В этом массиве указаны размеры изображения (ширина — 64 пиксела, высота — 9 пикселов), размер памяти для одной строки сканирования в байтах (равен 8), количество цветовых плоскостей (одна) и количество бит, используемых для представления цвета одного пиксела (один бит). Указатель на массив бит будет проинициализирован непосредственно перед созданием изображения, так как сегмент данных может переместиться.
После того как массив данных и структура подготовлены, можно вызывать функцию CreateBitmapIndirect, передав ей в качестве параметра указатель на структуру:
Непосредственно перед вызовом функции CreateBitmapIndirect следует установить в структуре типа BITMAP указатель на массив бит изображения.
Есть еще одна возможность. Вы можете создать битовое изображение, вызвав функцию CreateBitmap :
Через параметры этой функции передаются значения, которые необходимо записать в структуру типа BITMAP перед вызовом функции CreateBitmapIndirect.
Функции CreateBitmap и CreateBitmapIndirect возвращают идентификатор созданного в памяти изображения, который можно использовать для выбора изображения в контекст памяти, или NULL при ошибке.
Другие функции для работы с изображениями DDB
Если вы создали изображение DDB, то пользуясь его идентификатором, нетрудно скопировать в него новый массив бит, соответствующий новому изображению. Для этой цели можно воспользоваться функцией SetBitmapBits :
Первый параметр этой функции предназначен для передачи идентификатора битового изображения. Параметр lpvBits является указателем на массив бит, размер этого массива задается при помощи параметра cBits.
При успешном выполнении функция возвращает количество байт, использованных для изменения изображения. Если произошла ошибка, возвращается нулевое значение.
Обратную операцию (чтение массива памяти изображения) можно выполнить при помощи функции GetBitmapBits :
Эта функция копирует байты изображения hbmp в массив lpvBits, причем размер массива указывается через параметр cbBuffer.
Функция возвращает количество скопированных в буфер байт в случае нормального завершения или нулевое значение при ошибке.
Если вам нужно создать цветное битовое изображение DDB, можно воспользоваться функцией CreateCompatibleBitmap :
Эта функция создает неинициализированное изображение шириной nWidth пикселов и высотой nHeight пикселов, причем формат изображения соответствует контексту отображения hdc.
Ваше приложение может выбрать неинициализированное изображение, созданное при помощи функции CreateCompatibleBitmap, в контекст памяти (совместимый с тем же контекстом отображения). Затем оно может нарисовать в контексте памяти все что угодно, используя обычные функции GDI, такие как LineTo (передавая им в качестве первого параметра идентификатор контекста памяти). После этого приложение может вызвать функцию BitBlt для отображения результата в окне приложения.
Если желательно создать удаляемое (discardable) битовое изображение, вместо предыдущей функции вы можете вызвать функцию CreateDiscardableBitmap :
Она имеет параметры, аналогичные параметрам функции CreateCompatibleBitmap. Если изображение, созданное с использованием этой функции, не выбрано в контекст памяти, оно может быть удалено. При попытке выбрать в контекст удаленное изображение функция SelectBitmap вернет нулевое значение. В этом случае необходимо удалить изображение макрокомандой DeleteBitmap, после чего создать его заново.
StretchBlt Shrink Corruption
I’m using Windows (both 7 & XP — both 32bit) and coding in C++
I am receiving bitmaps from an external source. These bitmaps are of a fixed resolution (384×288)
After I receive a bitmap, I need to resize it based on a variable sized layout, so I’m currently using StretchBlt to perform these tasks.
If I resize the bitmap to a larger on screen image, this works great.
However, if I shrink the incoming bitmap to a smaller version to place on the screen I get some strange ‘boxing’ type effect that occurs over the image.
In the following example, the source image is the same for each of the three panels. But the left hand two (resize smaller) both have the boxing/lines effect on them.
For the actual StretchBlt call, I’m doing this:
But I’m wondering if perhaps the issue is elsewhere.
Has anyone else had experience of this kind of resizing image corruption that knows how I can fix it?
Сбой StretchBlt при печати
У меня есть диаграмма (в растровом формате), которую я пытаюсь сделать на принтере, используя StretchBlt . При рисовании на экран, StretchBlt работает отлично. При рисовании на принтер CutePDF, он возвращает 0, устанавливает последнюю ошибку в ERROR_INVALID_HANDLE , и работает в любом случае. При рисовании на принтере PDF995 или физическом принтере HP он возвращает 0, устанавливает последнюю ошибку в ERROR_INVALID_HANDLE , и не может ничего нарисовать.
Что вызвало бы StretchBlt потерпеть неудачу для определенных устройств? Я проверил, что исходное растровое изображение является DIB и что назначение поддерживает StretchBlt позвонив по телефону GetDeviceCaps .
Вот мой код, на случай, если он уместен: (Он написан на C++ Builder, поэтому он использует VCL Delphi; TCanvas оборачивает HDC, а TBitmap — HBITMAP. VCL предоставляет свой собственный StretchDraw функция, которая не поддерживает HALFTONE; У меня такие же проблемы с этим.)
1 ответ
Возможно, для Вашего проекта будут необходимы бесплатные векторные карты. На нашем сайте представлены карты для всех стран.