Type de fichier bmp quoi. Format de fichier BMP : description de l'extension. Informations complémentaires sur le format BMP

Le format de fichier BMP est une image raster et est très populaire. Il est bien « compris » par n’importe quel système d’exploitation Windows.

L'ouverture d'un fichier avec l'extension bmp sur votre ordinateur devrait se faire automatiquement - double-cliquez simplement dessus avec le bouton gauche de la souris.

Si cela ne se produit pas pour vous, il est fort probable que l'association du fichier soit rompue, le système doit alors spécifier manuellement avec quoi l'ouvrir.

Pour ce faire, faites un clic droit sur votre fichier bmp, déplacez le curseur sur la ligne « ouvrir avec » et sélectionnez n'importe quel programme (s'il est installé) de votre choix, par exemple Paint.

Quel programme pour ouvrir l'extension bmp

Le moyen le plus simple d'ouvrir le format BMP consiste à utiliser le programme d'album photo Windows. Il n'est pas nécessaire de le télécharger : il est fourni avec le système d'exploitation, c'est-à-dire que tout le monde devrait l'avoir.

Le deuxième programme est « Paint ». Il n'est pas non plus nécessaire de le télécharger - il est intégré par défaut à Windows, de plus, vous pouvez non seulement modifier l'extension bmp, mais également, après ouverture, l'enregistrer dans un autre format, par exemple jpg - pour le visualiser sur votre téléphone .

Le troisième programme est « PhotoScape ». Vous devrez le télécharger. C'est gratuit, en russe et avec son aide, en plus de la visualisation, vous pouvez traiter des images BMP.

La quatrième application Paint.NET. Il est également gratuit, possède une interface russe, est pratique et très simple à utiliser, avec de nombreux outils pour ajuster et éditer des images et des photos - c'est comme un substitut au "Paint" standard

Cinquième programme "GIMP". C'est comparé à Photoshop. Il s'agit d'un éditeur graphique gratuit à usage professionnel qui possède toutes les fonctions nécessaires et se caractérise par sa simplicité.

Les programmes fournis ci-dessus qui ouvrent des fichiers dans ce format ne sont pas tous. Il en existe des dizaines, mais ceux-ci sont largement suffisants pour l'utilisateur moyen d'un ordinateur. Bonne chance.

BMP est un format d'image populaire sans compression de données. Voyons quels programmes vous pouvez utiliser pour afficher des images avec cette extension.

Beaucoup ont probablement déjà deviné que puisque le format BMP est utilisé pour afficher des images, vous pouvez visualiser le contenu de ces fichiers à l'aide de visionneuses d'images et d'éditeurs graphiques. De plus, certaines autres applications, telles que les navigateurs et les visionneuses universelles, peuvent gérer cette tâche. Ensuite, nous examinerons l'algorithme d'ouverture des fichiers BMP à l'aide d'un logiciel spécifique.

Méthode 1 : Visionneuse d’images FastStone

Commençons par la visionneuse d'images populaire FastStone Viewer.


Méthode 2 : IrfanView

Examinons maintenant le processus d'ouverture d'un BMP dans une autre visionneuse d'images populaire IrfanView.


Méthode 3 : XnView

La prochaine visionneuse d'images dans laquelle nous examinerons l'ouverture d'un fichier BMP est XnView.


Méthode 4 : Adobe Photoshop

Passons maintenant à la description de l'algorithme d'actions permettant de résoudre le problème décrit dans les éditeurs graphiques, en commençant par l'application populaire Photoshop.


Le principal inconvénient de cette méthode est que l’application Photoshop est payante.

Méthode 5 : Gimp

Un autre éditeur graphique capable d'afficher du BMP est Gimp.


Par rapport à la méthode précédente, celle-ci bénéficie du fait que l’application Gimp ne nécessite aucun paiement pour son utilisation.

Méthode 6 : OpenOffice

L'éditeur graphique Draw, inclus dans le package gratuit OpenOffice, s'acquitte également avec succès de cette tâche.


Méthode 7 : Google Chrome

Non seulement les éditeurs graphiques et les visualiseurs d'images peuvent ouvrir BMP, mais également un certain nombre de navigateurs, par exemple Google Chrome.


Méthode 8 : Visionneuse universelle

Un autre groupe de programmes pouvant fonctionner avec BMP sont les visionneuses universelles, qui incluent l'application Universal Viewer.


Méthode 9 : Peindre

Les méthodes d'ouverture de BMP à l'aide de programmes tiers installés ont été répertoriées ci-dessus, mais Windows possède son propre éditeur graphique - Paint.


Méthode 10 : Visionneuse de photos Windows

Windows dispose également d'une visionneuse d'images intégrée qui peut être utilisée pour lancer BMP. Voyons comment procéder en utilisant Windows 7 comme exemple.


Comme vous pouvez le constater, il existe une liste assez longue de programmes capables d'ouvrir des images BMP. Et ce ne sont pas tous, mais seulement les plus populaires. Le choix d’une application spécifique dépend des préférences personnelles de l’utilisateur, ainsi que des objectifs fixés. Si vous avez simplement besoin de regarder un dessin ou une photo, il est préférable d'utiliser des visionneuses d'images et, pour l'édition, d'utiliser des éditeurs d'images. De plus, même les navigateurs peuvent être utilisés comme alternative à la visualisation. Si l'utilisateur ne souhaite pas installer de logiciel supplémentaire sur l'ordinateur pour travailler avec BMP, il peut utiliser le logiciel Windows intégré pour afficher et éditer des images.

Un petit programme a été envisagé pour déplacer le sprite sur l'écran, mais, malheureusement, il ne ressemblait pas à ce que nous souhaiterions. Dans cet article, nous allons essayer de « ranger » le sprite.

Nous avons obtenu l'image du sprite à partir d'un fichier Bmp ; à partir des mêmes fichiers, nous pouvons prendre l'image de l'arrière-plan, du curseur de la souris et des éléments de l'interface. Cependant, ce que nous voyons sur l'écran n'est pas exactement ce à quoi nous nous attendions : l'image s'avère être à l'envers et, en plus, avec des couleurs différentes de celles requises. Apprenons donc à lire correctement les fichiers Bmp et à transformer l’image « de la tête aux pieds ».

Par décision des développeurs, le format de fichier Bmp n'est pas lié à une plate-forme matérielle spécifique. Ce fichier se compose de quatre parties : un en-tête, un en-tête d'informations, une table de couleurs (palette) et des données d'image. Si le fichier stocke une image avec une profondeur de couleur de 24 bits (16 millions de couleurs), alors la table des couleurs peut être manquante, mais dans notre cas de 256 couleurs, elle est là. La structure de chaque partie d'un fichier stockant une image de 256 couleurs est donnée dans , et les types d'enregistrement correspondants sont donnés dans .

L'en-tête du fichier commence par signature"BM" suivi de la longueur du fichier, exprimée en octets. Les 4 octets suivants sont réservés à d'autres extensions de format, et cet en-tête se termine déplacement depuis le début du fichier jusqu'aux données d'image qui y sont enregistrées. Avec 256 couleurs, ce décalage est de 1078 - c'est exactement ce que nous avons dû sauter dans notre programme précédent pour accéder aux données.

L'en-tête d'information commence par sa propre longueur (celle-ci peut varier, mais pour un fichier de 256 couleurs, elle est de 40 octets) et contient les dimensions de l'image, la résolution, les caractéristiques de présentation des couleurs et d'autres paramètres.

Largeur et hauteur de l'image sont spécifiés aux points raster et ne nécessitent probablement pas d'explication.

Nombre d'avions pourrait être utilisé dans des fichiers avec une faible profondeur de couleur. Lorsque le nombre de couleurs est de 256 ou plus, il est toujours égal à 1, ce champ peut donc désormais être considéré comme obsolète, mais pour des raisons de compatibilité il est conservé.

La profondeur de la couleur est considérée comme la caractéristique la plus importante de la façon dont la couleur est représentée dans un fichier et est mesurée en bits par point. Dans ce cas, il est égal à 8.

Compression. Il n'est généralement pas utilisé dans les fichiers Bmp, mais un champ dans l'en-tête est prévu à cet effet. Généralement, il s'agit de 0, ce qui signifie que l'image n'est pas compressée. À l'avenir, nous n'utiliserons que de tels fichiers.

Taille de l'image- le nombre d'octets de mémoire nécessaire pour stocker cette image, sans compter les données de la palette.

Résolutions horizontales et verticales mesuré en points raster par mètre. Ils sont particulièrement importants pour conserver l’échelle des images numérisées. Les images créées à l'aide d'éditeurs graphiques comportent généralement des zéros dans ces champs.

Nombre de couleurs vous permet de réduire la taille de la table de la palette si l'image contient en réalité moins de couleurs que ne le permet la profondeur de couleur sélectionnée. Cependant, dans la pratique, de tels fichiers ne sont presque jamais trouvés. Si le nombre de couleurs est le maximum autorisé par la profondeur de couleur, par exemple 256 couleurs sur 8 bits, le champ est mis à zéro.

Nombre de couleurs primaires- vient du début de la palette, et il convient de l'afficher sans distorsion. Ce champ est important lorsque le nombre maximum de couleurs d'affichage est inférieur à celui de la palette du fichier Bmp. Lors de l'élaboration du format, il a évidemment été supposé que les couleurs les plus fréquentes se trouveraient au début du tableau. Or, cette exigence n'est pratiquement pas respectée, c'est-à-dire que les couleurs ne sont pas classées selon la fréquence à laquelle elles apparaissent dans le fichier. Ceci est très important, car les palettes de deux fichiers différents, même composées des mêmes couleurs, les contiendraient (les couleurs) dans un ordre différent, ce qui pourrait considérablement compliquer l'affichage simultané de telles images à l'écran.

L'en-tête d'information est suivi d'une table de couleurs, qui est un tableau de 256 (en nombre de couleurs) champs de 4 octets. Chaque champ correspond à une couleur de la palette et trois des quatre octets correspondent aux composants bleu, vert et rouge de cette couleur. Le dernier octet de poids fort de chaque champ est réservé et égal à 0.

Après la table des couleurs se trouvent les données d'image, qui sont écrites le long des lignes raster de bas en haut et à l'intérieur de la ligne - de gauche à droite. Étant donné que sur certaines plates-formes, il est impossible de lire une unité de données inférieure à 4 octets, la longueur de chaque ligne est alignée sur une limite de 4 octets, c'est-à-dire que si la longueur de la ligne n'est pas un multiple de quatre, elle est complétée par des zéros. Cette circonstance doit être prise en compte lors de la lecture du fichier, même s'il peut être préférable de s'assurer au préalable que les dimensions horizontales de toutes les images sont un multiple de 4.

Comme nous l'avons déjà dit, le format de fichier a été conçu pour être universel pour diverses plates-formes, il n'est donc pas surprenant que les couleurs de la palette y soient stockées différemment de ce qui est habituel pour le VGA. Pendant la procédure de lecture, le recodage nécessaire est effectué. (Nous parlerons de ce qu'est la palette VGA et de la manière de l'utiliser dans les articles suivants.)

Le module de lecture des fichiers Bmp 256 couleurs ne comporte que deux procédures. Comme le montre la liste, les dimensions de l'image doivent être transmises à la procédure de lecture du fichier ReadBMP. C'est pratique si l'image n'a pas besoin d'être lue complètement. Lorsque les tailles sont connues à l'avance, cela ne pose pas de problèmes, mais ce serait bien si, grâce à notre module, il était possible de lire n'importe quelle image, y compris celles dont la taille est inconnue à l'avance. A cet effet, la procédure ReadBMPheader est fournie, qui lit uniquement l'en-tête du fichier. En l'appelant, vous pouvez vérifier si l'image est enregistrée dans le format 256 couleurs sélectionné, connaître ses dimensions, puis lui allouer de la mémoire et la placer dans le tampon alloué.

Connectons maintenant un nouveau module à notre programme. Pour ce faire, nous écrirons son nom dans la directive using, et fournirons également un tableau pour stocker les données sur la palette, qui peut être décrit comme ceci :

P : tableau d’octets ;

La procédure CreateSprite, qui invoque l'opération de lecture d'un fichier depuis un nouveau module, a été simplifiée (voir).

Structure du fichier BMP

Nom Longueur Biais Description
En-tête de fichier (BitMapFileHeader)
Taper2 0 Signature "BM"
Taille4 2 taille du fichier
Réservé 12 6 Réservé
Réservé 22 8 Réservé
Bits de décalage4 10 Décalage de l'image par rapport au début du fichier
En-tête d'informations (BitMapInfoHeader)
Taille4 14 Longueur de l'en-tête
Largeur4 18 Largeur de l'image, points
Hauteur4 22 Hauteur de l'image, points
Avions2 26 Nombre d'avions
Nombre de bits2 28 Profondeur de couleur, bits par point
Compression4 30 Type de compression (0 - image non compressée)
TailleImage4 34 Taille de l'image, octets
XpelsParMètre4 38 Résolution horizontale, points par mètre
YpelsParMètre4 42 Résolution verticale, points par mètre
Couleursutilisées4 46 Nombre de couleurs utilisées (0 est le maximum possible pour une profondeur de couleur donnée)
CouleursImportant4 50 Nombre de couleurs primaires
Table de couleurs (palette)
Table des couleurs1024 54 256 éléments de 4 octets
Données d'image (tableau BitMap)
ImageTaille1078 Image enregistrée en lignes de gauche à droite et de bas en haut

Liste 1

unité bmpread; (procédures pour travailler avec Bmp) type d'interface artype = arrayof byte; arptr = ^artype; bmFileHeader = enregistrement (en-tête de fichier) Typf : mot ; (signature ) Taille : entier long ; (longueur du fichier en octets) Res1 : mot ; (réservé) Res2 : mot ; (réservé) OfBm : entier long ; (décalage d'image en octets (1078)) fin ; bmInfoHeader = enregistrement (en-tête d'informations) Taille : longint ; (longueur de l'en-tête en octets (40)) Largeur : entier long ; (largeur de l'image (en pixels)) Heig : entier long ; (hauteur de l'image (en pixels)) Plan : mot ; (nombre de plans (1)) BitC : mot ; (profondeur de couleur (bits par point) (8)) Comp : entier long ; (type de compression (0 - non)) SizI : entier long ; (taille de l'image en octets) XppM : entier long ; (résolution horizontale) ((points par mètre - généralement 0)) YppM : entier long ; (résolution verticale) ((points par mètre - généralement 0)) NCoL : entier long ; (nombre de couleurs) ((si le maximum autorisé est 0)) NCoI : longint ; (nombre de couleurs primaires) fin ; bmHeader = enregistrement (en-tête de fichier complet) f : bmFileHeader ; (en-tête du fichier) i : bmInfoHeader ; (en-tête d'information) p : tableau d'octets ; (table à palettes) fin ; bmhptr = ^bmEn-Tête; (lecture d'une image à partir d'un fichier Bmp) procédure ReadBMP(image:arptr; (tableau avec image) xim,yim:word; (dimensions) pal:arptr; (palette) filename:string); (nom du fichier) (lecture de l'en-tête du fichier Bmp) procédure ReadBMPheader(header:bmhptr;filename:string); implémentation ($R-) (lecture d'une image à partir d'un fichier Bmp) procédure ReadBMP(image:arptr; xim,yim:word; pal:arptr; filename:string); var h : bmEn-tête ; je:entier; fichier bmp : fichier ; s : entier long ; commencer assign (fichier bmp, nom de fichier); réinitialiser (fichier bmp, 1); blockread(bmpfile,h,sizeof(h)); (lire l'en-tête) pour i:= 0 à yim-1 do start (lire ligne par ligne) blockread(bmpfile,image^[(yim-i-1)*xim],xim); si (xim mod 4)<>0 puis blockread(bmpfile,s,4 - (xim mod 4)); fin; fermer (fichier bmp); pour i ^= 0 à 255, commencez (transformation de palette) pal^ := h.p shr 2 ; (bleu) pal^ := h.p shr 2 ; (vert) pal^ := h.p shr 2 ; (rouge) fin ; fin; (lecture de l'en-tête d'un fichier Bmp) procédure ReadBMPheader(header:bmhptr;filename:string); var fichierbmp:fichier; commencer assign (fichier bmp, nom de fichier); réinitialiser (fichier bmp, 1); blockread (fichier bmp, en-tête ^, taille de (en-tête ^)); fermer (fichier bmp); fin; fin.

Liste 2

(sprite) procédure CreateSprite(s:string; x,y,dx,dy:integer); var f : fichier ; (fichier avec image sprite) start getmem(Sprt.Img,sizeof(SpriteArrayType)); (allouer de la mémoire au sprite) getmem(Sprt.Back,sizeof(SpriteArrayType)); (allouer de la mémoire pour le tampon) Readbmp (@(Sprt.Img^),Xsize,Ysize,@p,s); Sprt.x:= x; Sprt.y:=y; (définir les valeurs initiales) Sprt.dx:= dx; (coordonnées et incréments) Sprt.dy:= dy; fin;

Cet article explique à quoi ressemble le format graphique bmp. Bien qu’il s’agisse de l’un des formats les plus simples, tous les points ne sont pas évidents en raison du fait qu’il existe de nombreuses variantes de ce format. Alors arrêtez de verser de l’eau, commençons.

Formater les structures

Le format bmp (des mots BitMaP - bit map ou, en russe, bit array) est une image non compressée (principalement) qui est assez facile à lire et à afficher dans le système d'exploitation Windows, qui possède des fonctions API spéciales qui aident.

Tout d'abord, donnons une représentation graphique des données en bmp (image tirée de MSDN).

Au début il y a un en-tête de fichier (BITMAPFILEHEADER). Il est décrit comme suit :

bfType détermine le type de fichier. Ici, il devrait être BM. Si vous ouvrez un fichier BMP dans un éditeur de texte (ou mieux encore, dans un éditeur hexadécimal), vous verrez que les deux premiers caractères sont BM (du mot BitMap, comme vous l'avez probablement déjà deviné).
bfTaille est la taille du fichier lui-même en octets. À proprement parler, vous devriez le calculer (ce qui est recommandé), mais j'ai mal défini la taille du fichier (mais pas volontairement :)) et il n'y a eu aucun problème (ACDSee a lu sans problème, mon programme a fonctionné), mais je ne vous recommande pas écrivez-le délibérément de manière incorrecte , tout à coup un programme consciencieux apparaîtra qui comparera cette taille avec la vraie et décidera que ce n'est pas du bmp, mais autre chose. Idéalement, tous les programmes, afin de s'assurer qu'il s'agit d'un vrai bmp et non d'un faux, devraient, d'une part, vérifier que bfType contient "BM" (sans guillemets), et, d'autre part, que bfSize est égal à la taille du fichier.
bfReserved1 et bfReserved2 sont réservés et doivent être nuls.
bfOffBits. C'est l'un des domaines les plus importants de cette structure. Il montre où commence le bitmap lui-même par rapport au début du fichier (ou, comme le dit MSDN, "à partir du début de la structure BITMAPFILEHEADER"), qui décrit l'image. Autrement dit, pour être sûr d'arriver au début du tableau, vous devez écrire :

typedef struct tagBITMAPINFOHEADER
{
DWORD biTaille ;
Bilargeur LONGUE ;
LONG biHauteur ;
Biplans WORD ;
MOT biBitCount ;
BiCompression DWORD ;
DWORD biTailleImage ;
LONG biXPelsPerMeter ;
BiYPelsPerMètre LONG ;
DWORD biClrUtilisé ;
DWORD biClrImportant ;
) BITMAPINFOHEADER, * PBITMAPINFOHEADER ;

biTaille est la taille de la structure elle-même. Il doit être initialisé comme suit : bih.biSize = sizeof(BITMAPINFOHEADER);
Ici encore nous supposerons que bih est déclaré comme suit : BITMAPINFOHEADER bih;
biLargeur et biHauteur définissez respectivement la largeur et la hauteur de l'image en pixels.
biplans précise le nombre d'avions. Pour l'instant, il est toujours réglé sur 1.
biBitCount- Nombre de bits par pixel. Nous en parlerons davantage ci-dessous.
biCompression indique le type de compression. Ne soyez pas surpris ou effrayé que bmp subisse soudainement une compression. Personnellement, je n'ai pas vu plus d'un bmp compressé (mais je ne dis pas qu'ils n'existent pas). S'il n'y a pas de compression, cet indicateur doit être défini sur BI_RGB. Dans cet article, nous parlons du format non compressé, je ne listerai donc même pas d’autres indicateurs. Il semble que la même structure soit utilisée dans les fichiers JPEG et PNG, car à partir de Windows 98 sont apparues les options BI_JPEG, qui montrent que cette image est JPEG et BI_PNG, qu'elle est PNG (je ne connais rien au format Jpeg, Je viens de tirer ces conclusions sur la base de ce qui est écrit dans MSDN).
biTailleImage indique la taille de l'image en octets. Si l'image n'est pas compressée (c'est-à-dire que le champ précédent est défini sur BI_RGB), alors un zéro doit être écrit ici. biXPelsParMètre Et biYPelsParMètre désignent respectivement la résolution horizontale et verticale (en pixels par mètre) du périphérique final sur lequel le bitmap (raster) sera généré. Une application peut utiliser cette valeur pour sélectionner parmi un groupe de ressources le bitmap le plus approprié pour le périphérique souhaité. Le fait est que le format BMP est essentiellement un raster indépendant du matériel, c'est-à-dire lorsque l'apparence de ce qui est obtenu ne dépend pas de ce sur quoi ce raster est projeté (pour ainsi dire). Par exemple, une image aura la même apparence, qu’elle soit dessinée sur un écran de contrôle ou imprimée sur une imprimante. Mais la résolution des appareils est différente, et c'est précisément pour sélectionner l'image la plus adaptée parmi celles disponibles que ces paramètres sont utilisés.
biClrUtilisé détermine le nombre de couleurs utilisées à partir du tableau. Si cette valeur est zéro, le raster utilise le nombre maximum de couleurs autorisé par la valeur biBitCount. Ceci ne concerne que les images compressées. Si biClrUsed est différent de zéro et biBitCount est inférieur à 16, alors biClrUsed détermine le nombre actuel de couleurs de moteur graphique ou de pilote de périphérique disponibles. Si biBitCount est supérieur ou égal à 16, alors biClrUsed détermine la taille de la table de couleurs utilisée pour optimiser la palette système actuelle.
biClrImportant- c'est le nombre de couleurs importantes. Détermine le nombre de couleurs nécessaires pour représenter le dessin. Si cette valeur est 0 (comme c’est généralement le cas), alors toutes les couleurs sont considérées comme importantes.

Types de formats BMP

Tous types de format bmp conditionnellement peut être divisé en deux types : palette et non-palette. Autrement dit, si la palette est utilisée ou non dans un format donné. Veuillez noter que la palette peut même être dans des formats sans palette, mais elle n'y est pas utilisée. Dans les bmps sans palette, la couleur est calculée directement à partir des bits qui vont dans le fichier, à partir d'un certain endroit. Et dans les palettes, chaque octet décrit un ou plusieurs pixels, et les valeurs d'octets (ou bits) sont l'index de couleur dans la palette. Pour commencer, je vais fournir un tableau qui compare les options possibles. Le type d'image (avec palette ou sans palette) dépend du nombre de bits donnés par pixel, c'est-à-dire de la valeur biBitCount de la structure BITMAPINFOHEADER.

biBitCountFormat palette ou non paletteNombre maximum de couleurs possibleRemarques 1 Palette2 Une image de palette bicolore, remarquez, pas nécessairement en noir et blanc. Si le bit raster (qui est juste en dessous) est réinitialisé (égal à 0), cela signifie que la première couleur de la palette doit être à cet endroit, et si elle est définie (égale à 1), alors la seconde. 4 Palette16 Chaque octet décrit 2 pixels. Voici un exemple tiré de MSDN. Si le premier octet de l'image est 0x1F, alors il correspond à deux pixels, la couleur du premier est la deuxième couleur de la palette (car le compte à rebours commence à zéro) et le deuxième pixel est la 16ème couleur de la palette. 8 Palette256 L'une des options les plus courantes. Mais en même temps, les plus simples. La palette occupe un kilo-octet (mais il vaut mieux ne pas compter dessus). Un octet correspond à une couleur. De plus, sa valeur est le numéro de couleur dans la palette. 16 Pas de palette2^16 ou 2^15C'est l'option la plus déroutante. Commençons par le fait qu'il est sans palette, c'est-à-dire que tous les deux octets (un mot WORD) dans le raster définissent de manière unique un pixel. Mais voici ce qui se passe : il y a 16 bits, et il y a 3 composantes de couleur (Rouge, Vert, Bleu). Mais 16 ne veut pas être divisé par 3. Il y a donc deux options ici. La première consiste à utiliser non pas 16, mais 15 bits, puis il y a 5 bits pour chaque composante de couleur. De cette façon, nous pouvons utiliser un maximum de 2^15 = 32768 couleurs et obtenir un triple R-G-B = 5-5-5. Mais ensuite, un tout petit peu sur 16 est gaspillé en vain. Mais il se trouve que nos yeux, parmi toutes les couleurs, perçoivent mieux le vert, nous avons donc décidé de donner ce bit à la composante verte, c'est-à-dire que nous obtenons alors le triple R-G-B = 5-6-5, et maintenant nous pouvons utiliser 2^16 = 65536 couleurs. Mais le plus désagréable, c'est que les deux options sont utilisées. MSDN suggère que pour distinguer le nombre de couleurs utilisées, remplissez le champ biClrUsed de la structure BITMAPINFOHEADER avec cette valeur. Pour sélectionner chaque composant, vous devez utiliser les masques suivants. Pour le format 5-5-5 : 0x001F pour la composante bleue, 0x03E0 pour la verte et 0x7C00 pour la rouge. Pour le format 5-6-5 : 0x001F - composants bleus, 0x07E0 - composants verts et 0xF800 rouges, respectivement. 24 Pas de palette2^24 Et c'est le format le plus simple. Ici, 3 octets définissent 3 composants de couleur. Autrement dit, un composant par octet. Nous lisons simplement la structure RGBTRIPLE et utilisons ses champs rgbtBlue, rgbtGreen, rgbtRed. Ils vont dans cet ordre. 32 Pas de palette2^32 Ici, 4 octets définissent 3 composants. Cependant, un octet n’est pas utilisé. Il peut être utilisé par exemple pour le canal alpha (transparence). Dans ce cas, il est pratique de lire le raster à l'aide des structures RGBQUAD, qui sont décrites comme suit :

Stockage des données au format BMP

Eh bien, arrivons maintenant à la partie la plus intéressante. Après les structures BITMAPFILEHEADER et BITMAPINFOHEADER vient la palette. De plus, si le format est sans palette, il se peut qu'il ne soit pas là, mais il ne faut pas compter dessus. Le fait est que lorsque je commençais tout juste à comprendre le format bmp, j'ai lu dans un livre que, soi-disant, si le format est sans palette, alors il n'a pas de palette du tout. Il y avait même deux images - diagrammes de format : une avec une palette, l'autre sans. Et à cette époque, j'écrivais un programme qui fonctionne avec diligence avec des fichiers BMP. Et j'ai dû convertir les images entrantes de 256 couleurs en 24 bits (le cas échéant) en fichiers temporaires. Et je n'ai tout simplement pas créé de palette en 24 bits (bfOffBits de la structure BITMAPFILEHEADER était égal à la somme de sizeof(BITMAPFILEHEADER) + sizeof (BITMAPINFOHEADER), et j'ai laissé les 24 bits entrants inchangés. Avec des rasters de 256 couleurs, tout fonctionnait comme il se doit, jusqu'à ce que je ne tombe pas sur une image 24 bits affichant des déchets en bas au lieu de la partie requise. Je n'ai pas immédiatement compris ce qui n'allait pas. Jusqu'à ce que je compare la taille du fichier d'origine avec celui théorique qui aurait dû être là s'il n'y avait pas de palette. La différence s'est avérée être exactement de 1 Ko (exactement 1024 octets). Il y avait une palette. Par conséquent, ne comptez jamais sur l'existence d'une palette et ne vous fiez pas à sa taille (bien que toutes les images que j'ai rencontrées avaient une taille de palette de 256 couleurs, soit 1 Ko), déplacez-vous toujours dans le fichier jusqu'au début du raster, en utilisant bfOffBits. La palette est un tableau de structures RGBQUAD se succédant. Même si toutes les couleurs ne sont pas utilisées dans la palette (mais seulement, par exemple, 16), alors souvent 256 champs sont encore alloués à la palette. Et 256 * 4 = 1024, où 4 est la taille de la structure RGBQUAD, c'est-à-dire ce même kilo-octet est obtenu.

Immédiatement après la palette vient le raster lui-même. C’est là que les choses deviennent plus confuses. Tout d'abord, les pixels sont décrits ici comme écrit dans le tableau ci-dessus, en fonction du format. Et ils peuvent eux-mêmes contenir la valeur des composants de couleur (pour ceux sans palette), ou ils peuvent être des index d'un tableau de palettes. L'image elle-même est enregistrée ligne par ligne. Deuxièmement, la situation semble inversée. C'est-à-dire que la ligne du bas est écrite en premier, puis l'avant-dernière ligne, et ainsi de suite jusqu'au sommet. Et troisièmement, comme indiqué, si la taille de la ligne raster n'est pas un multiple de 4, elle est alors complétée par 1 à 3 octets vides (zéro) afin que la longueur de la ligne soit un multiple du paragraphe. C'est la chose la plus désagréable. Le fait est que pour chaque format, vous devez ajuster ce nombre d'octets vides (même si j'aime y écrire une partie de la palette, je ne veux tout simplement pas créer de variables « zéro » supplémentaires si ces octets sont de toute façon ignorés et que personne en a besoin). Je fournis un tableau avec des formules indiquant pour quel format combien d'octets doivent être ajoutés à la fin de la ligne. Là, la variable Largeur, comme vous pouvez le deviner, signifie la largeur de l'image. Toutes ces formules ont été établies expérimentalement. Je ne donnerai un exemple que pour les formats les plus utilisés. Pour le reste, vous pouvez l'écrire vous-même.

Exemples de programmes

Vous pouvez télécharger toutes les sources, je n’écrirai pas grand-chose ici. Je vais juste donner les fonctions avec des commentaires.

Bonjour 1. Création d'une image au format bmp.
Ici, une image monochromatique est créée. Il existe trois exemples de telles fonctions : création de bmp 8, 16 et 24 bits. Je ne donnerai que pour 16 bits.

// Créons une image au format bmp 16 bits type 5-5-5, qui sera simplement monochromatique
void CreateBmp555(char * fname, couleur WORD)
{
MANIPULER hFichier ;
DWORDRW ;
int je, j;

// Déclare les structures nécessaires
BITMAPFILEHEADER bfh;
BITMAPINFOHEADER bih ;
Palette OCTET[1024] ; // Palette

// Ayons une image de 35 x 50 pixels
int Largeur = 35 ;
int Hauteur = 50 ;

memset(Palette, 0, 1024); // Dans la palette nous avons des zéros, remplissez-les
memset (&bfh, 0 , taille de (bfh) ) ;

Bfh.bfType = 0x4D42 ; // Notons qu'il s'agit de bmp "BM"
bfh.bfOffBits = taillede (bfh) + taillede (bih) + 1024 ; // La palette occupe 1 Ko, mais nous ne l'utiliserons pas
bfh.bfSize = bfh.bfOffBits +
taille de (couleur) * Largeur * Hauteur +
Hauteur * ((taille de (couleur) * Largeur) % 4 ) ; // Calcule la taille du fichier final
memset (&bih, 0 , taille de (bih) ) ;
bih.biSize = taillede(bih); // Voilà comment il est censé être
bih.biBitCount = 16 ; // 16 bits par pixel
bih.biClrUsed = 32768 ; // Nous utilisons 5-5-5
bih.biCompression = BI_RVB ; // Sans compression
bih.biHeight = Hauteur ;
bih.biWidth = Largeur ;
bih.biPlanes = 1 ; // Devrait être 1
// Et les champs restants restent 0

HFile = CreateFile(fname, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
si (hFichier == INVALID_HANDLE_VALUE)
retour ;

// Ecrit les en-têtes
WriteFile (hFile, & bfh, sizeof (bfh) , & RW, NULL ) ;
WriteFile (hFile, & bih, sizeof (bih) , & RW, NULL ) ;

// Ecrire la palette
WriteFile(hFichier, Palette, 1024, &RW, NULL);
pour (je = 0 ; je< Height; i++ )
{
pour (j = 0 ; j< Width; j++ )
{
WriteFile (hFile, & color, sizeof (color) , & RW, NULL ) ;
}

// Aligner avec la bordure
WriteFile (hFile, Palette, (sizeof (color) * width) % 4 , & RW, NULL ) ;
}
CloseHandle(hFichier) ;
}

couleur - couleur de l'image. La valeur de cette variable doit être renseignée selon le premier tableau. Vous pouvez par exemple visualiser l'image obtenue dans ACDSee. J'ai juste essayé de l'ouvrir dans Photoshop, mais il s'est avéré qu'il ne peut pas les lire dans ce format. Mais vous pouvez :).

Exemple 2. Conversion d'une image du format 8 bits (256 couleurs) en 24 bits.

BOOL Convert256To24 (char * fin, char * fout)
{
BITMAPFILEHEADER bfh;
BITMAPINFOHEADER bih ;
int Largeur, Hauteur ;
Palette RVBQUAD[ 256 ] ;
OCTET * inBuf ;
RVBTRIPLE * outBuf ;
POIGNÉE hIn, hOut ;
DWORDRW ;
DWORD DésactivéBits ;
int je, j;

HIn = CreateFile (fin, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL) ;
si (hIn == INVALID_HANDLE_VALUE)
retourner FAUX ;

HOut = CreateFile(fout, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
si (hOut == INVALID_HANDLE_VALUE)
{
CloseHandle(hIn);
retourner FAUX ;
}

// Lire les données
ReadFile (hIn, & bfh, sizeof (bfh) , & RW, NULL ) ;
ReadFile (hIn, & bih, sizeof (bih) , & RW, NULL ) ;
ReadFile (hIn, Palette, 256 * taille de (RGBQUAD) , & RW, NULL ) ;

// Place le pointeur au début du raster
SetFilePointer (hIn, bfh.bfOffBits, NULL, FILE_BEGIN) ;
Largeur = bih.biWidth ;
Hauteur = bih.biHauteur ;
OffBits = bfh.bfOffBits ;

// Allouer de la mémoire
inBuf = new BYTE [Largeur] ;
outBuf = nouveau RGBTRIPLE [Largeur] ;

// Remplir les en-têtes
bfh.bfOffBits = taillede (bfh) + taillede (bih) ; // N'écrivons pas de palette
bih.biBitCount = 24 ;
bfh.bfSize = bfh.bfOffBits + 4 * Largeur * Hauteur + Hauteur * (Largeur % 4 ) ; // Taille du fichier

// Et le reste reste inchangé
// Ecrit les en-têtes
WriteFile (hOut, & bfh, sizeof (bfh) , & RW, NULL ) ;
WriteFile (hOut, & bih, sizeof (bih) , & RW, NULL ) ;

// Commençons la conversion
pour (je = 0 ; je< Height; i++ )
{
ReadFile (hIn, inBuf, Largeur et RW, NULL ) ;
pour (j = 0 ; j< Width; j++ )
{
outBuf[ j].rgbtRed = Palette[ inBuf[ j] ] .rgbRed ;
outBuf[ j].rgbtGreen = Palette[ inBuf[ j] ] .rgbGreen ;
outBuf[ j].rgbtBlue = Palette[ inBuf[ j] ] .rgbBlue ;
}
WriteFile (hOut, outBuf, sizeof (RGBTRIPLE) * Largeur, & RW, NULL ) ;

// Écrit des déchets pour l'alignement
WriteFile (hOut, Palette, Largeur % 4 , & RW, NULL ) ;
SetFilePointer(hIn, (3 * Largeur) % 4, NULL, FILE_CURRENT) ;
}

supprimer inBuf ;
supprimer outBuf ;
CloseHandle(hIn);
CloseHandle(hOut);
retourner VRAI ;
}

Les noms des fichiers source et destination doivent être transmis respectivement à la fonction.

Comment masquer du texte dans une image bitmap. Malheureusement, je n'ai trouvé aucun sujet sur ce sujet et j'ai décidé de combler cette lacune. Sous la coupe, vous trouverez un moyen de masquer du texte dans un bitmap, ainsi qu'une implémentation en C#.

Formulation du problème

Masquez le texte arbitraire dans l'encodage Windows-1251 dans une image bitmap 24 bits et affichez-le sans distorsion.

Structure du fichier BMP

Tout d’abord, permettez-moi de vous rappeler ce qu’est un fichier bitmap. Je suis sûr que vous savez très bien tout cela, il sera simplement plus clair de décrire l'algorithme de masquage du texte en fonction du matériel présenté. Donc. Tout fichier bmp se compose de quatre parties :
  1. En-tête du fichier
  2. Titre de l'image (peut être manquant)
  3. Palette (peut-être manquante)
  4. L'image elle-même
L'en-tête du fichier contient des informations sur le service, notamment la profondeur de bits de l'image. D'ailleurs, la palette n'est pas utilisée pour un dessin 24 bits. Puisque nous avons clairement indiqué dans la mission que nous travaillerons uniquement avec des images 24 bits, nous pouvons idéalement vérifier la conformité de l'image d'entrée avec les exigences.
Passons maintenant à l'image elle-même. Comme vous le savez, le format bmp ne fournit pas de compression par défaut (bien qu'il existe une prise en charge de la compression utilisant l'algorithme RLE). Ainsi, chaque pixel dans notre cas est codé sur 24 bits, un octet pour chaque composante de couleur. Par conséquent, nous ne pouvons coder ni plus, ni moins, mais exactement 16777216 couleurs. Pour plus de clarté, voici une photo :

L'idée d'un algorithme de masquage de texte

Vous avez probablement déjà deviné quelle est l'idée. Le fait est que l’œil d’une personne moyenne (et non un artiste ou un photographe professionnel) distingue beaucoup moins de couleurs que ce qui est indiqué ci-dessus. Aucun livre n'apporte de réponse claire à la question de savoir combien de couleurs l'œil peut distinguer, mais le chiffre le plus élevé que j'ai rencontré est de 10 millions. Il s'ensuit que plusieurs des bits les moins significatifs sur les huit attribués à chaque composante de couleur peuvent être emprunté à nos fins égoïstes.
Quelques chiffres : par exemple, prenons et soustrayons de manière flagrante deux bits de poids faible de la composante RVB. Autrement dit, sur 24 bits, il nous en restera 18, qui peuvent coder exactement 262 144 couleurs. Prenons maintenant le texte en codage Windows-1251, dans lequel chaque caractère est représenté par 8 bits. Grâce à de simples calculs mathématiques, nous constatons que 3 caractères peuvent être stockés dans 4 pixels. Ainsi, dans une image 1024x768, où il y a 786432 pixels, vous pouvez stocker 589824 caractères. Pas mal, non ? Pour plus de clarté, je vais donner deux photos. Sur le premier se trouve l'image originale et sur le second se trouve une image dans laquelle les deux bits les moins significatifs de chaque composante de couleur sont remplis de texte. Permettez-moi de faire une réserve tout de suite : les images sont converties en png pour économiser du trafic.

Image originale:


Image contenant du texte


Si vous regardez attentivement, les couleurs semblent plus ternes sur la deuxième image. Oui c'est le cas. Mais vous et moi savons qu’il y a quelque chose qui ne va pas dans l’image présentée, et si nous ne le savions pas, nous n’aurions pas deviné qu’il y avait une sorte de texte caché dedans. À propos, cachée dans l’image se trouve la phrase « Hello World !!! =)" multiplié par 100.
C'est tout. Comme vous pouvez le constater, l’idée est extrêmement simple. D’ailleurs, la méthode présentée s’appelle LSB (merci à frol pour le conseil). Enfin, vous pouvez consulter l'implémentation en C#.

Implémentation en C#

L’implémentation présentée n’est pas éligible au prix « Perfect Code » ; elle démontre uniquement l’algorithme décrit dans la pratique. Dans ce cas, je ne recherchais pas la beauté du code, mais plutôt la clarté.