c ++ generate thumbnails

Reprinted: https://bbs.csdn.net/topics/360165636   3 floor

1. The first larger pictures, converted to BMP (assumed to be 12 x 12), did not point 24bits (RGB each one byte):
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .

Suppose you want to make it into an image of 2 x 2, you can be above 2 x 2 matrix into th 6 X 6 matrix.
6 x 6 matrix for each of all the points R, G, and B values together, and respectively sum_R, sum_G and sum_B, then the obtained
color value of the point is (sum_R / 36, sum_G / 36 , sum_B / 36)
since this, 36 points will be reduced to a point.

2.

Bitmap files can be viewed as consisting of four parts: the bitmap file header (bitmap-file header), bitmap information header (bitmap-information header), the color table (color table) byte and defines bitmaps (bitmaps data, image data, i.e., data Bits, or data Body) array

 

Bitmap file header includes information about file type, file size, storage location, etc., with the structure BITMAPFILEHEADER 3.0+ Windows bitmap file to define:

typedef struct tagBITMAPFILEHEADER {

    /* bmfh */

    UINT bfType;

    DWORD bfSize;

    UINT bfReserved1;

    UINT bfReserved2;

    DWORD bfOffBits;

} BITMAPFILEHEADER;

 

among them:

bfType

Description of the file type. (This value must be 0x4D42, i.e. the character 'BM')

Note: ascii check table B 0x42, M0x4d, bfType two bytes, B is a low byte, M being so high byte bfType = 0x4D42, instead 0x424D.

bfSize: Description file size in bytes with

bfReserved1: reserved, must be set to 0

bfReserved2: reserved, must be set to 0

bfOffBits: Description file header from the beginning to byte offset between the actual image data.

 

Defined using bitmap information BITMAPINFO structure, which consists of bitmap information header (bitmap-information header) and a color table (color table), the former with BITMAPINFOHEADER structure definition, which is defined by the RGBQUAD structure.

BITMAPINFO structure has the following form:

typedef struct tagBITMAPINFO {

    /* bmi */

    BITMAPINFOHEADER bmiHeader;

    RGBQUAD bmiColors[1];

} BITMAPINFO;

bmiHeader

DESCRIPTION BITMAPINFOHEADER structure, which contains information about the size and position of the bitmap format

bmiColors

DESCRIPTION RGBQUAD structure array color table, which contains the RGB values ​​of the real index image.

 

BITMAPINFOHEADER structure includes a bitmap file size, compression type and color format, the structure is defined as:

typedef struct tagBITMAPINFOHEADER {

    / * Bmih * /

    DWORD size;

    LONG biWidth;

    LONG biHeight;

    WORD biPlanes;

    WORD biBitCount;

    DWORD biCompression;

    DWORD biSizeImage;

    LONG biXPelsPerMeter;

    LONG biYPelsPerMeter;

    DWORD biClrUsed;

    DWORD biClrImportant;

} BITMAPINFOHEADER;

Size

Description Words BITMAPINFOHEADER the desired structure. NOTE: This value is not necessarily the size BITMAPINFOHEADER structure, it may be a value sizeof (BITMAPV4HEADER), or the value sizeof (BITMAPV5HEADER) a. This should be decided according to the bitmap file format version, but, on the current situation, the vast majority of BMP images are BITMAPINFOHEADER structure (the latter two may be too new because of it :-).

biWidth

Explaining the image width in pixels

biHeight

DESCRIPTION image height, in pixels. NOTE: This value is used in addition to a height beyond the description of the image, it has another use, indicating that the image is a bitmap backward or forward position in FIG. If the value is a positive number, an image is backward if the value is a negative number, then the image is positive. Most of the BMP bitmap files are backward, that is, the height value is a positive number. (Note: When the height value is a negative number (positive image), the image will not be compressed (that is to say biCompression members will not be BI_RLE8 or BI_RLE4).

biPlanes

To illustrate bit plane target device, which will always be set to the value 1

biBitCount

Description Number of bits / pixel, which is 1,4,8,16,24, or 32

 

biCompression

DESCRIPTION image data compression type. Its value can be one of the following values:

BI_RGB: no compression;

BI_RLE8: 8 bits for each pixel of RLE compression encoding, the compression format 2 bytes (pixel count and repeat color index);

BI_RLE4: four bits per pixel RLE compression encoding, the compression format 2 bytes

BI_BITFIELDS: bits per pixel determined by the mask specified.

 

biSizeImage

DESCRIPTION image size, in bytes. When used BI_RGB format, it can be set to 0

biXPelsPerMeter

DESCRIPTION horizontal resolution, expressed in pixels / meter

 

biYPelsPerMeter

DESCRIPTION vertical resolution, expressed in pixels / meter

biClrUsed

DESCRIPTION color index number of the bitmap color table actually used in (set to 0, then all instructions palette entries)

biClrImportant

Description have a major impact on the number of images displayed color index, if it is 0, that are important.

 

Color table positioning

Application may use information stored in biSize members to color lookup table BITMAPINFO structure, as follows:

pColor = ((LPSTR) pBitmapInfo + (WORD) (pBitmapInfo-> bmiHeader.biSize))

 

The following code generates a thumbnail BMP image formats. Artwork must be greater than the new map.

#define _CRT_SECURE_NO_WARNINGS

#include<windows.h>
#include<stdio.h>
#include<assert.h>
#include<iostream>

using namespace std;

#define newWidth 380     // New FIG width 
#define newHeight 310     // new height FIG.

//--------------------------------------------------Rothstein----------------------------------------------------------
class Rothstein
{
public:
    Rothstein(int p, int q);
    int operator[] (int i) { return myData[i]; }
    void Permute();
    void PrintData();
    ~Rothstein();
private:
    char *myData;
    int myP, myQ;
};

Rothstein::Rothstein(int p, int q)
{
    myP = p;
    myQ = q;
    myData = new char[p];

    if (p <= q) {
        memset(myData, 1, p);
        return;
    }

    char *ptr = myData;
    int diff = p - q;
    int  curr = q;
    for (int i = 0; i < p; i++)     //if we want to permute the code, we need <<1
    {
        if (curr < p)
        {
            * ptr = 0 ;
            curr += q;
        }
        else
        {
            * ptr = 1 ;
            curr -= diff;
        }
        ptr ++ ;
    }
}

void Rothstein::Permute()
{
    int temp = myData[0];

    for (int i = 0; i < myP - 1; i++)
        myData[i] = myData[i + 1];

    myData [myP - 1 ] = temp;
}

void Rothstein::PrintData()
{
    for (int i = 0; i < myP; i++)
    {
        cout << myData[i] << " ";
    }
    cout << "\n";
}

Rothstein::~Rothstein()
{
    delete myData;
}
//--------------------------------------------------Rothstein----------------------------------------------------------

//--------------------------------------------------RowRothstein----------------------------------------------------------
class RowRothstein
{
public:
    RowRothstein(int largerSize, int bpp); //increment according to byte per pixel
    int operator[] (int i) { return myData[i]; }
    void PrintData();
private:
    int myData[NEWWIDTH];
};

RowRothstein::RowRothstein(int largerSize, int bpp)
{    
    Rothstein rot(largerSize, NEWWIDTH);
    int j = 0;
    int oldData = 0;
    for (int i = 0; i < largerSize; i++)
    {
        if (rot[i])
        {
            myData[j++] = (i - oldData)*bpp; //increment in bytes per pixel * number of pixels
            oldData = i;
        }
    }
}

void RowRothstein::PrintData()
{
    for (int i = 0; i < NEWWIDTH; i++)
    {        
        cout << myData[i] << "\t";
    }
    cout << "\n";
}
//--------------------------------------------------RowRothstein----------------------------------------------------------

//--------------------------------------------------ColRothstein----------------------------------------------------------
class ColRothstein
{
public:
    ColRothstein(int largerSize, int bpl); //increment according to byte perl line 
    int operator[] (int i) { return myData[i]; }
    void PrintData();

private:
    int myData[NEWHEIGHT];
};

ColRothstein::ColRothstein(int largerSize, int bpl)
{
    Rothstein rot(largerSize, NEWHEIGHT);
    int j = 0;
    int oldData = 0;
    for (int i = 0; i < largerSize; i++)
    {
        if (rot[i])
        {
            myData[j++] = (i - oldData) * bpl; //increment by number of lines * bytes per line
            oldData = i;
        }
    }
}

void ColRothstein::PrintData()
{
    for (int i = 0; i < NEWHEIGHT; i++)
    {
        cout << myData[i] << "\t";
    }
    cout << "\n";
}
//--------------------------------------------------ColRothstein----------------------------------------------------------

BYTE* bits = NULL;
BYTE* newbits = NULL;
FILE* file = NULL;
BF the BITMAPFILEHEADER; // bitmap file header 
unsigned newwidth, newheight, newimagesize, newbfsize ;
unsigned bmiSize;
unsigned imageSize;
int bpp, bpl;
RowRothstein *rotRow;
ColRothstein *rotCol;
struct {
    BmiHeader the BITMAPINFOHEADER; // contains the size and position information about the format of the bitmap 
    RGBQUAD bmiColors [ 256 ]; // DESCRIPTION RGBQUAD structure array color table, which contains the true value of the index image, RGB 
} BMI; // bitmap information

void InitDevice()
{
    newwidth = NEWWIDTH;
    newheight = NEWHEIGHT;
    //-------byte per pixel 3   original image byte per line 800 x 3 = 2400
    bpp = 3;
    bpl = bmi.bmiHeader.biWidth * bpp;

    rotRow = new RowRothstein(bmi.bmiHeader.biWidth, bpp);
    rotCol = new ColRothstein(bmi.bmiHeader.biHeight, bpl);

}

void ResizeImage(unsigned char* src, unsigned char* dst)
{
    unsigned char* oldp;  //pointer to the pix in the old image
    int oldcol = 0;

    for (int row = 0; row < NEWHEIGHT; row++)
    {
        src += (*rotCol)[row];
        oldp = src;
        for (int col = 0; col < NEWWIDTH;)
        {    //unroll 10 times;
            oldp += (*rotRow)[col++];
            memcpy(dst, oldp, bpp);
            dst + = bpp;
            oldp += (*rotRow)[col++];
            memcpy(dst, oldp, bpp);
            dst + = bpp;
            oldp += (*rotRow)[col++];
            memcpy(dst, oldp, bpp);
            dst + = bpp;
            oldp += (*rotRow)[col++];
            memcpy(dst, oldp, bpp);
            dst + = bpp;
            oldp += (*rotRow)[col++];
            memcpy(dst, oldp, bpp);
            dst + = bpp;
            oldp += (*rotRow)[col++];
            memcpy(dst, oldp, bpp);
            dst + = bpp;
            oldp += (*rotRow)[col++];
            memcpy(dst, oldp, bpp);
            dst + = bpp;
            oldp += (*rotRow)[col++];
            memcpy(dst, oldp, bpp);
            dst + = bpp;
            oldp += (*rotRow)[col++];
            memcpy(dst, oldp, bpp);
            dst + = bpp;
            oldp += (*rotRow)[col++];
            memcpy(dst, oldp, bpp);
            dst + = bpp;
        }
    }
}

void LoadBMP(char* filename)
{
    if (!(file = fopen(filename, "rb"))) {
        goto done;
    }

    if (fread(&bf, 1, sizeof(bf), file) != sizeof(bf)) {
        goto done;
    }

    IF (! bf.bfType = * (WORD *) " the BM " ) { // determines whether the bmp file, bfType bmp file bitmap file header must be "the BM" (0x4D42) 
        GOTO DONE;
    }

    bmiSize = bf.bfOffBits - the sizeof (BF); // bfOffBits: From the start to the header bytes of image data between the actual offset 
    IF (bmiSize> the sizeof (BMI)) {
         GOTO DONE;
    }
    if (fread(&bmi, 1, bmiSize, file) != bmiSize) {
        goto done;
    }
    // biWidth: image width, in pixels 
    / * biHeight: image height, in pixels. If the value is a positive number, an image is backward if the value is a negative number, then the image is positive.
    When the height is a negative value (positive image), the image will not be compressed * / 
    // the biBitCount: specifies the number of bits / pixel, which is 1,4,8,16,24, or 32 
    imageSize = (BMI * bmi.bmiHeader.biBitCount .bmiHeader.biWidth / . 8 + . 3 & ~ . 3 ) * bmi.bmiHeader.biHeight;
    bits = new BYTE[imageSize];

    if (fread(bits, 1, imageSize, file) != imageSize) {
        goto done;
    }

    the Assert (bmi.bmiHeader.biHeight > = newHeight); // original larger than a thumbnail image should 
    the Assert (bmi.bmiHeader.biWidth> = newWidth); // original picture should be more than large thumbnails 

    cout << " Image size IS " imageSize << << " \ the n- " ;
    cout << "color is " << bmi.bmiHeader.biBitCount << "\n";
    cout << "width is " << bmi.bmiHeader.biWidth << " height is " << bmi.bmiHeader.biHeight << "\n";

done:
    if (file) {
        fclose(file);
    }

}

void ProcessBMP(char* filename)
{
    newimagesize = (newwidth* bmi.bmiHeader.biBitCount / 8 + 3 & ~3)* newheight;
    newbits = new BYTE[newimagesize];
    int bytes_per_line = bmi.bmiHeader.biBitCount / 8 * bmi.bmiHeader.biWidth + 3 & ~3;

    ResizeImage((unsigned char*)bits, (unsigned char*)newbits);

    int filesize = sizeof(bf)+bmiSize + newimagesize;
    bf.bfSize = filesize;
    bmi.bmiHeader.biWidth = newwidth;
    bmi.bmiHeader.biHeight = newheight;
    bmi.bmiHeader.biSizeImage = newimagesize;

    if (!(file = fopen(filename, "wb"))) {
        goto done;
    }
    if (fwrite(&bf, 1, sizeof(bf), file) != sizeof(bf)) {
        goto done;
    }

    if (fwrite(&bmi, 1, bmiSize, file) != bmiSize) {
        goto done;
    }

    if (fwrite(newbits, 1, newimagesize, file) != newimagesize) {
        goto done;
    }
done:
    if (file) {
        fclose(file);
    }
    if (bits) {
        delete[] bits;
    }
    if (newbits) {
        delete[] newbits;
    }

    if (rotRow) {
        delete rotRow;
    }
    if (rotCol) {
        delete rotCol;
    }
}

int main(int argc, char* argv[])
{
    char* infile;
    char* outfile;

    {
        infile = "test.bmp";
        outfile = "test2.bmp"; 
        
        LoadBMP(infile);
        InitDevice();
        ProcessBMP(outfile);
    }
    system("pause");
    return 0;
}

 

Guess you like

Origin www.cnblogs.com/Toya/p/12531989.html