Related
Im trying to remove value from a set but can't get it to work
this is the struct
struct set {
int capacity;
int size;
char *array;
};
This is how i insert the values in to the set
void set_insert(const int value, set *s)
{
if (!set_member_of(value, s))
{
int bit_in_array = value; // To make the code easier to read
// Increase the capacity if necessary
if (bit_in_array >= s->capacity)
{
int no_of_bytes = bit_in_array / 8 + 1;
s->array = realloc(s->array, no_of_bytes);
for (int i = s->capacity / 8 ; i < no_of_bytes ; i++)
{
s->array[i] = 0;
}
s->capacity = no_of_bytes * 8;
}
// Set the bit
int byte_no = bit_in_array / 8;
int bit = 7 - bit_in_array % 8;
s->array[byte_no] = s->array[byte_no] | 1 << bit;
s->size++;
}
}
This is how i've tried to remove the values. I don't know why but
it completely ruins the set and assigns different values to the
entire array
void set_remove(const int value, set *const s)
{
int byte_no = value / 8;
if(set_member_of(value, s))
{
s->array[byte_no] = 0;
s->size--;
}
}
You didn't post set_member_of, so I had to synthesize it.
The main issue with set_remove is that it is zeroing out all bits in the given byte. You want to and against the complement of the bit mask. So, change this:
s->array[byte_no] = 0;
Into:
s->array[byte_no] &= ~mask;
When I do bit masks, I like to use macros instead of shifts/divides/etc in multiple places.
In set_insert, I think it's easier to make capacity be number of bytes rather than number of bits.
Although char for the array type works, using unsigned char is probably better.
Note that as you define set, under C, it is not a type.
Anyway, here is the refactored code. I've compiled it but not tested it:
#include <stdlib.h>
typedef unsigned char atom;
typedef struct set {
int capacity;
int size;
atom *array;
} set;
#define INDEX(_bitno) ((_bitno) / 8)
#define MASK(_bitno) (7 - ((_bitno) % 8))
int
set_member_of(int bitno,set *s)
{
int byte_no = INDEX(bitno);
atom mask = MASK(bitno);
atom match = 0;
if (byte_no < s->capacity)
match = s->array[byte_no] & mask;
return match;
}
void
set_insert(int bitno, set *s)
{
if (! set_member_of(bitno, s)) {
int newcap = INDEX(bitno + 8);
// Increase the capacity if necessary
if (newcap > s->capacity) {
s->array = realloc(s->array, newcap);
// zero out any new cells
for (int i = s->capacity; i < newcap; ++i)
s->array[i] = 0;
s->capacity = newcap;
}
atom mask = MASK(bitno);
int byte_no = INDEX(bitno);
s->array[byte_no] |= mask;
s->size++;
}
}
void
set_remove(int bitno, set *s)
{
if (set_member_of(bitno, s)) {
int byte_no = INDEX(bitno);
atom mask = MASK(bitno);
s->array[byte_no] &= ~mask;
s->size--;
}
}
I want to write my own png reader using little help from other libraries. So far, I can read back images with only one IDAT chunk perfectly well. However, when I need to concatenate multiple chunks, the file ends up corrupted. Here is an example of one:
I have a lot of code, so I'm going to try and get it to as 'minimum reproducable example' as I can get, but this along with the fact I do not know specifically what part is causing it, is going to make it a bit longer than I'm sure some of you might like, and I'm sorry.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "zlib.h"
unsigned char IEND_CHUNK[4] = {'I', 'E', 'N', 'D'}; //Indicates End Of File
unsigned char IDAT_CHUNK[4] = {'I', 'D', 'A', 'T'}; //Holds Pixel Information
typedef struct Chunk Chunk;
typedef struct IHDR IHDR;
struct Chunk {
int length;
unsigned char type[4];
unsigned char *data;
unsigned char crc[4];
};
struct IHDR {
int width;
int height;
int bitd;
int colort;
int compm;
int filterm;
int interlacem;
int channels;
int bytesPerPixel;
};
int bytesToInt(unsigned char a, unsigned char b, unsigned char c, unsigned char d)
{
return (int) a << 24 | b << 16 | c << 8 | d;
}
int compType(unsigned char *a, unsigned char b[], int len)
{
int equal = 1;
for(int i = 0; i < len; i++) equal = a[i] == b[i] ? equal : 0;
return equal;
}
Chunk* getChunksFromBytes(unsigned char* bytes)
{
int next_seg = 7;
int chunks = 0;
long int size = 1;
Chunk* temp = (Chunk*) malloc(sizeof(Chunk));
while(1){
size += sizeof(Chunk);
temp = realloc(temp, size);
temp[chunks].length = bytesToInt(bytes[next_seg+1], bytes[next_seg+2],
bytes[next_seg+3], bytes[next_seg+4]);
temp[chunks].type[0] = bytes[next_seg+5];
temp[chunks].type[1] = bytes[next_seg+6];
temp[chunks].type[2] = bytes[next_seg+7];
temp[chunks].type[3] = bytes[next_seg+8];
temp[chunks].data = malloc(temp[chunks].length);
if(temp[chunks].length > 0){
memcpy(temp[chunks].data, bytes+next_seg+9, temp[chunks].length);
}
else temp[chunks].data = NULL;
temp[chunks].crc[0] = bytes[next_seg+temp[chunks].length+9];
temp[chunks].crc[1] = bytes[next_seg+temp[chunks].length+10];
temp[chunks].crc[2] = bytes[next_seg+temp[chunks].length+11];
temp[chunks].crc[3] = bytes[next_seg+temp[chunks].length+12];
if(compType(temp[chunks].type, IEND_CHUNK, 4)) break;
next_seg+=temp[chunks].length+12;
chunks++;
}
return temp;
}
IHDR getIHDRFromChunks(Chunk* chunks)
{
IHDR img_info;
int channels[7] = {1, 0, 3, 1, 2, 0, 4};
img_info.width = bytesToInt(chunks[0].data[0], chunks[0].data[1],
chunks[0].data[2], chunks[0].data[3]);
img_info.height = bytesToInt(chunks[0].data[4], chunks[0].data[5],
chunks[0].data[6], chunks[0].data[7]);
img_info.bitd = (int) chunks[0].data[8];
img_info.colort = (int) chunks[0].data[9];
img_info.compm = (int) chunks[0].data[10];
img_info.filterm = (int) chunks[0].data[11];
img_info.interlacem = (int) chunks[0].data[12];
img_info.channels = channels[img_info.colort];
img_info.bytesPerPixel = (int) img_info.channels * (img_info.bitd / 8);
return img_info;
}
unsigned char* getImgFromChunks(Chunk* chunks)
{
int count = 0;
IHDR ihdr_data = getIHDRFromChunks(chunks);
uLongf compressed_size = 0;
uLongf uncompressed_size = (ihdr_data.width*ihdr_data.height*ihdr_data.bytesPerPixel) + ihdr_data.height + 1;
unsigned char* compressed_idat = (unsigned char*) malloc(sizeof(unsigned char)*4);
unsigned char* uncompressed_idat = (unsigned char*) malloc(sizeof(unsigned char)*uncompressed_size);
while(1){
if(compType(chunks[count].type, IEND_CHUNK, 4)) break;
else if (compType(chunks[count].type, IDAT_CHUNK, 4)){
compressed_size += sizeof(unsigned char)*chunks[count].length;
compressed_idat = realloc(compressed_idat, compressed_size);
memcpy(compressed_idat + compressed_size - chunks[count].length, chunks[count].data, chunks[count].length);
}
count++;
}
int ret = uncompress(uncompressed_idat, &uncompressed_size, compressed_idat, compressed_size);
free(compressed_idat);
return ret == 0 ? uncompressed_idat : '\0';
}
int PaethPredictor(int a, int b, int c)
{
int pa = abs(b - c);
int pb = abs(a - c);
int pc = abs(a + b - (2*c));
if(pa <= pb && pa <= pc) return a;
else if(pb <= pc) return b;
return c;
}
int* getPixelsFromImg(unsigned char* img, IHDR ihdr_info)
{
int* pixels = (int*) malloc(sizeof(int)*ihdr_info.width*ihdr_info.height*ihdr_info.bytesPerPixel);
int filter_type;
int i = 0;
int current_pixel = 0;
int stride = ihdr_info.width * ihdr_info.bytesPerPixel;
int filt_a;
int filt_b;
int filt_c;
for(int r = 0; r < ihdr_info.height; r++){
filter_type = img[i];
i++;
for(int c = 0; c < stride; c++){
filt_a = c >= ihdr_info.bytesPerPixel ? pixels[r * stride + c - ihdr_info.bytesPerPixel] : 0;
filt_b = r > 0 ? pixels[(r - 1) * stride + c] : 0;
filt_c = r > 0 && c >= ihdr_info.bytesPerPixel ? pixels[(r - 1) * stride + c - ihdr_info.bytesPerPixel] : 0;
switch(filter_type){
case 0:
pixels[current_pixel] = img[i] & 0xff;
break;
case 1:
pixels[current_pixel] = (img[i] + filt_a) & 0xff;
break;
case 2:
pixels[current_pixel] = (img[i] + filt_b) & 0xff;
break;
case 3:
pixels[current_pixel] = (img[i] + filt_a + filt_c) & 0xff;
break;
case 4:
pixels[current_pixel] = (img[i] + PaethPredictor(filt_a, filt_b, filt_c)) & 0xff;
break;
}
current_pixel++;
i++;
}
}
return pixels;
}
These are the combinations of funtcions i use to achieve this. I first use a separate function which I know is not the problem and have therefore left out to get the bytes of the png file. I then call getChunksFromBytes() to gather the chunks of the png file, and I separate the IHDR from these chunks into a separate struct. Finally, I call getImgFromChunks() to uncompress the IDAT data, and getPixelsFromImg() to unfilter the uncompressed values.
First off, bytes per pixel is not a thing since pixels can be bits packed into bytes. So your calculation of uncompressed_size in getImgFromChunks() is wrong. It should be:
uLongf uncompressed_size = ihdr_data.height *
(1 + ((ihdr_data.bitd * ihdr_data.channels * (uLongf)ihdr_data.width + 7) >> 3));
Given that bits per pixel is not a thing, you need to rethink how you are doing getPixelsFromImg(). So there's no point in digging further here until you do that.
There is nothing wrong with your processing of multiple IDAT chunks. You may have misidentified the salient difference of the png file that is giving you issues.
I want to read an text file Using C Language.Here's the file:-
You see there is some pattern in the text content on the file.
0 means nothing. 9 means black. so there is coloring scheme from 0 to 9.
I have to create a bitmap image of this and the color are according to the values in the pattern. You have to adjust it with the 0-256 color scheme.
And the final output for this is shown below
Now see the pattern in the content of the text file is opposite to the final output bitmap file (not necessary). The darkness of the colors in bitmap image is according to the values in the pattern of the text content.
Anyone will tell me how I achieve this in C language.
I am able to create a BMP file but not according to the pattern in text file.
#include <stdio.h>
#include <stdlib.h>
int main()
{
char bitmap[1900];
// -- FILE HEADER -- //
// bitmap signature
bitmap[0] = 0x42;
bitmap[1] = 0x4d;
// file size
bitmap[2] = 58; // 40 + 14 + 12
bitmap[3] = 0;
bitmap[4] = 0;
bitmap[5] = 0;
int i=0;
// reserved field (in hex. 00 00 00 00)
for(i = 6; i < 10; i++) bitmap[i] = 0;
// offset of pixel data inside the image
for(i = 10; i < 14; i++) bitmap[i] = 0;
// -- BITMAP HEADER -- //
// header size
bitmap[14] = 40;
for(i = 15; i < 18; i++) bitmap[i] = 0;
// width of the image
bitmap[18] = 4;
for(i = 19; i < 22; i++) bitmap[i] = 0;
// height of the image
bitmap[22] = 1;
for(i = 23; i < 26; i++) bitmap[i] = 0;
// reserved field
bitmap[26] = 1;
bitmap[27] = 0;
// number of bits per pixel
bitmap[28] = 24; // 3 byte
bitmap[29] = 0;
// compression method (no compression here)
for(i = 30; i < 34; i++) bitmap[i] = 0;
// size of pixel data
bitmap[34] = 12; // 12 bits => 4 pixels
bitmap[35] = 0;
bitmap[36] = 0;
bitmap[37] = 0;
// horizontal resolution of the image - pixels per meter (2835)
bitmap[38] = 0;
bitmap[39] = 0;
bitmap[40] = 0b00110000;
bitmap[41] = 0b10110001;
// vertical resolution of the image - pixels per meter (2835)
bitmap[42] = 0;
bitmap[43] = 0;
bitmap[44] = 0b00110000;
bitmap[45] = 0b10110001;
// color pallette information
for(i = 46; i < 50; i++) bitmap[i] = 0;
// number of important colors
for(i = 50; i < 54; i++) bitmap[i] = 0;
// -- PIXEL DATA -- //
for(i = 54; i < 66; i++) bitmap[i] = 255;
FILE *file;
file = fopen("bitmap.bmp", "w+");
for(i = 0; i < 66; i++)
{
fputc(bitmap[i], file);
}
fclose(file);
return 0;
}
Here is a working code. I do not check some case of error (input file badly formatted, for example). I put some commentaries, though the code itself is not difficult to understand.
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <errno.h>
#include <ctype.h>
#define BMP_ASSERT(condition, message) \
do { \
if (! (condition)) { \
fprintf(stderr, __FILE__ ":%d: %s: Assertion `" #condition \
"` failed.\n\t: %s\n", __LINE__, __func__, message); \
exit(EXIT_FAILURE); \
} \
} while (false)
#define BMP_COLORMAP_SIZE 10
////////////////////////////////////////////////////////////////////////////////
// STRUCTS
typedef struct __attribute__((__packed__))
bmp_color
{
uint8_t r,
g,
b;
uint8_t :8;
} bmp_color_t;
typedef struct __attribute__((__packed__))
bmp_header_infos
{
uint32_t const info_size;
uint32_t width;
uint32_t height;
uint16_t const planes;
uint16_t const bpp;
uint32_t const compression;
uint32_t img_size;
uint32_t const horz_resolution;
uint32_t const vert_resolution;
uint32_t const n_colors;
uint32_t const n_important_colors;
} bmp_header_infos_t;
typedef struct __attribute__((__packed__))
bmp_header
{
/* Header */
char const signature[2];
uint32_t file_size;
uint32_t const :32; // reserved
uint32_t const img_offset;
/* Infos */
bmp_header_infos_t infos;
/* Color map */
bmp_color_t colormap[BMP_COLORMAP_SIZE];
} bmp_header_t;
typedef struct bmp_file_datas
{
size_t width;
size_t height;
/* Bit map */
uint8_t *bitmap;
} bmp_file_datas_t;
////////////////////////////////////////////////////////////////////////////////
// FUNCTIONS
/* Give a header with the right magic values */
bmp_header_t *
bmp_get_header(void)
{
static bmp_header_t _header = {
{'B', 'M'},
0u,
sizeof(_header),
{ // struct info
sizeof(_header.infos),
0u, 0u, // width, height
1u, // planes
8u, // bpp
0u, // no compression
0u, // img size
0u, 0u, // resolution
BMP_COLORMAP_SIZE,
BMP_COLORMAP_SIZE, // important colors
},
{{0u}}
};
bmp_header_t *header = malloc(sizeof(_header));
size_t i,
color;
assert(header != NULL);
memcpy(header, &_header, sizeof(*header));
// setting the scale of greys
for (i = 0 ; i < BMP_COLORMAP_SIZE ; ++i)
{
color = (i * 255) / BMP_COLORMAP_SIZE;
header->colormap[i] = (bmp_color_t){color, color, color};
}
return header;
}
/* Take all the file content and store it in a buffer */
char *
get_file_content(char const *filename)
{
FILE *file_handler = fopen(filename, "r");
size_t file_len;
char *buff;
BMP_ASSERT(file_handler != NULL, strerror(errno));
fseek(file_handler, 0, SEEK_END);
file_len = ftell(file_handler);
fseek(file_handler, 0, SEEK_SET);
buff = malloc(file_len + 1);
assert(buff != NULL);
fread(buff, file_len, 1, file_handler);
buff[file_len] = '\0';
fclose(file_handler);
return buff;
}
/* Get the greatest multiple of 4 that is >= size */
static inline size_t
multiple_of_four(size_t size)
{
while (size % 4)
++size;
return size;
}
/* Get the informations from buffer: size of line, number of lines */
void
get_file_infos(char *buff, bmp_header_t *header, bmp_file_datas_t *datas)
{
/* width & height */
header->infos.width = strchr(buff, '\n') - buff;
header->infos.height = strlen(buff) / (header->infos.width + 1);
// + 1 for the terminating '\n'
datas->width = multiple_of_four(header->infos.width);
datas->height = header->infos.height;
printf("File size: %u, %u\n", header->infos.width, header->infos.height);
/* image size & bitmap allocation */
header->infos.img_size = datas->width * datas->height;
datas->bitmap = malloc(header->infos.img_size * sizeof(*datas->bitmap));
assert(datas->bitmap != NULL);
header->file_size = header->img_offset + header->infos.img_size;
}
/* Take the informations from the buffer and store them in the bitmap */
void
write_bitmap(char *buff, bmp_file_datas_t *datas)
{
size_t ibuff,
iline = 0,
ibitmap = 0;
for (ibuff = 0 ; buff[ibuff] ; ++ibuff)
{
if (isdigit(buff[ibuff]))
{
datas->bitmap[ibitmap] = BMP_COLORMAP_SIZE - 1 - (buff[ibuff] - '0');
++ibitmap;
}
else if (buff[ibuff] == '\n')
{
++iline;
ibitmap = iline * datas->width;
}
}
}
/* Write the datas in the file: the header and the bitmap */
void
write_in_file(bmp_header_t *header,
bmp_file_datas_t *datas,
char const *filename)
{
FILE *file_handler = fopen(filename, "w");
BMP_ASSERT(file_handler != NULL, strerror(errno));
fwrite(header, sizeof(*header), 1, file_handler);
fwrite(datas->bitmap, header->infos.img_size, 1, file_handler);
fclose(file_handler);
}
int main(int argc, char **argv)
{
char *buff;
bmp_header_t *header;
bmp_file_datas_t datas;
if (argc != 3)
{
fprintf(stderr, "Usage: %s <input filename> <output filename>\n",
argv[0]);
return EXIT_FAILURE;
}
buff = get_file_content(argv[1]);
header = bmp_get_header();
get_file_infos(buff, header, &datas);
write_bitmap(buff, &datas);
write_in_file(header, &datas, argv[2]);
free(buff), free(header), free(datas.bitmap);
return EXIT_SUCCESS;
}
A crude method to achieve the required functionality would be: (Not really C, but then it is your homework not mine)
WIDTH = 0, HEIGHT = 0
if(LINE=READ_LINE(fin))
WIDTH = strlen(LINE)
++HEIGHT
else
ERROR!!!
PUSH(LINE)
while(LINE=READ_LINE(fin))
if(WIDTH != strlen(LINE))
ERROR!!!
else
++HEIGHT
PUSH(LINE)
WRITE_BMP_HEADER(WIDTH, HEIGHT)
for(h = 0; h < HEIGHT; ++h)
LINE = POP()
for(w = 0; w < WIDTH; ++w)
COLOR = (LINE[w] - '0') * 255 / 9;
WRITE_BMP_COLOR(COLOR)
WRITE_BMP_PADDING(W)
I am trying to apply DCT(discrete cosine transformation) compression on a bmp(bitmap) file. I have a c file which i am running in Turbo C++. This is not actually compressing but i was trying to implement the DCT and IDCT. The code is as follows:
/*
the image to be compressed is a bmp with 24 bpp and
with name "college4.bmp" of dimensions 200*160 ie 25*20- 8*8 blocks
o/p is college2.dat
format: 8 bit signed integers starting rowwise from 0,0 to 8,8
the coefficients order is blue,green,red
for the block no 1 then 2 and soon
*/
#include<stdlib.h>
#include<stdio.h>
#include<math.h>
#define WIDTH 25
#define HEIGHT 20
typedef struct {
unsigned int type;
unsigned long int filesize;
unsigned int reserved1,reserved2;
unsigned long int offset;
} BMPHEAD;
typedef struct {
unsigned long int infosize;
unsigned long int width,height;
unsigned int planes,bitsperpixel;
unsigned long int compression;
unsigned long int sizeimage;
long int xpelspermeter,ypelspermeter;
unsigned long int colorused,colorimportant;
} INFOHEAD;
typedef struct {
char rgbquad[4];
} colortable;
BMPHEAD bmphead;
INFOHEAD infohead;
FILE *bmp_fp1,*bmp_fp2;
int buf[WIDTH][8][8][3],buf1[WIDTH][8][8][3];
float pi=3.14159265,DCTcoeff[8][8][8][8];
void generatedctcoeff() {
int y, i, j, x;
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++) {
for (x = 0; x < 8; x++) {
for (y = 0; y < 8; y++) {
DCTcoeff[i][j][x][y] = cos(((2 * y + 1) * pi * j) / 16)
* cos(((2 * x + 1) * i * pi) / 16);
}
}
}
}
}
void outputtofile1() { // Write into college2.dat
int i, j, x, y, blockno; // One block at a time, buf contains pixel
int redcoef, greencoef, bluecoef; // data of one row of blocks
float gijred, gijgreen, gijblue, c, ci, cj;
c = 1 / (sqrt(2));
for (blockno = 0; blockno < WIDTH; blockno++) {
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++) {
gijred = 0;
gijgreen = 0;
gijblue = 0;
for (x = 0; x < 8; x++) {
for (y = 0; y < 8; y++) {
gijblue = gijblue + DCTcoeff[i][j][x][y]
* buf[blockno][x][y][0];
gijgreen = gijgreen + DCTcoeff[i][j][x][y]
* buf[blockno][x][y][1];
gijred = gijred + DCTcoeff[i][j][x][y]
* buf[blockno][x][y][2];
}
}
ci = cj = 1.0;
if (i == 0)
ci = c;
if (j == 0)
cj = c;
gijblue = ci * cj * gijblue / 4;
gijgreen = ci * cj * gijgreen / 4;
gijred = ci * cj * gijred / 4;
bluecoef = (int) gijblue;
greencoef = (int) gijgreen;
redcoef = (int) gijred;
fprintf(bmp_fp2, "%d %d %d ", bluecoef, greencoef, redcoef);
}
}
} /* end of one block processing */
}
void compressimage() {
int rowcount,x,y;
bmp_fp1=fopen("college4.bmp","r");
bmp_fp2=fopen("college2.dat","w");
printf("generating coefficients...\n");
generatedctcoeff();
if(bmp_fp1==NULL) {
printf("can't open");
return;
}
printf("compressing....\n");
fread(&bmphead,1,sizeof(bmphead),bmp_fp1);
fread(&infohead,1,sizeof(infohead),bmp_fp1);
fseek(bmp_fp1,bmphead.offset,SEEK_SET);
for(rowcount=0;rowcount<HEIGHT;rowcount++) {
for(y=0;y<8;y++) {
for(x=0;x<infohead.width;x++) {
buf[x/8][x%8][y][0]=(int)fgetc(bmp_fp1);
buf[x/8][x%8][y][1]=(int)fgetc(bmp_fp1);
buf[x/8][x%8][y][2]=(int)fgetc(bmp_fp1);
}
}
outputtofile1(); //output contents of buf after dct to file
}
fclose(bmp_fp1);
fclose(bmp_fp2);
}
void outputtofile2() { //output buf to college3.bmp
int i, j, x, y, blockno; // buf now contains coefficients
float pxyred, pxygreen, pxyblue, c, ci, cj; // a temp buffer buf1 used to
c = 1 / (sqrt(2)); // store one row of block of
for (blockno = 0; blockno < WIDTH; blockno++) { // decoded pixel values
for (x = 0; x < 8; x++)
for (y = 0; y < 8; y++) {
pxyred = 0;
pxygreen = 0;
pxyblue = 0;
for (j = 0; j < 8; j++) {
cj = 1.0;
if (j == 0)
cj = c;
for (i = 0; i < 8; i++) {
ci = 1.0;
if (i == 0)
ci = c;
pxyblue = pxyblue + ci * cj * DCTcoeff[i][j][y][x] * buf[blockno][i][j][0];
pxygreen = pxygreen + ci * cj
* DCTcoeff[i][j][y][x] * buf[blockno][i][j][1];
pxyred = pxyred + ci * cj * DCTcoeff[i][j][y][x] * buf[blockno][i][j][2];
}
}
pxyblue /= 4;
pxygreen /= 4;
pxyred /= 4;
buf1[blockno][y][x][0] = pxyblue;
buf1[blockno][y][x][1] = pxygreen;
buf1[blockno][y][x][2] = pxyred;
}
}
for (y = 0; y < 8; y++) {
for (blockno = 0; blockno < WIDTH; blockno++)
for (x = 0; x < 8; x++) {
fprintf(bmp_fp2, "%c%c%c", (char) buf1[blockno][x][y][0],
(char) buf1[blockno][x][y][1],
(char) buf1[blockno][x][y][2]);
}
}
}
void uncompressimage() {
int blue,green,red,rowcount,colcount,i,j;
bmp_fp1=fopen("college2.dat","r");
bmp_fp2=fopen("college3.bmp","w");
printf("generating coefficients...\n");
generatedctcoeff();
if (bmp_fp1==NULL) {
printf("open failed");
return;
}
printf("uncompressing....\n");
bmphead.type=0x4d42;
bmphead.filesize=30518;
bmphead.reserved1=0;
bmphead.reserved2=0;
bmphead.offset=sizeof(bmphead)+sizeof(infohead);
infohead.infosize=sizeof(infohead);
infohead.width=200;
infohead.height=160;
infohead.planes=1;
infohead.bitsperpixel=24;
infohead.compression=0;
infohead.sizeimage=0;
infohead.xpelspermeter=3780;
infohead.ypelspermeter=3780;
infohead.colorused=0;
infohead.colorimportant=0;
fwrite(&bmphead,sizeof(BMPHEAD),1,bmp_fp2);
fwrite(&infohead,sizeof(INFOHEAD),1,bmp_fp2);
for(rowcount=0;rowcount<HEIGHT;rowcount++) {
for(colcount=0;colcount<WIDTH;colcount++) {
for(i=0;i<8;i++) {
for(j=0;j<8;j++) {
fscanf(bmp_fp1,"%d",&blue);
fscanf(bmp_fp1,"%d",&green);
fscanf(bmp_fp1,"%d",&red);
buf[colcount][i][j][0]=blue;
buf[colcount][i][j][1]=green;
buf[colcount][i][j][2]=red;
}
}
}
outputtofile2();
}
fclose(bmp_fp1);
fclose(bmp_fp2);
}
int main() {
printf("opening files...\n");
compressimage();
printf("opening files...again\n");
uncompressimage();
printf("successful decompression\nenter any key\n");
return 0;
}
Here is the image i am using as input
(im srry the site converted the bmp into png. You may convert it back to bmp to use it)
Here is the image that is generated:
The file college3.bmp that gets created is of size 200x160 and of 93.8 kB but till quarter of the image it has decoded the coefficients correctly but later the file is filled with black pixels. I have taken a screenshot of the o/p as it was saying not a valid bmp while uploading. I am sitting on this problem since feb,2004. If anyone can say me where there is a bug i would be very thankful. I have analysed the output file and found an EOF right at the place where the pixels are starting to be black. I read some other questions on the topic and found that the conversion factors ci,cj have been used improperly. While coding i had also got confused with the indices x,y,i and j. So i hope this problem i will solve in a few days.
Apparently, the problem in the above code is in how you open your files.
This is what should be in your code (note the explicitly specified open modes, binary and text):
void compressimage() {
...
bmp_fp1=fopen("college4.bmp","rb");
bmp_fp2=fopen("college2.dat","wt");
...
}
void uncompressimage() {
...
bmp_fp1=fopen("college2.dat","rt");
bmp_fp2=fopen("college3.bmp","wb");
...
}
With that and slightly altered structure definitions:
#pragma pack(push,1)
typedef struct {
unsigned short int type;
unsigned long int filesize;
unsigned short int reserved1,reserved2;
unsigned long int offset;
} BMPHEAD;
typedef struct {
unsigned long int infosize;
unsigned long int width,height;
unsigned short int planes,bitsperpixel;
unsigned long int compression;
unsigned long int sizeimage;
long int xpelspermeter,ypelspermeter;
unsigned long int colorused,colorimportant;
} INFOHEAD;
typedef struct {
char rgbquad[4];
} colortable;
#pragma pack(pop)
I'm able to compile your program successfully using 3 different compilers (Turbo C++, Open Watcom, gcc) and get the desired output picture.
I have a doubt with cairo library.
I downloaded an image and I put it into a buffer memory. Is there any solution in cairo to load an image from data that there is in memory?
Thanks
Give a look to cairo_image_surface_create_for_data.
You can load image data from memory, but you need to lay out that memory in the correct format that Cairo expects.
For what you describe, it's probably easier to save the data in a tmpfile and let Cairo load it using FILE operations. Cairo recognizes more formats as filetypes than it does as in-memory structures.
When I used cairo_image_surface_create_for_data for bitmaps, I had to convert my byte-oriented Big-endian bitmap data into 32bit-word-oriented Little-endian rows.
You can tell from the littering of comments, that at times my efforts were reduced to hunt-and-peck, trial-and-error methods. But I got the desired output with this code. Steal from it what you can.
One more thing: The documentation for the in-memory formats (A8, RGB24, ARGB32) is in the .header files, not the reference manual.
enum { BIG, LITTLE } endian = LITTLE;
inline unsigned char reverse(unsigned char b) {
return (b&1 ? 0x80: 0)
| (b&2 ? 0x40: 0)
| (b&4 ? 0x20: 0)
| (b&8 ? 0x10: 0)
| (b&0x10 ? 8: 0)
| (b&0x20 ? 4: 0)
| (b&0x40 ? 2: 0)
| (b&0x80 ? 1: 0);
}
inline unsigned long wreverse(unsigned long w) {
return ( ( w &0xFF) << 24)
| ( ((w>>8) &0xFF) << 16)
| ( ((w>>16)&0xFF) << 8)
| ( ((w>>24)&0xFF) );
}
unsigned char abit[2] = { 0, 0xFF };
unsigned char aspeck[4] = { 0, 0x55, 0xAA, 0xFF };
unsigned char anibble[16] = { 0, 36, 72, 108, 144, 180, 216, 255 };
unsigned char *amap[] = { abit, aspeck, anibble };
void drawimage(state *st, int wid, int hgt, int bits, unsigned char *samp, unsigned char *tmap) {
int stride;
//stride = cairo_format_stride_for_width(CAIRO_FORMAT_A8, wid);
stride = cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, wid);
//stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, wid);
int n;
//unsigned char data[n=stride*hgt];
unsigned char data[n=stride*hgt*4];
memset(data, 0, n);
//unsigned char *data; data = calloc(n=stride*hgt, 1);
unsigned long *ldata = (void *)data;
int spo = 8/bits; /* samples per octet */
int span = wid/spo + (wid%spo?1:0); /* byte width */
int i,j;
for (i=0; i < hgt; i++) {
for (j=0; j < wid; j++) {
unsigned char t;
/*if (bits==8) t = samp[i*span + j/spo];
else*/ t = ( ( samp[i*span + j/spo] >> (/*7 -*/ (j%spo)/* *bits */) )
& (0xFF >> (8-bits)) ) /*<< (8-bits)*/;
if (bits < 8) t = amap[bits==1?0:bits==2?1:2][t];
t = tmap[t]; /* map value through the transfer map */
//printf("%2X ", t);
//data[i*stride + j] = t;
ldata[i*stride/4 + j] = /*0x80<<24 |*/ t<<16 | t<<8 | t;
}
//puts("");
}
/*
for (i=0; i < hgt; i++) {
//for (j=0; j < stride; j++)
//printf("%2X ", data[i*stride + j]);
for (j=0; j < stride/4; j++)
printf("%2lX ", ldata[i*stride/4 + j] & 0xFF);
puts("");
}
*/
cairo_surface_t *surf;
//surf = cairo_image_surface_create_for_data(data, CAIRO_FORMAT_A8, wid, hgt, stride);
surf = cairo_image_surface_create_for_data(data, CAIRO_FORMAT_RGB24, wid, hgt, stride);
//surf = cairo_image_surface_create_for_data(data, CAIRO_FORMAT_ARGB32, wid, hgt, stride);
//cairo_mask_surface(st->cr, surf, 0, 0);
cairo_set_source_surface(st->cr, surf, 0, 0);
cairo_paint(st->cr);
cairo_surface_flush(st->surface);
if (st->dis) XFlush(st->dis);
cairo_surface_destroy(surf);
//free(data);
}
OPFN_ void image(state *st, object w, object h, object bits, object mat, object proc) {
unsigned char tmap[256];
switch (bits.u.i) {
case 1: case 2: case 4: case 8: break;
default: error(st, rangecheck);
}
int n;
int i;
unsigned char data[n=w.u.i*h.u.i/(8/bits.u.i)];
/* map gray scale through the transfer function */
for (i = 0; i < 256; i++) {
object v;
v = consreal((double)i/255);
push(v);
pushe(consoper(st, "quit", NULL,0,0));
pushe(consoper(st, "exec", NULL,0,0));
pushe(consoper(st, "currenttransfer", NULL,0,0));
run(st);
v = pop();
if (v.tag==integertype) promote(v);
if (v.tag!=realtype) error(st, typecheck);
tmap[i] = v.u.r * 255;
}
for (i = 0; i < n; ) {
object s;
pushe(consoper(st, "quit", NULL,0,0));
pushe(proc);
run(st);
if (tos-os < 1) error(st, stackunderflow);
s = pop();
if (s.tag != stringtype) error(st, typecheck);
memcpy(&data[i], STR(s), s.u.c.n);
i += s.u.c.n;
}
if (DEBUG) { for (i=0; i<n; i++) { printf("%02x ", data[i]); } puts(""); }
if (st->cr) {
gsave(st);
cairo_new_path(st->cr);
cairo_rectangle(st->cr, 0, 0, 1, 1);
cairo_clip(st->cr);
{ cairo_matrix_t cm, icm;
psm2cm(st, mat, &cm);
cminvert(&cm, &icm);
cairo_transform(st->cr, &icm);
}
cairo_set_source_rgb(st->cr, 0.0, 0.0, 0.0);
drawimage(st, w.u.i, h.u.i, bits.u.i, data, tmap);
grestore(st);
}
}
Maybe you want something like gdk_pixbuf_new_from_data
http://developer.gnome.org/gdk-pixbuf/stable/gdk-pixbuf-Image-Data-in-Memory.html#gdk-pixbuf-new-from-data