I would like to create a large TIFF RGBA image using tiles. I wrote the following program which loops over the positions of the tiles, but the resulting image is always transparent. Why ?
#include <math.h>
#include <stdlib.h>
#include "tiffio.h"
int main(int argc,char** argv)
{
uint32 width=400, height=400;
uint32 tileWidth=16, tileHeight=16;
TIFF* tif = TIFFOpen("foo.tif", "w");
int i,j,x;
int spp=4;
int bps = 8;
TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, width);
TIFFSetField(tif, TIFFTAG_IMAGELENGTH, height);
TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL,spp);//R G B A
TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bps);
TIFFSetField(tif, TIFFTAG_TILEWIDTH, tileWidth);
TIFFSetField(tif, TIFFTAG_TILELENGTH, tileHeight);
TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
int tilesize = tileWidth * tileHeight * bps/8 * spp;
uint8 *buf = malloc(tilesize);
for ( j = 0; j < width; j += tileWidth) {
for ( i = 0; i < height; i += tileHeight)
{
for ( x = 0; x < tilesize; x+=spp)
{
uint8 a = 100;
buf[x+0] =a;
buf[x+1] =a;
buf[x+2] =a;
buf[x+3] =a;
}
if(TIFFWriteTile(tif, buf, i, j, 0, 0)<0) exit(-1);
}
}
free(buf);
TIFFClose(tif);
return 0;
}
Related
I'm trying to implement Hough algorithm using C programming language and 2D raw image.
I have written the code in order to get separate output image for edge detection and Hough transform. When I do edge detection only I'm getting the proper edge detected output image. But here I'm getting the output raw image of size 0KB.I'm not getting where I made mistake.
Can anybody please help me to rectify this problem and give idea for further development such as draw line based on Hough space for the below code.
Thank you in advance.
#include <stdio.h>
#include <math.h>
#define PI 3.14159265
void
hough_transform(unsigned char out[256][256], unsigned char h_out[][256],
int w, int h)
{
int i, j;
int thetaDeg;
float thetaRad;
int rho;
int distMax;
int thetamax;
distMax = sqrt((h * h) + (w * w));
thetamax = 360;
int Acc[180][180];
for (i = 0; i < w; i++) {
for (j = 0; j < h; j++) {
if (out[i][j] > 0) {
for (thetaDeg = 0; thetaDeg < thetamax; ++thetaDeg) {
thetaRad = thetaDeg * (PI / 180);
rho = i * cos(thetaRad) + j * sin(thetaRad);
// find rho value that is closest to this
if (distMax < rho) {
int min = abs(rho - distMax);
}
if (distMax <= 1) {
// Increment a value in an accumulator array
Acc[rho][thetaDeg] += 1;
}
}
}
}
}
for (rho = 0; rho < distMax; rho++) {
for (thetaDeg = 0; thetaDeg < thetamax; thetaDeg++) {
h_out[rho][thetaDeg] = Acc[rho][thetaDeg];
}
}
}
void
edge_detect(unsigned char input[256][256], unsigned char out[][256],
int width, int height)
{
int in[3][3] = { {1, 2, 1}, {0, 0, 0}, {-1, -2, -1} };
int pixel;
int i;
int j;
int x;
int y;
for (y = 1; y < height - 1; y++) {
for (x = 1; x < width - 1; x++) {
pixel = 0;
for (j = -1; j <= 1; j++) {
for (i = -1; i <= 1; i++) {
pixel += in[j + 1][i + 1] * input[y + j][x + i];
}
}
out[y][x] = (unsigned char) abs(pixel);
}
}
}
int
main()
{
FILE *fp;
FILE *fp1;
FILE *fp2;
unsigned char input[256][256];
unsigned char out[256][256];
unsigned char h_out[256][256];
int width = 256;
int height = 256;
fp = fopen("Image.raw", "rb");
fp1 = fopen("output.raw", "wb");
fp2 = fopen("h_output.raw", "wb");
fread(input, 256 * 256, 1, fp);
edge_detect(input, out, width, height);
hough_transform(out, h_out, width, height);
fwrite(out, 256 * 256, 1, fp1);
fwrite(h_out, 256 * 256, 1, fp2);
fclose(fp);
fclose(fp1);
fclose(fp2);
return (0);
}
I would like to create a dual array of texture with the dynamic memory allocation, but, my program crash during the second initialization of them.
To add, I don't know what to write like argument in my fonction because I don't know the length of the last array.
I have two kind of levels. The levels of the adventure and the edited levels.
This is my code :
#include <stdlib.h>
#include <stdio.h>
#include <SDL.h>
void initializePreviewLevels(SDL_Texture ***texture, char **prefix, int type, int numberLevels, SDL_Renderer *renderer);
int main(int argc, char *argv[])
{
SDL_Window *window = NULL;
SDL_Renderer *renderer = NULL;
SDL_Texture *textureLevels[2];
int i, numberLevels[2];
char prefixNameFileLevels[][2] = {"lvl", "edited-lvl"};
SDL_Init(SDL_INIT_VIDEO);
SDL_CreateWindowAndRenderer(0, 0, SDL_WINDOW_MAXIMIZED|SDL_WINDOW_RESIZABLE, window, renderer);
for (i = 0; i < 2; ++)
{
numberLevels[i] = 10;
textureLevels[i] = malloc(numberLevels[i] * sizeof(SDL_Texture*));
if (textureLevels[i] == NULL)
exit(EXIT_FAILURE);
initializePreviewLevels(textureLevels, prefixNameFileLevels[i], i, numberLevels[i], renderer);
}
for(i = 0; i < 2; i++)
SDL_DestroyTexture(textureLevels[i]);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
void initializePreviewLevels(SDL_Texture ***texture, char **prefix, int type, int numberLevels, SDL_Renderer *renderer)
{
int number, currentDigit, j, k, l, numberDigits = 1, i, prefixLength;
char pictureName[100], end[] = ".bmp";
SDL_Surface *picture;
if (type)
prefixLength = 7;
else
prefixLength = 2;
strcpy(pictureName, prefixe);
for(i = 1; i <= nombreNiveaux; i++)
{
number = i;
while(number >= 10)
{
number /= 10;
numberDigits++;
}
number = i;
for(j = numberDigits-1; j >= 0; j --)
{
currentNumber = number%10;
number /= 10;
pictureName[prefixLength+j] = currentNumber+48;
if (j == 0)
{
k = prefixLength + numberDigits;
for (l = 0; l < 4; l++)
pictureName[k+l] = end[l];
pictureName[k+l+1] = '\0';
}
}
picture = SDL_LoadBMP(pictureName);
texture[type][i-1] = SDL_CreateTextureFromSurface(renderer, picture);
}
SDL_FreeSurface(picture);
}
EDIT : I add a pointer on my fonction. It was a typo.
hey I need a little help with my code, I read a ppm file, change the colors to black and white and want to save it to a new file. I could read the header of my file and write it to the new file but I've struggles with changing the colors. I know that I can get the grey value with the formula: 0.299 * red component + 0.587 * green component + 0.114 * blue component. Does anyone know how I can write this as a code?
int main(int argc, char **argv)
{
FILE *oldFile, *newFile;
int width, height, max_colour;
oldFile = fopen("oldpic.ppm","rb");
newFile = fopen("newpic.ppm","wb");
fscanf (oldFile, "P6\n %d %d %d", &width, &height, &max_colour);
unsigned char *data = malloc(width*height);
fread(data,1,width*height,oldFile);
fprintf(newFile, "P6\n%d %d\n%d\n", width, height, max_colour);
for (int j = 0; j < width; ++j)
{
for (int i = 0; i < height; ++i)
{
unsigned char color[3];
color[0] = 0.299 * ? + 0.587 * ? + 0.114 * ?; /* red */
color[1] = 0.299 * ? + 0.587 * ? + 0.114 * ?; /* green */
color[2] = 0.299 * ? + 0.587 * ? + 0.114 * ?; /* blue */
(void) fwrite(color, 1, 3, newFile);
}
}
(void) fclose(newFile);
return 0;
}
You probably want scaled binary arithmetic.
Also, even though you can read the input data into a large array, it may be easier to read it and process it a pixel at a time.
Here's your code reworked to do just that:
int
main(int argc, char **argv)
{
FILE *oldFile;
FILE *newFile;
int width;
int height;
int max_colour;
oldFile = fopen("oldpic.ppm", "rb");
newFile = fopen("newpic.ppm", "wb");
fscanf(oldFile, "P6\n %d %d %d", &width, &height, &max_colour);
#if 0
unsigned char *data = malloc(width * height);
fread(data, 1, width * height, oldFile);
#endif
fprintf(newFile, "P6\n%d %d\n%d\n", width, height, max_colour);
for (int j = 0; j < width; ++j) {
for (int i = 0; i < height; ++i) {
unsigned char color[3];
unsigned int grey;
fread(color, 1, 3, oldFile);
grey = 0;
grey += 299u * color[0]; // red
grey += 586u * color[1]; // green
grey += 114u * color[2]; // blue
grey /= 1000;
color[0] = grey;
color[1] = grey;
color[2] = grey;
fwrite(color, 1, 3, newFile);
}
}
fclose(oldFile);
fclose(newFile);
return 0;
}
I've wanted to create program that generates fractals on my GPU.
First I created a working project in C, after that I tried to convert it into CUDA/C.
Unfortunately, after I did it I saw that there is a difference in results of CPU and GPU.
I spend few hours thinking what I did wrong and it's a mystery to me.
IMO: It seems that there is a difference of calculating values in while loop, therefore it ends earlier than in normal CPU function.
Question: is there any possibility that it is true? And if, what can I do to avoid that kind of computing error?
Here's my entire code:
// C libs
#include <stdint.h>
#include <stdio.h>
#include <iostream>
// Help libs
#include <windows.h>
#include <math.h>
// CUDA libs
#include "cuda.h"
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
__global__ void calulateFractal(unsigned char *a, int N, double c_re, double c_im, int width, int height, double minX, double maxX, double minY, double maxY, double ratioX, double ratioY, int maxLevel)
{
int i = blockIdx.x * blockDim.x + threadIdx.x;
if(i < N)
{
int x = i % width;
int y = i / width;
double p_im = y * ratioY + minY;
double p_re = x * ratioX + minX;
double z_re = p_re;
double z_im = p_im;
int iteration = 0;
while ((z_re * z_re + z_im * z_im) < 4 && iteration < maxLevel)
{
double tmp_re = z_re * z_re - z_im * z_im + c_re;
double tmp_im = 2 * z_re * z_im + c_im;
z_re = tmp_re;
z_im = tmp_im;
iteration++;
}
a[i] = iteration;
}
}
void calulateFractalCPU(unsigned char *a, int i, double c_re, double c_im, int width, int height, double minX, double maxX, double minY, double maxY, double ratioX, double ratioY, int maxLevel)
{
int x = i % width;
int y = i / width;
double p_im = y * ratioY + minY;
double p_re = x * ratioX + minX;
double z_re = p_re;
double z_im = p_im;
int iteration = 0;
while ((z_re * z_re + z_im * z_im) < 4 && iteration < 99)
{
double tmp_re = z_re * z_re - z_im * z_im + c_re;
double tmp_im = 2 * z_re * z_im + c_im;
z_re = tmp_re;
z_im = tmp_im;
iteration++;
}
a[i] = iteration;
}
int saveFractalToBitmap(unsigned char **colorsArray, unsigned char *bitmap, int width, int height, char *filename)
{
// Bitmap structures to be written to file
BITMAPFILEHEADER bfh;
BITMAPINFOHEADER bih;
// Fill BITMAPFILEHEADER structure
memcpy((char *)&bfh.bfType, "BM", 2);
bfh.bfSize = sizeof(bfh) + sizeof(bih) + 3*height*width;
bfh.bfReserved1 = 0;
bfh.bfReserved2 = 0;
bfh.bfOffBits = sizeof(bfh) + sizeof(bih);
// Fill BITMAPINFOHEADER structure
bih.biSize = sizeof(bih);
bih.biWidth = width;
bih.biHeight = height;
bih.biPlanes = 1;
bih.biBitCount = 24;
bih.biCompression = BI_RGB; // uncompressed 24-bit RGB
bih.biSizeImage = 0; // can be zero for BI_RGB bitmaps
bih.biXPelsPerMeter = 3780; // 96dpi equivalent
bih.biYPelsPerMeter = 3780;
bih.biClrUsed = 0;
bih.biClrImportant = 0;
// Open bitmap file (binary mode)
FILE *f;
f = fopen(filename, "wb");
if(f == NULL)
return -1;
// Write bitmap file header
fwrite(&bfh, 1, sizeof(bfh), f);
fwrite(&bih, 1, sizeof(bih), f);
// Write bitmap pixel data starting with the
// bottom line of pixels, left hand side
for (int i = 0; i < width * height ; i++)
{
// Write pixel components in BGR order
fputc(colorsArray[bitmap[i]][2], f);
fputc(colorsArray[bitmap[i]][1], f);
fputc(colorsArray[bitmap[i]][0], f);
}
// Close bitmap file
fclose(f);
return 0;
}
int main()
{
unsigned char **colorsArray;
unsigned char *fractalLevelsCPU;
unsigned char *fractalLevelsGPU;
double minX = -1.7;
double maxX = 1.7;
double minY = -1.5;
double maxY = 1.5;
double input_re = -0.79;
double input_im = 0.1463;
int width = 10;
int height = 5;
int N = width * height;
int maxLevel = 100;
size_t levelsArraySize = N * sizeof(unsigned char);
double ratioX = (maxX - minX) / (double) width;
double ratioY = (maxY - minY) / (double) height;
bool gpu = true;
// Allocate memory
colorsArray = (unsigned char**) malloc((maxLevel+1) * sizeof(unsigned char*));
for(int i=0; i<=maxLevel; i++)
{
colorsArray[i] = (unsigned char *) malloc(3 * sizeof(unsigned char));
colorsArray[i][0] = (int) (255.0 * i / maxLevel);
colorsArray[i][1] = (int) (255.0 * i / maxLevel);
colorsArray[i][2] = (int) (255.0 * log((double) i) / log((double) maxLevel));
}
fractalLevelsCPU = (unsigned char*) malloc(levelsArraySize);
cudaMalloc((unsigned char **) &fractalLevelsGPU, levelsArraySize);
cudaMemcpy(fractalLevelsCPU, fractalLevelsGPU, levelsArraySize, cudaMemcpyHostToDevice);
if(gpu)
{
// Run GPU method
calulateFractal <<< 1, N >>> (fractalLevelsGPU, N, input_re, input_im, width, height, minX, maxX, minY, maxY, ratioX, ratioY, maxLevel);
// Copy data from GPU to CPU array
cudaMemcpy(fractalLevelsCPU, fractalLevelsGPU, levelsArraySize, cudaMemcpyDeviceToHost);
}
else
{
// Iterate every element in array and compute level of fractal
for(int i=0; i<N; i++)
{
calulateFractalCPU(fractalLevelsCPU, i, input_re, input_im, width, height, minX, maxX, minY, maxY, ratioX, ratioY, maxLevel);
}
}
// Show results
for(int i=0; i<N; i++)
{
if((i % width) == 0)
printf("\n");
printf("%d\t", fractalLevelsCPU[i]);
}
//saveFractalToBitmap(colorsArray, fractalLevelsCPU, width, height, "frac.bmp");
// Free memory
for(int i=0; i<=maxLevel; i++)
{
free(colorsArray[i]);
}
free(colorsArray);
free(fractalLevelsCPU);
cudaFree(fractalLevelsGPU);
return 0;
}
I've find solution to my problem.
First of all, number of threads per block should be a power of two number.
Also I realized that my GPU has it's limits for number of threads per block and blocks itself.
NVIDIA Utils showed me that I can use max 65536 blocks and 512 threads per block.
Solution:
int threadsPerBlock = 512;
int blocksNumber = N/threadsPerBlock + (N % threadsPerBlock == 0 ? 0:1);
if(blocksNumber > 65536)
return -1;
calulateFractal <<< blocksNumber, threadsPerBlock >>> (fractalLevelsGPU, N, input_re, input_im, width, height, minX, maxX, minY, maxY, ratioX, ratioY, maxLevel);
I am trying to understand images some more, and I'm having a great deal of trouble. From using matlab, I have experience in using imread('test.tif'), and getting a beautiful matrix of rows vs. columns, where you have the intensity of each pixel as an integer. So, a 720 x 250 image will give a 720 x 250 matrix, where each cell contains the intensity of the pixel, on a scale from 0-255 (depending on the data type). So, 0 was black, 255 was white.
It was so simple and made so much sense. Now I am attempting to use libtiff, and I am really struggling. I want to do the same thing--access those pixels, and I just can't get it.
I have the following code:
int main(int argc, char *argv[]){
TIFF* tif = TIFFOpen( argv[1], "r");
FILE *fp = fopen("test2.txt", "w+");
if (tif) {
int * buf;
tstrip_t strip;
uint32* bc;
uint32 stripsize;
TIFFGetField( tif, TIFFTAG_STRIPBYTECOUNTS, &bc);
stripsize = bc[0];
buf = _TIFFmalloc(stripsize);
for(strip = 0; strip < TIFFNumberOfStrips(tif); strip++ ) {
if( bc[strip] > stripsize) {
buf = _TIFFrealloc(buf, bc[strip]);
stripsize = bc[strip];
}
TIFFReadRawStrip(tif, strip, buf, bc[strip]);
}
int i;
for (i=0; i<stripsize; i++) {
if ( i % 960 ==0 )
fprintf(fp, "\n");
fprintf(fp,"%d ", buf[i]);
}
_TIFFfree(buf);
TIFFClose(tif);
}
exit(0);
}
But I get completely meaningless results--just completely wacked out numbers. Nothing like the numbers I see when I load the image in matlab.
How can I simply access the pixel values, and look at them?
Thanks so much.
I think you should read Using The TIFF Library article. It contains enough information to get started with libtiff.
Here is some code to read image scanlines and print values of each sample.
main()
{
TIFF* tif = TIFFOpen("myfile.tif", "r");
if (tif) {
uint32 imagelength;
tsize_t scanline;
tdata_t buf;
uint32 row;
uint32 col;
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &imagelength);
scanline = TIFFScanlineSize(tif);
buf = _TIFFmalloc(scanline);
for (row = 0; row < imagelength; row++)
{
TIFFReadScanline(tif, buf, row);
for (col = 0; col < scanline; col++)
printf("%d ", buf[col]);
printf("\n");
}
_TIFFfree(buf);
TIFFClose(tif);
}
}
Regarding this article, I think it'll be better to use TIFFRGBAImage approach, because as it turned out TIFF file could be one of different formats: tiled, scanline-based and strip-oriented. Here's an example from the same article.
TIFF* tif = TIFFOpen(argv[1], "r");
if (tif) {
uint32 w, h;
size_t npixels;
uint32* raster;
TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w);
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h);
npixels = w * h;
raster = (uint32*) _TIFFmalloc(npixels * sizeof (uint32));
if (raster != NULL) {
if (TIFFReadRGBAImage(tif, w, h, raster, 0)) {
...process raster data...
}
_TIFFfree(raster);
}
TIFFClose(tif);
}
raster is a uint32 array (maximum value= 0xffffffff)
but you are trying to read a 16-bit array (maximum value 0xffff).
you will run into 32bit to 16bit conversion problems.
Reading the scanline method is the better way to do it.
This way you can convert the void* buf to uint16* and access the pixel values.
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <inttypes.h>
#include "tiffio.h"
using namespace std;
void printArray(uint16 * array, uint16 width);
int main()
{
TIFF* tif = TIFFOpen("16bit_grayscale_image.tif", "r");
if (tif) {
uint32 imagelength,height;
tdata_t buf;
uint32 row;
uint32 config;
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &imagelength);
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height);
TIFFGetField(tif, TIFFTAG_PLANARCONFIG, &config);
buf = _TIFFmalloc(TIFFScanlineSize(tif));
uint16 s, nsamples;
uint16* data;
TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &nsamples);
for (s = 0; s < nsamples; s++)
{
for (row = 0; row < imagelength; row++)
{
TIFFReadScanline(tif, buf, row, s);
data=(uint16*)buf;
printArray(data,imagelength);
}
// printArray(data,imagelength,height);
}
_TIFFfree(buf);
TIFFClose(tif);
}
exit(0);
}
void printArray(uint16 * array, uint16 width)
{
uint32 i;
for (i=0;i<width;i++)
{
printf("%u ", array[i]);
}
printf("\n");
}