1 #include "bmp.h"
2
3 namespace Upp {
4
5 #include "bmphdr.h"
6
GetPaletteCount()7 int BMPEncoder::GetPaletteCount()
8 {
9 if(bpp > 8 || grayscale) return 0;
10 return bpp == 8 ? 256 : bpp == 4 ? 16 : 2;
11 }
12
Start(Size size)13 void BMPEncoder::Start(Size size)
14 {
15 BMPHeader header;
16 Zero(header);
17 header.biSize = sizeof(BMP_INFOHEADER);
18 header.biWidth = size.cx;
19 header.biHeight = size.cy;
20 header.biBitCount = bpp;
21 header.biPlanes = 1;
22 header.biCompression = 0;
23 int ncolors = 0;
24 switch(bpp) {
25 case 1: format.Set1mf(); ncolors = 2; break;
26 case 4: format.Set4mf(); ncolors = 16; break;
27 case 8: format.Set8(); ncolors = 256; break;
28 case 16: format.Set16le(0xf800, 0x07E0, 0x001f); break;
29 case 32: format.Set32le(0xff0000, 0x00ff00, 0x0000ff); break;
30 default: format.Set24le(0xff0000, 0x00ff00, 0x0000ff); break;
31 }
32 if(ncolors) {
33 if(grayscale)
34 for(int i = 0; i < ncolors; i++) {
35 BMP_RGB& p = header.palette[i];
36 p.rgbRed = p.rgbGreen = p.rgbBlue = 255 * i / (ncolors - 1);
37 }
38 else {
39 const RGBA *palette = GetPalette();
40 for(int i = 0; i < ncolors; i++) {
41 BMP_RGB& p = header.palette[i];
42 p.rgbRed = palette[i].r;
43 p.rgbGreen = palette[i].g;
44 p.rgbBlue = palette[i].b;
45 }
46 }
47 }
48 if(bpp == 16) {
49 dword *bitfields = reinterpret_cast<dword *>(header.palette);
50 bitfields[2] = 0x001f;
51 bitfields[1] = 0x07E0;
52 bitfields[0] = 0xf800;
53 header.biCompression = 3/* BI_BITFIELDS */;
54 ncolors = 3;
55 }
56 row_bytes = (format.GetByteCount(size.cx) + 3) & ~3;
57 scanline.Alloc(row_bytes);
58 header.biSizeImage = size.cy * row_bytes;
59 Size dots = GetDots();
60 if(dots.cx && dots.cy) {
61 header.biXPelsPerMeter = fround(header.biWidth * (1000.0 / 25.4 * 600.0) / dots.cx);
62 header.biYPelsPerMeter = fround(header.biHeight * (1000.0 / 25.4 * 600.0) / dots.cy);
63 }
64 BMP_FILEHEADER bmfh;
65 Zero(bmfh);
66 bmfh.bfType = 'B' + 256 * 'M';
67 bmfh.bfOffBits = sizeof(bmfh) + sizeof(BMP_INFOHEADER) + sizeof(BMP_RGB) * ncolors;
68 bmfh.bfSize = sizeof(bmfh) + sizeof(BMP_INFOHEADER) + ncolors + header.biSizeImage;
69 bmfh.SwapEndian();
70 GetStream().Put(&bmfh, sizeof(bmfh));
71 header.SwapEndian();
72 int h = sizeof(BMP_INFOHEADER) + sizeof(BMP_RGB) * ncolors;
73 GetStream().Put(&header, h);
74 soff = GetStream().GetPos();
75 GetStream().SetSize(sizeof(bmfh) + h + size.cy * row_bytes);
76 linei = size.cy;
77 linebytes = format.GetByteCount(size.cx);
78 }
79
WriteLineRaw(const byte * s)80 void BMPEncoder::WriteLineRaw(const byte *s)
81 {
82 GetStream().Seek(soff + row_bytes * --linei);
83 memcpy(scanline, s, linebytes);
84 GetStream().Put(scanline, row_bytes);
85 }
86
87 }
88