====== ugBASIC User Manual ====== ===== IMAGE MANIPULATION ===== In this section, you will learn how to master the image conversion ad manipulation. ugBASIC is equipped with a sophisticated image conversion system, which allows the use of modern formats (like JPG or PNG) which are then "translated" into a native format of the target machine. This mechanism is exposed by means of a series of primitives, which allow you to load images, to draw them on the screen and to move them. This section will limit itself to giving general indications on the functioning of these primitives. It must in fact be taken into account that ugBASIC is an isomorphic language, therefore it does not provide a real abstraction but rather exposes the mechanisms of the specific target. For this reason, it is necessary to carefully study the "form" of the graphic data, so that they can be used easily by all targets. ==== What is a buffer? ==== In order to draw an image, it is necessary to define it and, above all, to allocate space to keep the graphic and color information. This is done with the use of the ''BUFFER'' data type. This type of data is special: in fact, it represents a certain memory area, of a certain size and starting from a certain position in the memory. Defining a ''BUFFER'' is simple, because it is sufficient to use the following syntax: b = #[aa55aa55aa55aa55] The sequence of hexadecimal digits in square brackets describes the contents of the buffer ''b''. In this specific case, we are defining a memory area of 8 bytes, with an alternating pattern of ''55'' (85 decimal) and ''aa'' (170 decimal) values. ==== What is an image? ==== For the purpose of image manipulation, a specific type has been introduced: ''IMAGE''. This type of data is equivalent to a ''BUFFER'' but the content is declined according to the target and the specific graphics mode. In other words, it is possible to define an image as a buffer is defined, simply by asking ugBASIC to consider it a variable of type ''IMAGE'', and putting a content that is compatible with the target / chipset: image = (IMAGE) #[1004aa55aa55aa55aa55] Although the actual content may vary, the format assumes that the first two bytes represent the width (in pixels) and height (in pixels) (currently: 16x4 pixel), while the rest of the sequence represents the graphic content. Recall that ugBASIC is an isomorphic language, it does not code the content homogeneously. Each target has its own format, and even each individual graphics mode. It follows that it is neither easy nor advisable to manually define such information but other primitives, much more powerful and effective, must be used. ==== Loading images ==== To load an image from the development computer, you need to use the ''LOAD IMAGE'' function. This function accepts, as a parameter, the name of a file located on the development system and returns a value of type ''IMAGE'', which can then be used. airplaneImage = LOAD IMAGE("examples/air_attack_airplane.png") Note that the term "load" does not represent the action actually performed by the compiler. The compiler, in fact, will take the file, convert it into a format suitable for the boundary conditions, and store it in the data segment of the program. As a result, there is no type of access to a disk, tape or other media. Furthermore, there are obvious limitations in the size of a single image or set of images, which cannot be overcome. Loading the same image several times results in the generation of a single image buffer, without repetition. REM airplaneImage1 and airplaneImage2 are the very same buffer! airplaneImage1 = LOAD IMAGE("examples/air_attack_airplane.png") airplaneImage2 = LOAD IMAGE("examples/air_attack_airplane.png") To avoid this behavior, the ''AS'' keyword must be used. REM airplaneImage1 and airplaneImage2 are the very same buffer! airplaneImage1 = LOAD IMAGE("examples/air_attack_airplane.png" AS "airplane1") airplaneImage2 = LOAD IMAGE("examples/air_attack_airplane.png" AS "airplane2") ==== Drawing images ==== ugBASIC offers a primitive for drawing images, and it's called PUT IMAGE. PUT IMAGE airplane AT 16,16 This primitive is designed so that it can exploit, in the most efficient way possible, the graphics subsystem. For this reason, although it is possible to indicate an absolute position from which to start drawing, there is no guarantee that this position will be respected. For example, on many systems there is an alignment to the nearest 8 horizontal pixels (byte alignment), while on others this alignment may also be present vertically. In general, positioning an image at (0,0) is guaranteed to cause the image to be drawn starting from the upper left corner. ==== How to choose colors and resolution ==== We began by arguing that ugBASIC converts images according to contextual constraints. This is implemented through the evaluation of both which target is being compiled and the graphics mode in use at the moment. Both of these factors are evaluated at the time of compilation, and reaffirmed at the time of execution. In this example, we define (and, the, draw) an airplane in a bitmap monocromatic resolution: BITMAP ENABLE (2) airplaneImage = LOAD IMAGE("examples/air_attack_airplane.png") PUT IMAGE airplaneImage : REM use last graphic coordinates, normally (0,0) This implies that the loading and the conversion of the images takes place according to a graphic modality deduced from the static execution of the code, while the drawing of the graphic elements from the dynamic execution. This can be a bit confusing in those programs that use more than one graphics mode. As a general rule, the graphic elements must be defined within the chosen resolution, and therefore it is necessary to foresee a phase in which the program "explores" the modalities that it will then use, in order to define the graphic elements. Finally, remember that it is not possible to "mix" images defined for different graphic modes. In this example, we define an airplane in a bitmap monocromatic resolution and, then, in a multicolor bitmap (we use the ''AS'' keyword to avoid aliasing): BITMAP ENABLE (2) airplaneImage = LOAD IMAGE("examples/air_attack_airplane1.png" AS "airplanebw") BITMAP ENABLE (16) airplaneImage = LOAD IMAGE("examples/air_attack_airplane2.png" AS "airplanecol")