Compress multipage tiff - matlab

For faster loading of images in MATLAB I am using multi-page TIFF files which for me work much faster than MATLAB's simple imread. But my problem is that the size of the TIFF file is way bigger than normal images ( like ten times more ) so I'm looking in compression options. I have tried some of those options ( with the code I attached below ) some of them don't work and produce empty files and the rest kill the speed.
Is there any way to have both size and speed?
Thank you
P.S: I put my codes here. If I'm doing sth wrong please tell me.
#include <stdio.h>
#include <time.h>
#include "tiffio.h"
#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
using namespace std;
#define XSIZE 1280
#define YSIZE 720
#define NPAGES 1000
#define CHANNEL 3
int main (int argc, char **argv)
{
uint32 image_width, image_height;
float xres, yres;
uint16 spp, bpp, photo, res_unit;
TIFF *out;
int i, j;
uint16 page;
Mat img;
int COMPRESSION_TAG = atoi(argv[1]);
unsigned char *array = new unsigned char [XSIZE * YSIZE*3];
char name[20];
out = TIFFOpen("myfile.tif", "w");
image_width = XSIZE;
image_height = YSIZE;
spp = CHANNEL; /* Samples per pixel */
bpp = 8; /* Bits per sample */
photo = PHOTOMETRIC_MINISBLACK;
for (page = 0; page < NPAGES; page++)
{
sprintf(name, "5_29%03d.jpg", page);
img = imread(name);
array = img.data;
TIFFSetField(out, TIFFTAG_IMAGEWIDTH, image_width );
TIFFSetField(out, TIFFTAG_IMAGELENGTH, image_height);
TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, bpp);
TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, spp);
TIFFSetField(out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
TIFFSetField(out, TIFFTAG_PHOTOMETRIC, photo);
TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_BOTLEFT);
TIFFSetField(out, TIFFTAG_COMPRESSION, COMPRESSION_TAG);
/* It is good to set resolutions too (but it is not nesessary) */
xres = yres = 100;
res_unit = RESUNIT_INCH;
TIFFSetField(out, TIFFTAG_XRESOLUTION, xres);
TIFFSetField(out, TIFFTAG_YRESOLUTION, yres);
TIFFSetField(out, TIFFTAG_RESOLUTIONUNIT, res_unit);
/* We are writing single page of the multipage file */
TIFFSetField(out, TIFFTAG_SUBFILETYPE, FILETYPE_PAGE);
/* Set the page number */
TIFFSetField(out, TIFFTAG_PAGENUMBER, page, NPAGES);
for (j = 0; j < image_height; j++)
TIFFWriteScanline(out, &array[3*j * image_width], j, 0);
TIFFWriteDirectory(out);
}
TIFFClose(out);
return 0;
}

Related

When approaching the gpio register address of RaspberryPi, why is the result different between unsigned int* and char*?

Using mmap(), I am going to write a value to the GPIO register address of the Raspberry Pi.
I thought the register value would have the same when reading mapped GPIO address in unsigned int * or char *, but it was not. I compared the results for both cases.
This is my code.
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#define GPIO_BASE 0x3F200000
#define GPFSEL1 0x04
#define GPSET0 0x1C
#define GPCLR0 0x28
int main()
{
int fd = open("/dev/mem", O_RDWR|O_SYNC);
// Error Handling
if (fd < 0) {
printf("Can't open /dev/mem \n");
exit(1);
}
// Map pages of memory
char *gpio_memory_map = (char*)mmap(0, 4096, PROT_READ|PROT_WRITE,
MAP_SHARED, fd, GPIO_BASE);
// Error Handling
if (gpio_memory_map == MAP_FAILED) {
printf("Error : mmap \n");
exit(-1);
}
// GPIO18
//volatile unsigned int *gpio = (volatile unsigned int*)gpio_memory_map;
//gpio[GPFSEL1/4] = (1<<24);
volatile char *gpio = (volatile char *)gpio_memory_map;
int i;
for (i = 0; i < 16; i++)
printf("gpio[%d](%#x) = %#0x\n", i, &gpio[i], gpio[i]);
/*
for (i = 0; i < 5; i++) {
gpio[GPCLR0 / 4] = (1 << 18);
sleep(1);
gpio[GPSET0 / 4] = (1 << 18);
sleep(1);
}
*/
// Unmap pages of memory
munmap(gpio_memory_map, 4096);
return 0;
}
And those below are the results.
volatile unsigned int *gpio = (volatile unsigned int *)gpio_memory_map;
gpio[0](0x76f12000) = 0x1
gpio[1](0x76f12004) = 0x1000000
gpio[2](0x76f12008) = 0
gpio[3](0x76f1200c) = 0x3fffffc0
gpio[4](0x76f12010) = 0x24000924
gpio[5](0x76f12014) = 0x924
gpio[6](0x76f12018) = 0
gpio[7](0x76f1201c) = 0x6770696f
gpio[8](0x76f12020) = 0x6770696f
gpio[9](0x76f12024) = 0x6770696f
gpio[10](0x76f12028) = 0x6770696f
gpio[11](0x76f1202c) = 0x6770696f
gpio[12](0x76f12030) = 0x6770696f
gpio[13](0x76f12034) = 0x2ffbbfff
gpio[14](0x76f12038) = 0x3ef4ff
gpio[15](0x76f1203c) = 0
volatile char *gpio = (volatile char *)gpio_memory_map;
As the result #1 above, I thought gpio[1], gpio[2], gpio[3] should be 0. But it was different. And even if I try to write a new value on gpio[1] or gpio[2] or gpio[3], it stays the same. Why are the results different when approaching char * and unsigned char *?
gpio[0](0x76f47000) = 0x1
gpio[1](0x76f47001) = 0x69
gpio[2](0x76f47002) = 0x70
gpio[3](0x76f47003) = 0x67
gpio[4](0x76f47004) = 0
gpio[5](0x76f47005) = 0x69
gpio[6](0x76f47006) = 0x70
gpio[7](0x76f47007) = 0x67
gpio[8](0x76f47008) = 0
gpio[9](0x76f47009) = 0x69
gpio[10](0x76f4700a) = 0x70
gpio[11](0x76f4700b) = 0x67
gpio[12](0x76f4700c) = 0xc0
gpio[13](0x76f4700d) = 0x69
gpio[14](0x76f4700e) = 0x70
gpio[15](0x76f4700f) = 0x67

Cairo: Draw an array of pixels

I'm just starting to explore Cairo, but right now I really want to use it for something very simple.
I have a very low-tech bitmap, i.e., a 3*X*Y array of numbers. I'd like to use Cairo to make this into a bitmap and write to a file. I'm looking through tutorials and I'm not seeing a way to use it for comparatively low-level functions like this.
I don't think I need guidance on how to use the tool once I know what the tool is.
I didn't actually test this, but the following should give you lots of useful hints:
#include <cairo.h>
#include <stdint.h>
#define WIDTH 42
#define HEIGHT 42
uint8_t data[WIDTH][HEIGHT][3];
cairo_surface_t* convert()
{
cairo_surface_t *result;
unsigned char *current_row;
int stride;
result = cairo_image_surface_create(CAIRO_FORMAT_RGB24, WIDTH, HEIGHT);
if (cairo_surface_status(result) != CAIRO_STATUS_SUCCESS)
return result;
cairo_surface_flush(result);
current_row = cairo_image_surface_get_data(result);
stride = cairo_image_surface_get_stride(result);
for (int y = 0; y < HEIGHT; y++) {
uint32_t *row = (void *) current_row;
for (int x = 0; x < WIDTH; x++) {
uint32_t r = data[x][y][0];
uint32_t g = data[x][y][1];
uint32_t b = data[x][y][2];
row[x] = (r << 16) | (g << 8) | b;
}
current_row += stride;
}
cairo_surface_mark_dirty(result);
return result;
}

Unable to link external lib (CLAPACK) using MATLAB mex

I'm new to mex and this problem spent me days but I still cannot figure out what to do.
I create la_test.cpp file to test one of the subroutines in CLAPCK: cgemm_ (complex matrix-matrix multiplication). Here is the code:
#include "mex.h"
#include "matrix.h"
#include <string.h>
#include <stdlib.h>
#include <malloc.h>
#include <iostream>
#include <stdio.h>
#include "f2c.h"
#include "clapack.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
float *Xr,*Xi; // To store the input data
float *zsr,*zsi; // To store the output
long int m,n;
complex *A;
Xr = (float *) mxGetPr(prhs[0]);
Xi = (float *) mxGetPi(prhs[0]);
size_t K = mxGetNumberOfDimensions(prhs[0]);
const int *size = mxGetDimensions(prhs[0]);
m = mxGetM(prhs[0]);
n = mxGetN(prhs[0]);
A = new complex[m*n];
complex one = {1.0f, 0.0f}, zero = {0.0f, 0.0f};
for (int i=0; i<m; i++){
for (int j=0; j<n; j++){
complex rc = {Xr[j + n*i], Xi[j + n*i]};
A[j + n*i] = rc;
}
}
plhs[0] =(mxArray *) mxCreateDoubleMatrix( n, n, mxCOMPLEX );
zsr = (float *) mxGetPr(plhs[0]);
zsi = (float *) mxGetPi(plhs[0]);
complex *AtA = 0;
AtA = new complex[n*n];
char *chn = "N";
char *chc = "C";
cgemm_(chc, chn, &n, &n, &m, &one, A, &m, A, &m, &zero, AtA, &n);
for (int i=0; i<m; i++){
for (int j=0; j<n; j++){
zsr[j + n*i] = AtA[j + n*i].r;
zsi[j + n*i] = AtA[j + n*i].i;
}
}
}
Basically, I store input matrix into A and try to compute A'*A. Header files: f2c.h, clapack.h as well as three 64bit libraries: blas.lib, libf2c.lib and lapack.lib from http://icl.eecs.utk.edu/lapack-for-windows/clapack/index.html#install are all in the same file of la_test.cpp. I'm working on Windows 7 64bit system with matlab r2013a and Visual Studio 2012.
I have tried with both:
mex la_test.cpp lapack.lib libf2c.lib blas.lib
and
mex -llapack -llibf2c -lblas -L"C:\Users\Ziwu\Desktop\la_test" la_test.cpp
all with following error:
Creating library C:\Users\Ziwu\AppData\Local\Temp\mex_epl230\templib.x and object C:\Users\Ziwu\AppData\Local\Temp\mex_epl230\templib.exp
la_test.obj : error LNK2019: unresolved external symbol cgemm_ referenced in function mexFunction
la_test.mexw64 : fatal error LNK1120: 1 unresolved externals
I've checked on Internet for long time, but found no solution yet!
Please help me if you have any advice.

fwrite with BMP file returning 0 and segmentation fault

I'm trying to read a simple bmp file then invert the color then save it back to the file system using fread and fwrite binary mode.
So I did
BMP_Image * img;
BMP_Header * hdr;
fread(hdr,sizeof(BMP_Header),1, fptr);
img->width = hdr->width;
img->height = hdr->height;
img->bytes_per_pixel = hdr->bits*BIT_TO_BYTE;
img->header = *hdr;
img->data_size = hdr->size;
to get the header information where BMP_Header is a struct
Then read the image data and put into array
fread(data, sizeof(char), img->data_size - 54, fptr);
Then I subtract each element in my image data by 255
int i = 0;
for(i = 0;i<img->data_size;i++){
data[i] = 255 - data[i];
}
Now when I want to write the file back to the file system, I couldn't get it to work properly. I know you'd have to do fwrite 2 times. First writing the header, then writing the image data.
I have so far:
fwrite(header, 1 ,dataSize, fptr_out);
which gives me sgmentation fault and 0 byte bmp file.
Here are the typedefs of my BMP_Header and BMP_image struct
typedef unsigned short int uint16_t;
typedef unsigned int uint32_t;
typedef int int32_t;
typedef struct {
uint16_t type; // Magic identifier
uint32_t size; // File size in bytes
uint16_t reserved1; // Not used
uint16_t reserved2; // Not used
uint32_t offset; // Offset to image data in bytes
uint32_t header_size; // Header size in bytes
int32_t width; // Width of the image
int32_t height; // Height of image
uint16_t planes; // Number of color planes
uint16_t bits; // Bits per pixel
uint32_t compression; // Compression type
uint32_t imagesize; // Image size in bytes
int32_t xresolution; // Pixels per meter
int32_t yresolution; // Pixels per meter
uint32_t ncolours; // Number of colors
uint32_t importantcolours; // Important colors
} BMP_Header;
typedef struct {
BMP_Header header;
int data_size;
int width;
int height;
int bytes_per_pixel; // This amount should be equals to number of bits/8
char *data;
} BMP_Image;

Encoding images to video with ffmpeg

I am trying to encode series of images to one video file. I am using code from api-example.c, its works, but it gives me weird green colors in video. I know, I need to convert my RGB images to YUV, I found some solution, but its doesn't works, the colors is not green but very strange, so thats the code:
// Register all formats and codecs
av_register_all();
AVCodec *codec;
AVCodecContext *c= NULL;
int i, out_size, size, outbuf_size;
FILE *f;
AVFrame *picture;
uint8_t *outbuf;
printf("Video encoding\n");
/* find the mpeg video encoder */
codec = avcodec_find_encoder(CODEC_ID_MPEG2VIDEO);
if (!codec) {
fprintf(stderr, "codec not found\n");
exit(1);
}
c= avcodec_alloc_context();
picture= avcodec_alloc_frame();
/* put sample parameters */
c->bit_rate = 400000;
/* resolution must be a multiple of two */
c->width = 352;
c->height = 288;
/* frames per second */
c->time_base= (AVRational){1,25};
c->gop_size = 10; /* emit one intra frame every ten frames */
c->max_b_frames=1;
c->pix_fmt = PIX_FMT_YUV420P;
/* open it */
if (avcodec_open(c, codec) < 0) {
fprintf(stderr, "could not open codec\n");
exit(1);
}
f = fopen(filename, "wb");
if (!f) {
fprintf(stderr, "could not open %s\n", filename);
exit(1);
}
/* alloc image and output buffer */
outbuf_size = 100000;
outbuf = malloc(outbuf_size);
size = c->width * c->height;
#pragma mark -
AVFrame* outpic = avcodec_alloc_frame();
int nbytes = avpicture_get_size(PIX_FMT_YUV420P, c->width, c->height);
//create buffer for the output image
uint8_t* outbuffer = (uint8_t*)av_malloc(nbytes);
#pragma mark -
for(i=1;i<77;i++) {
fflush(stdout);
int numBytes = avpicture_get_size(PIX_FMT_YUV420P, c->width, c->height);
uint8_t *buffer = (uint8_t *)av_malloc(numBytes*sizeof(uint8_t));
UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:#"10%d", i]];
CGImageRef newCgImage = [image CGImage];
CGDataProviderRef dataProvider = CGImageGetDataProvider(newCgImage);
CFDataRef bitmapData = CGDataProviderCopyData(dataProvider);
buffer = (uint8_t *)CFDataGetBytePtr(bitmapData);
avpicture_fill((AVPicture*)picture, buffer, PIX_FMT_RGB8, c->width, c->height);
avpicture_fill((AVPicture*)outpic, outbuffer, PIX_FMT_YUV420P, c->width, c->height);
struct SwsContext* fooContext = sws_getContext(c->width, c->height,
PIX_FMT_RGB8,
c->width, c->height,
PIX_FMT_YUV420P,
SWS_FAST_BILINEAR, NULL, NULL, NULL);
//perform the conversion
sws_scale(fooContext, picture->data, picture->linesize, 0, c->height, outpic->data, outpic->linesize);
// Here is where I try to convert to YUV
/* encode the image */
out_size = avcodec_encode_video(c, outbuf, outbuf_size, outpic);
printf("encoding frame %3d (size=%5d)\n", i, out_size);
fwrite(outbuf, 1, out_size, f);
free(buffer);
buffer = NULL;
}
/* get the delayed frames */
for(; out_size; i++) {
fflush(stdout);
out_size = avcodec_encode_video(c, outbuf, outbuf_size, NULL);
printf("write frame %3d (size=%5d)\n", i, out_size);
fwrite(outbuf, 1, outbuf_size, f);
}
/* add sequence end code to have a real mpeg file */
outbuf[0] = 0x00;
outbuf[1] = 0x00;
outbuf[2] = 0x01;
outbuf[3] = 0xb7;
fwrite(outbuf, 1, 4, f);
fclose(f);
free(outbuf);
avcodec_close(c);
av_free(c);
av_free(picture);
printf("\n");
Please give me advice how to fix that problem.
You can see article http://unick-soft.ru/Articles.cgi?id=20. But it is article on Russian, but it includes code samples and VS Example.
Has anyone found a fix for this? I am seeing the green video problem on the decode side. That is, when I decode incoming PIX_FMT_YUV420 packets and then swsscale them to PIX_FMT_RGBA.
Thanks!
EDIT:
The green images are probably due to an arm optimization backfiring. I used this to fix the problem in my case:
http://ffmpeg-users.933282.n4.nabble.com/green-distorded-output-image-on-iPhone-td2231805.html
I guess the idea is to not specify any architecture (the config will you a warning about the architecture being unknown but you can continue to 'make' anyway). That way, the arm optimizations are not used. There maybe a slight performance hit (if any), but atleast it works! :)
I think the problem is most likely that you are using PIX_FMT_RGB8 as your input pixel format. This does not mean 8 bits per channel like the commonly used 24-bit RGB or 32-bit ARGB. It means 8 bits per pixel, meaning that all three color channels are housed in a single byte. I am guessing that this is not the format of your image since it is quite uncommon, so you need to use PIX_FMT_RGB24 or PIX_FMT_RGB32 depending on whether or not your input image has an alpha channel. See this documentation page for info on the pixel formats.