View difference between Paste ID: vXGNTgjg and dRxJYs8m
SHOW: | | - or go back to the newest paste.
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
}