summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlivier Gayot <duskcoder@gmail.com>2014-09-18 01:27:28 +0000
committerOlivier Gayot <duskcoder@gmail.com>2014-09-18 01:27:28 +0000
commit6d95df26508747cd5c511684f3981ac97550408e (patch)
tree7759c4851d7c5299f7c747b707c3c87076eb3890
parentcc94f989c49e4645796fb7dcc471ebb696606ffa (diff)
write the algorithms to write to and read from the bitmap
* now we can write to the LSBs of the bitmap using: $ ./stegmp write file.bmp input_file if input_file is "-", then then standard input will be handled * the same way, we can read the content of the-said LSBs using: $ ./stegmp read file.bmp Signed-off-by: Olivier Gayot <duskcoder@gmail.com>
-rw-r--r--stegmp.c110
1 files changed, 109 insertions, 1 deletions
diff --git a/stegmp.c b/stegmp.c
index 09d9e00..825fd8f 100644
--- a/stegmp.c
+++ b/stegmp.c
@@ -23,12 +23,114 @@
#include <sysexits.h>
+#include <limits.h>
+
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "bmp.h"
+/*
+ * loop through every LSB of each RGB component of each pixel of the bitmap
+ * for each value, shift the retrieved bit directly in the value
+ * whenever a value is completely built, display it on the standard output
+ */
+static int stegmp_loop_read(unsigned char *baseaddr, struct bitmap *bmpp)
+{
+ unsigned char *addr = baseaddr + bmpp->data_offset;
+ unsigned char bits = 0;
+ uint8_t value;
+
+ if (bmpp->width == UINT_MAX || bmpp->height == UINT_MAX) {
+ bmp_errno = BMP_EINVALSIZ;
+ return -1;
+ }
+
+ for (uint32_t y = 0; y < bmpp->height; ++y) {
+ for (uint32_t x = 0; x < bmpp->width; ++x) {
+ for (int i = 0; i < bmpp->bpp / 8; ++i) {
+ value = (value << 1) | (*addr & 0x1);
+
+ if (++bits == 8) {
+ fwrite(&value, 1, 1, stdout);
+ bits = 0;
+ }
+
+ addr++;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * reads input from `fh' and write it bit by bit to the LSB of each RGB
+ * component of each pixel of the bitmap
+ */
+static
+int stegmp_loop_write(unsigned char *baseaddr, struct bitmap *bmpp, FILE *fh)
+{
+ unsigned char *addr = baseaddr + bmpp->data_offset;
+ unsigned char bits = 0;
+ uint8_t value;
+ char buffer[256];
+ size_t idx = 0;
+ size_t len;
+
+ if (bmpp->width == UINT_MAX || bmpp->height == UINT_MAX) {
+ bmp_errno = BMP_EINVALSIZ;
+ return -1;
+ }
+
+ len = fread(buffer, 1, sizeof(buffer), fh);
+
+ if (len == 0) {
+ return (ferror(fh)) ? -1 : 0;
+ }
+
+ value = buffer[idx++];
+
+ for (uint32_t y = 0; y < bmpp->height; ++y) {
+ for (uint32_t x = 0; x < bmpp->width; ++x) {
+ for (int i = 0; i < bmpp->bpp / 8; ++i) {
+
+ /* write a bit of the new value on the mapped file */
+ *addr = (*addr & 0xfe) | ((value >> (7 - bits)) & 0x1);
+
+ if (++bits == 8) {
+ /* 8 bits of the value have been written */
+
+ bits = 0;
+
+ /* check if bufferized input still present */
+ if (idx == len) {
+ if (feof(fh)) {
+ return 0;
+ } else if (ferror(fh)) {
+ return -1;
+ }
+
+ len = fread(buffer, 1, sizeof(buffer), fh);
+
+ if (len == 0) {
+ return (ferror(fh)) ? -1 : 0;
+ }
+
+ idx = 0;
+ }
+
+ value = buffer[idx++];
+ }
+ ++addr;
+ }
+ }
+ }
+
+ return 0;
+}
+
static int stegmp_parse_windows_bitmap_info_header(const unsigned char *addr,
size_t size, struct bitmap *bmpp)
{
@@ -162,7 +264,11 @@ static int stegmp(const char *bmp_file, FILE *input)
/* retrieve the required information (i.e. width, height, bpp .. ) */
if (stegmp_parse_headers(addr, stat.st_size, &bmp) >= 0) {
- (void) input;
+ if (input) {
+ stegmp_loop_write(addr, &bmp, input);
+ } else {
+ stegmp_loop_read(addr, &bmp);
+ }
} else {
fprintf(stderr, "unable to parse headers: %s\n",
@@ -208,6 +314,8 @@ static void usage(const char *prgnam)
fprintf(stderr, "\nCOMMAND\n");
fprintf(stderr, " read BMP\n");
fprintf(stderr, " write BMP in_file\n");
+ fprintf(stderr, "\n");
+ fprintf(stderr, "if in_file is \"-\", the standard input is used\n");
exit(EX_USAGE);
}