Advertisement
Deerenaros

Working with BMP. For education by 'Yos'. with functions

Jul 4th, 2012
78
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. //*************************************************************
  2. //*
  3. //* Обрезать
  4. //*
  5. //*************************************************************
  6. void Cut(LPHICOLOR * pImageData, LPDWORD pWidth, LPDWORD pHeight, DWORD left, DWORD top, DWORD right, DWORD bottom)
  7. {
  8.  //****
  9.  LPHICOLOR              pNewImageData;
  10.  
  11.  DWORD                  ImageOffset;
  12.  DWORD                  NewImageOffset;
  13.  
  14.  DWORD                  x;
  15.  DWORD                  y;
  16.  
  17.  DWORD                  width;
  18.  DWORD                  height;
  19.  
  20.  // расчитываем новый размер
  21.  width = right - left + 1;
  22.  height = bottom - top + 1;
  23.  
  24.  // выделяем память под результирующие рабочие данные изображения
  25.  pNewImageData = (LPHICOLOR)GlobalAlloc(GPTR,width*height*sizeof(HICOLOR));
  26.  
  27.  // формируем обрезанное рабочее изображение
  28.  for( y=0; y<height; y++ )
  29.  {
  30.     for( x=0; x<width; x++ )
  31.     {
  32.         // расчитываем смещения
  33.         ImageOffset = (y + top) * (*(pWidth)) + x + left;
  34.         NewImageOffset = y * width + x;
  35.  
  36.         // формируем рабочие данные
  37.         (pNewImageData+NewImageOffset)->Color = (*(pImageData)+ImageOffset)->Color;
  38.     }
  39.  }
  40.  
  41.  // освобождаем ранее выделенную память под рабочие данные изображения
  42.  GlobalFree(*(pImageData));
  43.  // и передаем новую
  44.  *(pImageData) = pNewImageData;
  45.  
  46.  // возвращаем новые размеры
  47.  *(pWidth) = width;
  48.  *(pHeight) = height;
  49. }
  50.  
  51. //*************************************************************
  52. //*
  53. //* Изменить размер
  54. //*
  55. //*************************************************************
  56. void Resize(LPHICOLOR * pImageData, LPDWORD pWidth, LPDWORD pHeight, DWORD NewWidth, DWORD NewHeight)
  57. {
  58.  //****
  59.  LPHICOLOR              pNewImageData;
  60.  
  61.  DWORD                  ImageOffset;
  62.  DWORD                  NewImageOffset;
  63.  
  64.  DWORD                  X;
  65.  DWORD                  Y;
  66.  
  67.  DWORD                  NewX;
  68.  DWORD                  NewY;
  69.  
  70.  DWORD                  CountX;
  71.  DWORD                  CountY;
  72.  
  73.  // выделяем память под результирующие рабочие данные изображения
  74.  pNewImageData = (LPHICOLOR)GlobalAlloc(GPTR,NewWidth*NewHeight*sizeof(HICOLOR));
  75.  
  76.  // формируем рабочее изображение с новыми размерами
  77.  // Основа этих "хитрых" преобразований корнями уходит в целочисленные методы формирования
  78.  // графических примитивов по Брезенхему, с которыми вы должны быть знакомы, так как прочитали указанную мною книгу...
  79.  for( Y=NewY=0,CountY=0; NewY<NewHeight; NewY++,CountY+=*(pHeight) )
  80.  {
  81.     while( CountY >= NewHeight )
  82.     {
  83.         CountY -= NewHeight;
  84.         Y++;
  85.     }
  86.  
  87.     for( X=NewX=0,CountX=0; NewX<NewWidth; NewX++,CountX+=*(pWidth) )
  88.     {
  89.         while( CountX >= NewWidth )
  90.         {
  91.             CountX -= NewWidth;
  92.             X++;
  93.         }
  94.  
  95.         // расчитываем смещения
  96.         ImageOffset = Y * (*(pWidth)) + X;
  97.         NewImageOffset = NewY * NewWidth + NewX;
  98.  
  99.         // формируем рабочие данные
  100.         (pNewImageData+NewImageOffset)->Color = (*(pImageData)+ImageOffset)->Color;
  101.     }
  102.  }
  103.  
  104.  // освобождаем ранее выделенную память под рабочие данные изображения
  105.  GlobalFree(*(pImageData));
  106.  // и передаем новую
  107.  *(pImageData) = pNewImageData;
  108.  
  109.  // возвращаем новые размеры
  110.  *(pWidth) = NewWidth;
  111.  *(pHeight) = NewHeight;
  112. }
  113.  
  114. //*************************************************************
  115. //*
  116. //* Добавить шум
  117. //*
  118. //*************************************************************
  119. void AppendNoise(LPHICOLOR pImageData, DWORD width, DWORD height)
  120. {
  121.  //****
  122.  DWORD                  ImageOffset;
  123.  
  124.  DWORD                  x;
  125.  DWORD                  y;
  126.  
  127.  SYSTEMTIME             time;
  128.  
  129.  DWORD                  Count;
  130.  DWORD                  Random;
  131.  
  132.  BYTE                   gray;
  133.  
  134.  // инициализируем датчик случайных чисел на основании текущего времени
  135.  GetLocalTime(&time);
  136.  Random = time.wMilliseconds * time.wSecond * time.wMinute * time.wHour;
  137.  
  138.  // формиуруем шум
  139.  for( Count=0; Count<10000; Count++ )
  140.  {
  141.     // генерируем положение
  142.     Random = Random * 214013 + 2531011;
  143.     x = Random % width;
  144.     Random = Random * 214013 + 2531011;
  145.     y = Random % height;
  146.  
  147.     // генерируем "цвет" шума - реализация может быть разной
  148.     gray = (BYTE)(Random % 255);
  149.  
  150.     // расчитываем смещение
  151.     ImageOffset = y * width + x;
  152.  
  153.     // формируем рабочие данные
  154.     (pImageData+ImageOffset)->Layer.B = (pImageData+ImageOffset)->Layer.B * gray / 255;
  155.     (pImageData+ImageOffset)->Layer.G = (pImageData+ImageOffset)->Layer.G * gray / 255;
  156.     (pImageData+ImageOffset)->Layer.R = (pImageData+ImageOffset)->Layer.R * gray / 255;
  157.  }
  158. }
  159.  
  160.  
  161.  
  162.  
  163. //*************************************************************
  164.  
  165. typedef struct _HICOLOR
  166. {
  167.     union
  168.     {
  169.         // цельный цвет
  170.         DWORD   Color;
  171.  
  172.         // составляющие
  173.         struct
  174.         {
  175.             BYTE    B;
  176.             BYTE    G;
  177.             BYTE    R;
  178.             BYTE    Alpha;
  179.  
  180.         } Layer;
  181.     };
  182.  
  183. } HICOLOR, *PHICOLOR, *LPHICOLOR;
  184.  
  185. //*************************************************************
  186. //*
  187. //* Старт программы
  188. //*
  189. //*************************************************************
  190. int main(int Count, char ** pArguments)
  191. {
  192.  //****
  193.  HANDLE                 hFile;
  194.  
  195.  BITMAPFILEHEADER       FileHeader;
  196.  BITMAPINFOHEADER       InfoHeader;
  197.  
  198.  LPBYTE                 pFileData;
  199.  LPHICOLOR              pImageData;
  200.  
  201.  DWORD                  Size;
  202.  DWORD                  LineSize;
  203.  
  204.  DWORD                  FileOffset;
  205.  DWORD                  ImageOffset;
  206.  
  207.  DWORD                  x;
  208.  DWORD                  y;
  209.  
  210.  // открываем файл
  211.  hFile = CreateFile(*(pArguments+1),GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL);
  212.  // читаем заголовок файла
  213.  ReadFile(hFile,(LPVOID)&FileHeader,sizeof(BITMAPFILEHEADER),&Size,NULL);
  214.  // читаем заголовок изображения
  215.  ReadFile(hFile,(LPVOID)&InfoHeader,sizeof(BITMAPINFOHEADER),&Size,NULL);
  216.  
  217.  // если это изображение R8G8B8
  218.  if( InfoHeader.biBitCount == 24 )
  219.  {
  220.     // выделяем память под данные файла изображения
  221.     pFileData = (LPBYTE)GlobalAlloc(GPTR,InfoHeader.biSizeImage);
  222.  
  223.     // читаем данные файла изображения
  224.     SetFilePointer(hFile,FileHeader.bfOffBits,NULL,FILE_BEGIN);
  225.     ReadFile(hFile,(LPVOID)pFileData,InfoHeader.biSizeImage,&Size,NULL);
  226.  
  227.     // закрываем файл
  228.     CloseHandle(hFile);
  229.  
  230.     // вычисляем размер линии по горизонтали, так как она должна быть выравнена на DWORD
  231.     // это нужно для дальнейших преобразований
  232.     LineSize = InfoHeader.biSizeImage / InfoHeader.biHeight;
  233.  
  234.     // выделяем память под рабочие данные изображения
  235.     pImageData = (LPHICOLOR)GlobalAlloc(GPTR,InfoHeader.biWidth*InfoHeader.biHeight*sizeof(HICOLOR));
  236.  
  237.     // формируем рабочее изображение
  238.     for( y=0; y<InfoHeader.biHeight; y++ )
  239.     {
  240.         for( x=0; x<InfoHeader.biWidth; x++ )
  241.         {
  242.             // расчитываем смещения
  243.             FileOffset = y * LineSize + x * 3;
  244.             ImageOffset = y * InfoHeader.biWidth + x;
  245.  
  246.             // формируем рабочие данные
  247.             (pImageData+ImageOffset)->Layer.Alpha = 0xFF;
  248.             (pImageData+ImageOffset)->Layer.B = *(pFileData+FileOffset);
  249.             (pImageData+ImageOffset)->Layer.G = *(pFileData+FileOffset+1);
  250.             (pImageData+ImageOffset)->Layer.R = *(pFileData+FileOffset+2);
  251.         }
  252.     }
  253.  
  254.     // освобождаем ранее выделенную память под данные файла изображения
  255.     GlobalFree(pFileData);
  256.  
  257.     // Изменяем размер
  258.     Resize(&pImageData,(LPDWORD)&InfoHeader.biWidth,(LPDWORD)&InfoHeader.biHeight,InfoHeader.biWidth/2,InfoHeader.biHeight/2);
  259.  
  260.     // Обрезаем
  261.     Cut(&pImageData,(LPDWORD)&InfoHeader.biWidth,(LPDWORD)&InfoHeader.biHeight,InfoHeader.biWidth/4,InfoHeader.biHeight/4,InfoHeader.biWidth*3/4,InfoHeader.biHeight*3/4);
  262.  
  263.     // Добавляем шум
  264.     AppendNoise(pImageData,InfoHeader.biWidth,InfoHeader.biHeight);
  265.  
  266.     // вычисляем размер линии по горизонтали, так как она должна быть выравнена на DWORD
  267.     // это нужно для дальнейших преобразований
  268.     for( LineSize=InfoHeader.biWidth*3; (LineSize & 0x00000003); LineSize++ );
  269.  
  270.     // заполняем описание нового изображения
  271.     InfoHeader.biSizeImage = LineSize * InfoHeader.biHeight;
  272.     FileHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + InfoHeader.biSizeImage;
  273.  
  274.     // выделяем память под данные файла изображения
  275.     pFileData = (LPBYTE)GlobalAlloc(GPTR,InfoHeader.biSizeImage);
  276.  
  277.     // формируем готовое изображение
  278.     for( y=0; y<InfoHeader.biHeight; y++ )
  279.     {
  280.         for( x=0; x<InfoHeader.biWidth; x++ )
  281.         {
  282.             // расчитываем смещения
  283.             FileOffset = y * LineSize + x * 3;
  284.             ImageOffset = y * InfoHeader.biWidth + x;
  285.  
  286.             // формируем рабочие данные
  287.             *(pFileData+FileOffset) = (pImageData+ImageOffset)->Layer.B;
  288.             *(pFileData+FileOffset+1) = (pImageData+ImageOffset)->Layer.G;
  289.             *(pFileData+FileOffset+2) = (pImageData+ImageOffset)->Layer.R;
  290.         }
  291.     }
  292.  
  293.     // освобождаем ранее выделенную память под рабочие данные изображения
  294.     GlobalFree(pImageData);
  295.  
  296.     // создаем файл
  297.     hFile = CreateFile(*(pArguments+2),GENERIC_WRITE,FILE_SHARE_WRITE,NULL,CREATE_ALWAYS,0,NULL);
  298.     // записываем заголовок файла
  299.     WriteFile(hFile,(LPVOID)&FileHeader,sizeof(BITMAPFILEHEADER),&Size,NULL);
  300.     // записываем заголовок изображения
  301.     WriteFile(hFile,(LPVOID)&InfoHeader,sizeof(BITMAPINFOHEADER),&Size,NULL);
  302.     // записываем само изображение
  303.     WriteFile(hFile,(LPVOID)pFileData,InfoHeader.biSizeImage,&Size,NULL);
  304.  
  305.     // закрываем файл
  306.     CloseHandle(hFile);
  307.  
  308.     // освобождаем ранее выделенную память под данные файла изображения
  309.     GlobalFree(pFileData);
  310.  }
  311.  
  312.  // закрываем файл
  313.  else CloseHandle(hFile);
  314.  
  315.  return 0;
  316. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement