Bitmap c что это

от admin

Bitmap c что это

Выше мы обсуждали работу с объектами типа Image. Как я уже говорил в начале этой главы, пространство имен System.Drawing также включает класс Bitmap, наследуемый от Image. Все свойства Image применимы и к Bitmap. Любые операции, допустимые в отношении Image, допустимы и в отношении Bitmap. И, кроме того, класс Bitmap позволяет работать прямо с битами растрового изображения.

У класса Image нет конструкторов, а у Bitmap их 12. Следующие конструкторы загружают объект Bitmap из файла, потока или ресурса.

Конструкторы Bitmap (выборочно)

Bitmap(string strFilename)
Bitmap(string strFilename, bool bUseImageColorManagement)
Bitmap(Stream stream)
Bitmap(Stream stream, bool bUseImageColorManagement)
Bitmap(Type type, string strResource)

Первые четыре по сути дублируют статические методы FromFile и FromStream класса Image. Пятый конструктор загружает объект Bitmap из ресурсов, обычно встраиваемых в .ехе -файлы приложений. Подробнее о ресурсах мы поговорим далее в этой главе.

Далее приведен набор конструкторов, которые создают новые объекты Bitmap на основе существующих объектов Image:

Конструкторы Bitmap (выборочно)

Bitmap(Image image)
Bitmap(Image image, Size size)
Bitmap(Image image, int cx, int cy)

Хотя первый аргумент этих конструкторов определен как Image, он может быть и другим объектом Bitmap. Первый конструктор аналогичен методу Clone класса Image — он создает идентичный исходному новый объект Bitmap. Второй и третий похожи на метод GetThumbnailImage — они изменяют размер изображения. Во всех случаях новое растровое изображение наследует формат пикселов исходного изображения, а разрешение нового изображения устанавливается равным разрешению дисплея.

Последние четыре конструктора не имеют аналогов в классе Image. Они создают новые объекты Bitmap с пустыми изображениями.

Конструкторы Bitmap (выборочно)

Bitmap(int cx, int су)
Bitmap(int cx, int су, PixelFormat pf)
Bitmap(int cx, int су, Graphics grfx)
Bitmap(int cx, int cy, int cxRowBytes, PixelFormat pf, IntPtr pBytes)

Первые три инициализируют пикселы значением 0, которое в различных форматах битовых карт имеет разный смысл. В битовых RGB-картах 0 соответствует черному цвету. В ARGB-картах 0 обозначает прозрачность. Четвертый конструктор также может принимать указатель на массив байтов, инициализирующий растровое изображение.

Первый конструктор создает объект Bitmap заданного размера с форматом пикселов PixelFormat.Format32bppArgb. Это 32 бита на пиксел с альфа-каналом, определяющим прозрачность. Горизонтальное и вертикальное разрешения задаются равными разрешению дисплея. Второй конструктор позволяет указать элемент перечисления PixelFormat, если вас не устраивает формат PixelFormat.Format32bppArgb.

Третий конструктор позволяет указать объект Graphics. Независимо от того, связан указанный объект с дисплеем или принтером, и независимо от того, является ли принтер цветным, этот конструктор всегда создает объект Bitmap с форматом пикселов PixelFormat.Format32bppPArgb. Заметьте: данный формат пикселов предполагает, что значение альфа-канала уже учтено в отдельных компонентах. Самое важное следствие создания битовой карты на основе объекта Graphics — то, что свойствам HorizontalResolution и VerticalResolution объекта Bitmap задаются значения свойств DpiX и DpiY объекта Graphics. Для принтера это означает не 100, а 300, 600, 720 и больше dpi.

Например, разрешение вашего принтера — 600 dpi. Вам нужно растровое изображение, созданное на основе разрешения принтера. И зачем вам это? Затем, что при печати растрового изображения все на нем (включая текст) должно выглядеть настолько красивым и плавным, насколько позволяет разрешение принтера. Квадратное растровое изображение со стороной 2 дюйма и разрешением 600 dpi будет иметь пиксельный размер 1 200 × 1 200 пикселов и займет 5 Мб памяти. Помните, что при выводе такого растрового изображения на экран или принтер надо использовать его метрический размер! (Не волнуйтесь — скоро мы рассмотрим это на примере.)

Если вы создаете растровые изображения, разрешения которых не соответствуют ни экранному разрешению, ни разрешению принтера, можно изменить разрешение загруженного или созданного растрового изображения с помощью метода SetResolution класса Bitmap.

Методы Bitmap (выборочно)

void SetResolution(float xDpi, float yDpi)

Как нарисовать что-либо на растровом изображении? Есть три подхода.

Создать объект Graphics для данного изображения и рисовать на нем, как на обычном графическом устройстве. Об этом мы уже говорили в предыдущих разделах. Помните, что создать объект Graphics можно не для всех допустимых форматов пикселов!

Воспользоваться методами SetPixel и GetPixel класса Bitmap и задать (или получить) цвет определенных пикселов изображения.

Воспользоваться методами LockBits и UnlockBits класса Bitmap и обратиться прямо к данным битовой карты.

К сожалению, я не смогу продемонстрировать второй и третий подходы в этой книге.

Манипулируем System.Drawing.Bitmap

Класс System.Drawing.Bitmap очень полезен в инфраструктуре .NET, т.к. позволяет считывать и сохранять файлы различных графических форматов. Единственная проблема – это то, что он не очень полезен для попиксельной обработки – например если нужно перевести битмап в ч/б. Под катом – небольшой этюд на эту тему.

Допустим у нас есть два битмапа, один из которых считан из файла, а другой должен содержать ч/б конверсию:

Мы хотим чтобы targetBitmap был как sourceBitmap , только черно-белый. На самом деле, в C# делается это просто:

Это решение понятное и простое, но к сожалению жуть как неэффективное. Чтобы получить более «резвый» код, можно попробовать написать все это дело на С++. Для начала создадим структурку для хранения цветовых значений пикселя

Теперь можно написать функцию которая будет делать пиксель черно-белым:

Теперь собственно пишем саму функцию обхода:

А дальше остается только использовать ее из C#.

Это улучшило быстродействие, но мне захотелось еще большего. Я добавил директиву OpenMP перед циклом по y и получил предсказуемое ускорение в 2 раза. Дальше захотелось поэкспериментировать и попробовать применить еще и SIMD. Для этого я написал вот этот, не очень читабельный, код:

Несмотря на то, что этот код делает 4 операции умножения за раз (инструкция _mm_mul_ps ), все эти конверсии не дали никакого выигрыша по сравнению с обычными операциями – скорее наоборот, алгоритм начал работать медленнее. Вот результаты выполнения функций на картинке 360×480. Использовался 2х-ядерный MacBook с 4Гб RAM, результаты усредненные.

Работа с растровыми и векторными изображениями с использованием классов Image, Bitmap и Metafile

Класс Image — это абстрактный базовый класс, содержащий методы для работы с растровыми изображениями (точечные рисунки) и векторными рисунками (метафайлы). Классы Bitmap и Metafile наследуют у класса Image. Класс Bitmap расширяет возможности класса Image за счет дополнительных методов для загрузки, сохранения и использования растровых изображений. Класс Metafile расширяет возможности класса Image за счет дополнительных методов для записи и анализа векторных рисунков.

Типы точечных рисунков

Растровое изображение или битовый образ — это массив битов, задающих цвет для каждой точки (пикселя) в прямоугольном массиве точек. Количество битов, задающих цвет одной точки, определяет количество цветов, которые могут быть заданы для этой точки. Например, если точка представляется четырьмя битами, то для каждой такой точки можно задать один из 16 различных цветов (2^4 = 16).. В приведенной ниже таблице содержится несколько примеров того, сколько цветов можно задавать для точки, представляемой определенным количеством битов.

Количество битов на точку

Количество цветов, которые могут быть заданы для точки

Файлы, которые служат для хранения точечных рисунков, обычно включают один или более информационных блоков, содержащих такие данные, как количество битов на одну точку, количество точек в строке и количество строк в массиве. Такой файл может также содержать таблицу цветов (иногда называемую цветовой палитрой). Таблица цветов сопоставляет числа из растрового образа с определенными цветами. На приведенном ниже рисунке изображен увеличенный рисунок, его представление в виде растрового образа и соответствующая таблица цветов. Каждая точка описывается 4-битным числом, поэтому таблица цветов содержит 2^4 = 16 цветов. Каждый цвет в таблице представляется 24-битным числом: 8 бит для интенсивности красного, 8 бит для интенсивности зеленого и 8 бит для интенсивности синего. Числа отображаются в шестнадцатеричной системе счисления (системе счисления с основанием 16): A = 10, B = 11, C = 12, D = 13, E = 14, F = 15.

Look at the pixel in row 3, column 5 of the image. The corresponding number in the bitmap is 1. The color table tells us that 1 represents the color red so the pixel is red. All the entries in the top row of the bitmap are 3. The color table tells us that 3 represents blue, so all the pixels in the top row of the image are blue.

Some bitmaps are stored in bottom-up format; the numbers in the first row of the bitmap correspond to the pixels in the bottom row of the image.

A bitmap that stores indexes into a color table is called a palette-indexed bitmap. Some bitmaps have no need for a color table. For example, if a bitmap uses 24 bits per pixel, that bitmap can store the colors themselves rather than indexes into a color table. The following illustration shows a bitmap that stores colors directly (24 bits per pixel) rather than using a color table. The illustration also shows an enlarged view of the corresponding image. In the bitmap, FFFFFF represents white, FF0000 represents red, 00FF00 represents green, and 0000FF represents blue.

Обратите внимание на точку рисунка на пересечении строки 3 и столбца 5. Соответствующее ей число в растровом образе равно 1. Согласно таблице цветов, число 1 соответствует красному цвету, поэтому цвет точки — красный. Все элементы верхней строки битового образа равны 3. Согласно таблице цветов число 3 соответствует синему, поэтому все точки верхней строки изображения синие.

Читать:
Как изменить размер объекта в blender

Некоторые точечные рисунки хранятся в перевернутом формате — числам в верхней строке растрового образа соответствуют точки в нижней строке изображения.

Точечные рисунки, которые содержат ссылки на таблицу цветов, иногда называются растровыми изображениями, индексированными палитрой. Для некоторых растровых рисунков таблица цветов не нужна. Например, если в точечном рисунке каждой точке соответствует 24 бита, в такой растровый рисунок можно заносить непосредственно 24-битные представления цветов, а не номера этих цветов в таблице цветов. Приведенный ниже рисунок — это растровое изображение, в котором не используется таблица цветов и цвета указываются явным образом (каждой точке соответствует 24 бита). На приведенном ниже рисунке изображение также увеличено. В битовом образе число FFFFFF обозначает белый цвет, число FF0000 обозначает красный, число 00FF00 обозначает зеленый, а число 0000FF обозначает синий цвет.

Graphics File Formats

There are many standard formats for saving bitmaps in disk files. GDI+ supports the graphics file formats described in the following paragraphs.

BMP is a standard format used by Windows to store device-independent and application-independent images. The number of bits per pixel (1, 4, 8, 15, 24, 32, or 64) for a given BMP file is specified in a file header. BMP files with 24 bits per pixel are common. BMP files are usually not compressed and, therefore, are not well suited for transfer across the Internet.

Graphics Interchange Format (GIF)

GIF is a common format for images that appear on Web pages. GIFs work well for line drawings, pictures with blocks of solid color, and pictures with sharp boundaries between colors. GIFs are compressed, but no information is lost in the compression process; a decompressed image is exactly the same as the original. One color in a GIF can be designated as transparent, so that the image will have the background color of any Web page that displays it. A sequence of GIF images can be stored in a single file to form an animated GIF. GIFs store at most 8 bits per pixel, so they are limited to 256 colors.

Joint Photographic Experts Group (JPEG)

JPEG is a compression scheme that works well for natural scenes such as scanned photographs. Some information is lost in the compression process, but often the loss is imperceptible to the human eye. JPEGs store 24 bits per pixel, so they are capable of displaying more than 16 million colors. JPEGs do not support transparency or animation.

The level of compression in JPEG images is configurable, but higher compression levels (smaller files) result in more loss of information. A 20:1 compression ratio often produces an image that the human eye finds difficult to distinguish from the original. The following illustration shows a BMP image and two JPEG images that were compressed from that BMP image. The first JPEG has a compression ratio of 4:1 and the second JPEG has a compression ratio of about 8:1.

Using Bitmaps for Persistent Graphics in C Sharp

In the previous chapter we looked at the basics of drawing graphics in C# using the Graphics Object. In that chapter we dealt with the issue of making graphics persistent by performing all the drawing sequences in the Paint() method of a component. In this chapter we will look at using bitmaps to provide persistent graphics

Contents

Why Use Bitmaps for Graphics Persistence in C#?

In the previous chapter we explained that simply drawing graphics on a component in C# is not sufficient to ensure the graphics will remain if part or all of the window containing the graphics is obscured by another window. In such situations the application will not know to redraw the erased graphics once the obscured section of the window is uncovered. To address this problem we used the Paint() method of the component to ensure that the draw commands were executed again when the Paint() event was triggered. This approach works well for simple, pre-defined graphics but is not suitable for complex drawings or situations where different graphics are drawn each time the application runs (for example the graphics may be drawn based on interaction with the user).

To address such situations it is preferable to draw the graphics on a bitmap residing in memory which can be rendered on a component whenever the a Paint() event is triggered. This avoids the problem of having to call all the Draw methods or store and replay a complex sequence of draw commands each time the graphics need to be refreshed.

report this ad

Creating a Bitmap

The first step in this tutorial is to create a new Visual Studio Windows Form Application project named CSharpBitmap. Once the project is created, double click on the Form to display the source code. Within the class declaration for the form we need to add a Bitmap declaration called myBitmap as follows:

This bitmap will be used to store the graphics image in memory ready to be displayed to the user.

Instantiating a Bitmap and Creating a Graphics Object

Having declared a Bitmap to store our graphics we now need to instantiate it. This can be performed in the Form1_Load() method of our form so that it is executed when the form is created:

Having created a bitmap object the next step is create a Graphics Object for the bitmap so that we can draw graphics into the bitmap. This is achieved by calling the Graphics.FromImage() method, passing through the bitmap as the argument. Our Form1_Load() method should now appear as follows:

Note that it is important to dispose of the Graphics Object before we exit the method to free up resources.

Drawing onto the Bitmap

Now that we have our object we can draw onto it using the Graphics Object just as we would writing to any other graphics object (for details on drawing to a graphics object read Drawing Graphics in C#).

In this example we will create Pen and Rectangle objects and use them to draw an ellipse:

When compiled and executed the code will create the bitmap in memory, create a Graphics Object associated with the bitmap and draw an ellipse into the bitmap image. It will not, at this point, display anything to user because the bitmap is still just an image sitting in memory. The next task is to wire up the Paint() event to render the bitmap into the Graphics Object of our form.

Rendering a Bitmap Image on a Control

The next step is to write some code for the Paint() event of our form. Select the form in the Visual Studio design area and click on the lightning bolt button in the Properties dialog to display events. Double click on the Paint event to go to the code area. In the Paint() event enter the following code to draw the bitmap image onto the form:

When compiled and executed the graphics created in the bitmap image will appear in the form area:

Changing the Background Color of a Bitmap

If you followed the tutorial you will now have a plum color circle drawn on a black background. The background is black because this is the default for a new Bitmap object and we made no attempt change the color after we created the Graphics Object. Had we wanted a different background color we could have called the Clear() method of the bitmap’s Graphics Object in the Form1_Load() method, passing in a new color:

The above code will clear the bitmap prior to creation of the image and, in doing so change the color of the background to white:

Summary

A more efficient and persistent approach to displaying images in C# can be achieved by rendering images into memory in the form of a bitmap, and then displaying the bitmap in a component’s Paint() method. This avoids the necessity to repeatedly perform potentially complex and CPU intensive drawing operations each time an image needs to be rendered or refreshed. In this chapter we have worked through the steps involved in creating persistent graphics in C# through the implementation of bitmaps.

Похожие статьи