Advertisement
Guest User

Untitled

a guest
Jan 1st, 2017
101
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.71 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <fcntl.h>
  5. #include <stdint.h>
  6. #include <limits.h>
  7. #include <errno.h>
  8. #include <time.h>
  9.  
  10.  
  11. struct BMPFileHeader {
  12.    
  13.     // "BM"
  14.     uint16_t type;
  15.     // size of file in bytes
  16.     uint32_t size;
  17.     // reserved, unused, must be 0
  18.     uint16_t reserved1;
  19.     uint16_t reserved2;
  20.  
  21.     // offset to start pixel data
  22.     // or rahter... file offset for the start of the actual image data
  23.     uint32_t offset_bits;
  24. };
  25.  
  26.  
  27. struct BMPImageHeader {
  28.     // 40
  29.     uint32_t header_size;
  30.  
  31.     // width and height of the image, in pixels
  32.     uint32_t width;
  33.     uint32_t height;
  34.  
  35.     // always 1 plane
  36.     uint16_t planes;
  37.  
  38.     // go for 24bit-true-color
  39.     //    R        G        B
  40.     // 00000000 00000000 00000000
  41.     uint16_t bit_count;
  42.  
  43.     // 0, no compression
  44.     uint32_t compression;
  45.  
  46.     // image size. May be zero for uncompressed images
  47.     uint32_t image_size;
  48.  
  49.     // 0, no preference
  50.     uint32_t x_pixels_per_meter;
  51.     uint32_t y_pixels_per_meter;
  52.  
  53.     // number of color map entries actually used
  54.     // 0 for 24bit true color
  55.     uint32_t color_maps_used;
  56.  
  57.     // number of significant colors in the color table
  58.     // set to 0 for default (a lot), no color table anyway
  59.     uint32_t color_important;
  60. };
  61.  
  62.  
  63. int sort_cmp(const void *a, const void *b)
  64. {
  65.     return *(uint8_t *)a - *(uint8_t *)b;
  66. }
  67.  
  68.  
  69. int32_t getPositive32bit(const char *num)
  70. {
  71.     int res;
  72.     char *endptr;
  73.  
  74.     res = strtol(num, &endptr, 10);
  75.  
  76.     if (errno == ERANGE || res == LONG_MIN || res == LONG_MAX) {
  77.         return -1;
  78.     }
  79.  
  80.     if (*endptr != '\0') {
  81.         return -1;
  82.     }
  83.  
  84.     if (res <= 0) {
  85.         return -1;
  86.     }
  87.  
  88.     if (res > 2147483647) {
  89.         return -1;
  90.     }
  91.  
  92.     return res;
  93. }
  94.  
  95.  
  96. int write_file(int f, struct BMPFileHeader *fh, struct BMPImageHeader *ih, uint8_t *img)
  97. {
  98.     // file header
  99.     write(f, &fh->type, 2);
  100.     write(f, &fh->size, 4);
  101.     write(f, &fh->reserved1, 2);
  102.     write(f, &fh->reserved2, 2);
  103.     write(f, &fh->offset_bits, 4);
  104.  
  105.     // img header
  106.     write(f, &ih->header_size, 4);
  107.     write(f, &ih->width, 4);
  108.     write(f, &ih->height, 4);
  109.     write(f, &ih->planes, 2);
  110.     write(f, &ih->bit_count, 2);
  111.     write(f, &ih->compression, 4);
  112.     write(f, &ih->image_size, 4);
  113.     write(f, &ih->x_pixels_per_meter, 4);
  114.     write(f, &ih->y_pixels_per_meter, 4);
  115.     write(f, &ih->color_maps_used, 4);
  116.     write(f, &ih->color_important, 4);
  117.  
  118.     // image data
  119.     write(f, img, ih->width * ih->height * 3);
  120.  
  121.     return 0;
  122. }
  123.  
  124.  
  125. struct BMPImageHeader *makeBMPImageHeader(uint32_t width, uint32_t height)
  126. {
  127.     struct BMPImageHeader *image_header = calloc(1, sizeof(struct BMPImageHeader));
  128.     image_header->header_size = 40;
  129.     image_header->width = width;
  130.     image_header->height = height;
  131.     image_header->planes = 1;
  132.     image_header->bit_count = 24;
  133.     return image_header;
  134. }
  135.  
  136.  
  137. struct BMPFileHeader *makeBMPFileHeader(struct BMPImageHeader *ih)
  138. {
  139.     struct BMPFileHeader *file_header = calloc(1, sizeof(struct BMPFileHeader));
  140.     file_header->type |= 'M' << 8;
  141.     file_header->type |= 'B';
  142.     file_header->size = 54 + (ih->width * ih->height * 3);
  143.     file_header->offset_bits = 54;
  144.     return file_header;
  145. }
  146.  
  147.  
  148. uint8_t *makeBMPImageData(struct BMPImageHeader *image_header)
  149. {
  150.     int i;
  151.     int j;
  152.     uint8_t r;
  153.     size_t size;
  154.     uint8_t *data;
  155.     uint8_t *dptr;
  156.  
  157.     size = image_header->height * image_header->width;
  158.     data = calloc(1, size * 3);
  159.     dptr = data;
  160.  
  161.     for (i = 0; i < size; i++) {
  162.         // write 1 pixel to buffer (3 bytes per pixel)
  163.         for (j = 0; j < 3; j++, dptr++) {
  164.             r = rand() & 0x000000FF;
  165.             *dptr = r;
  166.         }
  167.     }
  168.  
  169.     qsort(data, size, 3, sort_cmp);
  170.  
  171.     return data;
  172. }
  173.  
  174.  
  175. void seed_rng(void)
  176. {
  177.     long int seed;
  178.     int fp = open("/dev/urandom", O_RDONLY);
  179.     read(fp, (char *)&seed, sizeof(seed));
  180.     srand(seed);
  181.     close(fp);
  182. }
  183.  
  184.  
  185. int main(int argc, char *argv[])
  186. {
  187.     int f;
  188.     int32_t width;
  189.     int32_t height;
  190.     uint8_t *data;
  191.     struct BMPImageHeader *image_header;
  192.     struct BMPFileHeader *file_header;
  193.  
  194.     if (argc < 4) {
  195.         fprintf(stderr, "Usage: %s width height filename\n", argv[0]);
  196.         return -1;
  197.     }
  198.  
  199.     seed_rng();
  200.  
  201.     width = getPositive32bit(argv[1]);
  202.     if (width == -1) {
  203.         fprintf(stderr, "Invalid width %s\n", argv[1]);
  204.         return -1;
  205.     }
  206.  
  207.     height = getPositive32bit(argv[2]);
  208.     if (height == -1) {
  209.         fprintf(stderr, "Invalid height %s\n", argv[2]);
  210.         return -1;
  211.     }
  212.  
  213.     f = open(argv[3], O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR | S_IXUSR);
  214.     if (f == -1) {
  215.         fprintf(stderr, "Could not open file for writing: %s\n", argv[3]);
  216.         return -1;
  217.     }
  218.  
  219.     image_header = makeBMPImageHeader(width, height);
  220.     file_header = makeBMPFileHeader(image_header);
  221.     data = makeBMPImageData(image_header);
  222.  
  223.     write_file(f, file_header, image_header, data);
  224.    
  225.     close(f);
  226.  
  227.     free(image_header);
  228.     free(file_header);
  229.     free(data);
  230.  
  231.     return 0;
  232. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement