/* --------------- */ /* --- bmpNR.c --- */ /* --------------- */ // Copyright (c) 2013-2014 Lionel Lacassagne, All Rights Reserved // Laboratoire de Recherche en Informatique // Universite Paris-Sud / CNRS #include #include #include /* -- image -- */ #ifdef CLI #include "nrc_os_config.h" #include "nrtype.h" #include "nrdef.h" #include "nrmacro.h" #include "nralloc.h" #endif #include "palette.h" /* -- local -- */ #include "bmpNR.h" #define BM 0x4d42 #define BI_RGB 0L PRIVATE void ReadBMProw (int fd, long width, uint8 * row); PRIVATE void WriteBMProw (uint8 * row, long width, int fd); //PRIVATE void SetupPalette (RGBQUAD Palette[]); #if (!defined(WIN32) && !defined(_WINDOWS_) && !defined(_WINGDI_)) //#pragma message("bmpio.h no WINDOWS echo") PRIVATE void Palette_RGBQuad2RGBQUAD(RGBQuad * src, RGBQUAD dst[]); #endif /* ------------------------------------- */ uint8 *ui8ArrayAppend(uint8 *ptr, uint8 x) /* ------------------------------------- */ { *ptr++ = x; return ptr; } /* ---------------------------------------- */ uint8 *ui16ArrayAppend(uint8 *ptr, uint16 x) /* ---------------------------------------- */ { uint8 x0, x1; x0 = x & 0xFF; x = x >> 8; x1 = x & 0xFF; x = x >> 8; *ptr++ = x0; *ptr++ = x1; return ptr; } /* -------------------------------------- */ uint8 *ui32ArrayAppend(uint8 *ptr, uint32 x) /* -------------------------------------- */ { uint8 x0, x1, x2, x3; x0 = x & 0xFF; x = x >> 8; x1 = x & 0xFF; x = x >> 8; x2 = x & 0xFF; x = x >> 8; x3 = x & 0xFF; x = x >> 8; *ptr++ = x0; *ptr++ = x1; *ptr++ = x2; *ptr++ = x3; return ptr; } // Seul moyen de cache dans la librairie ces putains de types windoze // -------------------------------------------------------- PRIVATE void ReadBMProw(int fd, long width, uint8 *row) // -------------------------------------------------------- { // Le fichier est ouvert (en lecture) et ne sera pas ferme a la fin read(fd, row, sizeof(uint8) * width); } // --------------------------------------------------------- PRIVATE void WriteBMProw(uint8 *row, long width, int fd) // --------------------------------------------------------- { // Le fichier est deja ouvert et ne sera pas ferme a la fin write(fd, row, sizeof(uint8) * width); } #if (!defined(WIN32) && !defined(_WINDOWS_) && !defined(_WINGDI_)) //#pragma message("bmpio.h no WINDOWS echo") /* ----------------------------------------------------------- */ PRIVATE void Palette_RGBQuad2RGBQUAD(RGBQuad *src, RGBQUAD dst[]) /* ----------------------------------------------------------- */ { int i; for (i = 0; i < 256; i++) { dst[i].rgbBlue = (byte) src[i].blue; dst[i].rgbGreen = (byte) src[i].green; dst[i].rgbRed = (byte) src[i].red; dst[i].rgbReserved = (byte) 0; } } #endif #if (!defined(WIN32) && !defined(_WINDOWS_) && !defined(_WINGDI_)) //#pragma message("bmpio.h no WINDOWS echo") /* --------------------------------------------------------------------------- */ IMAGE_EXPORT(int) SaveBMP0_ui8matrix(uint8 **m, int width, int height, RGBQuad *palette_RGBQuad, char *filename) /* --------------------------------------------------------------------------- */ /* sauvegarde 'image' au format bmp dans le fichier 'filename' */ { int rc = 0; int v_offset = 0; // no more implemented image->v_offset; int h_offset = 0; // no more implemented image->h_offset; int vmax = height - v_offset; //int hmax = width - h_offset; int height_utile = height - 2*v_offset; int width_utile = width - 2*h_offset; int taille_utile = height_utile * width_utile; //int size; int padding_len; BITMAPFILEHEADER Bitmap_File_Header; /*BITMAPINFO; Bitmap_Info; */ BITMAPINFOHEADER Bitmap_Info_Header; /*RGBQUAD RGB_Quad; */ RGBQUAD palette_RGBQUAD[256]; /* Windows */ uint8 Padding[3]; uint8 **data = m; int fd; int i; Padding[0] = 0; Padding[1] = 0; Padding[2] = 0; /* --- Header --- */ Bitmap_File_Header.bfType = (WORD) BM; /* BM */ Bitmap_File_Header.bfSize = (DWORD) sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+256*sizeof(RGBQuad)+taille_utile; /* taille avec header et palette */ Bitmap_File_Header.bfReserved1 = (WORD) 0; /* 0 */ Bitmap_File_Header.bfReserved2 = (WORD) 0; /* 0 */ Bitmap_File_Header.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + (DWORD) sizeof(BITMAPINFOHEADER) + (DWORD) sizeof(RGBQUAD)*256; /* */ Bitmap_Info_Header.biSize = (DWORD) sizeof(BITMAPINFOHEADER); Bitmap_Info_Header.biWidth = (LONG) width_utile; // width sans padding Bitmap_Info_Header.biHeight = (LONG) height_utile; // height sans padding Bitmap_Info_Header.biPlanes = (WORD) 1; // 1 Bitmap_Info_Header.biBitCount = (WORD) 8; // 8 en 256 colors Bitmap_Info_Header.biCompression = (DWORD) BI_RGB; // BI_RGB Bitmap_Info_Header.biSizeImage = (DWORD) 0; // 0 si BI_RGB Bitmap_Info_Header.biXPelsPerMeter = (LONG) 0; // ??? Bitmap_Info_Header.biYPelsPerMeter = (LONG) 0; // ??? Bitmap_Info_Header.biClrUsed = (DWORD) 256; // 256 Bitmap_Info_Header.biClrImportant = (DWORD) 0; // 0 printf(" SaveBMP %s ", filename); printf("[%dx%d] - [%dx%d] = [%dx%d]\n",height,width, v_offset, h_offset, height_utile, width_utile); fd = open(filename, O_CREAT | O_TRUNC); if (fd < 0) { printf("*** Erreur : Ouverture du fichier impossible dans SaveBMP"); } /* enregistrement de l'image au format bmp */ write(fd, &Bitmap_File_Header, sizeof(BITMAPFILEHEADER)); /*if(size != sizeof(BITMAPFILEHEADER)) { printf("Bitmap File Header : octets ecrits %d attendus %d\n", size, sizeof(BITMAPFILEHEADER)); Error("Erreur d'ecriture du Bitmap File Header"); }*/ write(fd, &Bitmap_Info_Header, sizeof(BITMAPINFOHEADER)); /*if(size != sizeof(BITMAPINFOHEADER) ){ printf("Bitmap Info Header : octets ecrits %d attendus %d\n", size, sizeof(BITMAPINFOHEADER)); Error("Erreur d'ecriture du Bitmap Info Header"); }*/ Palette_RGBQuad2RGBQUAD(palette_RGBQuad, palette_RGBQUAD); write(fd, palette_RGBQUAD, sizeof(RGBQUAD) * 256); /*if(size != 256*sizeof(RGBQUAD)) { printf("Palette : octets ecrits %d attendus %d\n", size, 256*sizeof(RGBQUAD)); Error("Erreur d'ecriture de la palette"); }*/ //for(i=v_offset; i= v_offset; i--) { WriteBMProw(data[i] + h_offset, width_utile, fd); write(fd, Padding, sizeof(byte) * padding_len); } close(fd); return rc; } #endif // ------------------------------------------------------------------------------------------------------------ IMAGE_EXPORT(int) SaveBMP2_ui8matrix(uint8 **m, int width, int height, RGBQuad *palette_RGBQuad, char *filename) // ------------------------------------------------------------------------------------------------------------ // sauvegarde 'image' au format bmp dans le fichier 'filename' { int taille_utile = height * width; //int size; int padding_len; BitmapFileHeader Bitmap_File_Header; BitmapInfoHeader Bitmap_Info_Header; //RGBQuad palette_RGBQuad[256]; /* Windows */ byte Padding[3]; uint8 rawBFH[14], *ptrBFH; // raw Bitmap File Header uint8 rawBIH[40], *ptrBIH; // raw Bitmap Info Header int fd; int i; //#pragma message("BMP warnin' data structure aligment must be 2") //#pragma message(" sizeof( BitmapFileHeader) must = 14, not 16") //DEBUG(printf("BMP0 : %d %d\n", sizeof( BITMAPFILEHEADER), sizeof( BITMAPINFOHEADER))); //DEBUG(printf("BMP0_: %d %d\n", sizeof(_BITMAPFILEHEADER), sizeof(_BITMAPINFOHEADER))); //DEBUG(printf("BMP : %d %d\n", sizeof( BitmapFileHeader), sizeof( BitmapInfoHeader))); if (sizeof(BitmapFileHeader) != 14) { printf("*** Error SaveMBP: sizeof(BitmapFileHeader) = %d should be 14...\n", sizeof(BitmapFileHeader)); } Padding[0] = 0; Padding[1] = 0; Padding[2] = 0; // --- Header --- Bitmap_File_Header.bfType = (uint16) BM; // Bitmap_File_Header.bfSize = (uint32) sizeof(BitmapFileHeader) + sizeof(BitmapInfoHeader) + 256 * sizeof(RGBQuad) + taille_utile; /* taille avec header et palette */ Bitmap_File_Header.bfReserved1 = (uint16) 0; /* 0 */ Bitmap_File_Header.bfReserved2 = (uint16) 0; /* 0 */ Bitmap_File_Header.bfOffBits = (uint32) sizeof(BitmapFileHeader) + (uint32) sizeof(BitmapInfoHeader) + (uint32) sizeof(RGBQuad) * 256; /* */ Bitmap_Info_Header.biSize = (uint32) sizeof(BitmapInfoHeader); Bitmap_Info_Header.biWidth = (uint32) width; // width sans padding Bitmap_Info_Header.biHeight = (uint32) height; // height sans padding Bitmap_Info_Header.biPlanes = (uint16) 1; // 1 Bitmap_Info_Header.biBitCount = (uint16) 8; // 8 en 256 colors Bitmap_Info_Header.biCompression = (uint32) BI_RGB; // BI_RGB Bitmap_Info_Header.biSizeImage = (uint32) 0; // 0 si BI_RGB Bitmap_Info_Header.biXPelsPerMeter = (uint32) 0; // ??? Bitmap_Info_Header.biYPelsPerMeter = (uint32) 0; // ??? Bitmap_Info_Header.biClrUsed = (uint32) 256; // 256 Bitmap_Info_Header.biClrImportant = (uint32) 0; // 0 ptrBFH = rawBFH; ptrBFH = ui16ArrayAppend(ptrBFH, Bitmap_File_Header.bfType); ptrBFH = ui32ArrayAppend(ptrBFH, Bitmap_File_Header.bfSize); ptrBFH = ui16ArrayAppend(ptrBFH, Bitmap_File_Header.bfReserved1); ptrBFH = ui16ArrayAppend(ptrBFH, Bitmap_File_Header.bfReserved2); ptrBFH = ui32ArrayAppend(ptrBFH, Bitmap_File_Header.bfOffBits); ptrBIH = rawBIH; ptrBIH = ui32ArrayAppend(ptrBIH, Bitmap_Info_Header.biSize); ptrBIH = ui32ArrayAppend(ptrBIH, Bitmap_Info_Header.biWidth); ptrBIH = ui32ArrayAppend(ptrBIH, Bitmap_Info_Header.biHeight); ptrBIH = ui16ArrayAppend(ptrBIH, Bitmap_Info_Header.biPlanes); ptrBIH = ui16ArrayAppend(ptrBIH, Bitmap_Info_Header.biBitCount); ptrBIH = ui32ArrayAppend(ptrBIH, Bitmap_Info_Header.biCompression); ptrBIH = ui32ArrayAppend(ptrBIH, Bitmap_Info_Header.biSizeImage); ptrBIH = ui32ArrayAppend(ptrBIH, Bitmap_Info_Header.biXPelsPerMeter); ptrBIH = ui32ArrayAppend(ptrBIH, Bitmap_Info_Header.biYPelsPerMeter); ptrBIH = ui32ArrayAppend(ptrBIH, Bitmap_Info_Header.biClrUsed); ptrBIH = ui32ArrayAppend(ptrBIH, Bitmap_Info_Header.biClrImportant); //printf(" SaveBMP %s %dx%d\n", filename, width, height); fd = open(filename, O_CREAT | O_TRUNC); if (fd < 0) { printf("*** Erreur : ouverture du fichier '%s' impossible dans SaveBMP", filename); } // enregistrement de l'image au format bmp //size = fwrite(&Bitmap_File_Header, sizeof(BitmapFileHeader), 1, file); write(fd, rawBFH, 14); //if(size != sizeof(BITMAPFILEHEADER)) { // printf("Bitmap File Header : octets ecrits %d attendus %d\n", size, sizeof(BITMAPFILEHEADER)); // Error("Erreur d'ecriture du Bitmap File Header"); //} //size = fwrite(&Bitmap_Info_Header, sizeof(BitmapInfoHeader), 1, file); write(fd, rawBIH, 40); //if(size != sizeof(BITMAPINFOHEADER) ){ // printf("Bitmap Info Header : octets ecrits %d attendus %d\n", size, sizeof(BITMAPINFOHEADER)); // Error("Erreur d'ecriture du Bitmap Info Header"); //} write(fd, palette_RGBQuad, sizeof(RGBQuad) * 256); //if(size != 256*sizeof(RGBQUAD)) { // printf("Palette : octets ecrits %d attendus %d\n", size, 256*sizeof(RGBQUAD)); // Error("Erreur d'ecriture de la palette"); //} // en 2x car le compilo est trop con ... padding_len = width % 4; padding_len = (4 - padding_len) % 4; for (i = height - 1; i >= 0; i--) { //WriteBMProw(data[i]+h_offset, width_utile, fichier); WriteBMProw(m[i] + 0, width, fd); write(fd, Padding, sizeof(uint8) * padding_len); } close(fd); return 0; }