Class: Oil::JPEGReader

Inherits:
Object
  • Object
show all
Defined in:
ext/oil/jpeg.c,
ext/oil/jpeg.c

Overview

Read a compressed JPEG image given an IO object.

Instance Method Summary collapse

Constructor Details

#new(io_in[, markers]) ⇒ Object

Creates a new JPEG Reader. io_in must be an IO-like object that responds to read(size).

markers should be an array of valid JPEG header marker symbols. Valid symbols are :APP0 through :APP15 and :COM.

If performance is important, you can avoid reading any header markers by supplying an empty array, [].

When markers are not specified, we read all known JPEG markers.

io = File.open("image.jpg", "r")
reader = Oil::JPEGReader.new(io)

io = File.open("image.jpg", "r")
reader = Oil::JPEGReader.new(io, [:APP1, :APP2])


279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
# File 'ext/oil/jpeg.c', line 279

static VALUE initialize(int argc, VALUE *argv, VALUE self)
{
	struct readerdata *reader;
	VALUE io, markers;
	struct jpeg_decompress_struct *dinfo;
	int i, marker_code;

	Data_Get_Struct(self, struct readerdata, reader);
	dinfo = &reader->dinfo;

	/* If source_io has already been set, then this is a re-used jpeg reader
	 * object. This means we need to abort the previous decompress to
	 * prevent memory leaks.
	 */
	if (reader->source_io) {
		jpeg_abort_decompress(dinfo);
	}

	jpeg_create_decompress(&reader->dinfo);
	reader->dinfo.src = &reader->mgr;

	rb_scan_args(argc, argv, "11", &io, &markers);
	reader->source_io = io;
	reader->mgr.bytes_in_buffer = 0;

	if(!NIL_P(markers)) {
		Check_Type(markers, T_ARRAY);
		for (i=0; i<RARRAY_LEN(markers); i++) {
			marker_code = sym_to_marker_code(RARRAY_PTR(markers)[i]);
			jpeg_save_markers(dinfo, marker_code, 0xFFFF);
		}
	}

	/* Be warned that this can raise a ruby exception and longjmp away. */
	jpeg_read_header(&reader->dinfo, TRUE);

	jpeg_calc_output_dimensions(dinfo);

	return self;
}

Instance Method Details

#color_spaceObject

Returns a symbol representing the color model in which the JPEG is stored.

This does not have to be set explicitly and can be relied upon when the file conforms to JFIF or Adobe conventions. Otherwise it is guessed.

Possible color models are: :GRAYSCALE, :RGB, :YCbCr, :CMYK, and :YCCK. This method will return :UNKNOWN if the color model is not recognized.



347
348
349
350
351
352
353
354
355
356
# File 'ext/oil/jpeg.c', line 347

static VALUE color_space(VALUE self)
{
	struct jpeg_decompress_struct * dinfo;
	ID id;

	Data_Get_Struct(self, struct jpeg_decompress_struct, dinfo);
	id = j_color_space_to_id(dinfo->jpeg_color_space);

	return ID2SYM(id);
}

#out_color_space=(symbol) ⇒ Object

Set the color model to which teh image will be converted on decompress.



384
385
386
387
388
389
390
391
392
393
394
# File 'ext/oil/jpeg.c', line 384

static VALUE set_out_color_space(VALUE self, VALUE cs)
{
	struct readerdata *reader;

	Data_Get_Struct(self, struct readerdata, reader);
	raise_if_locked(reader);

	reader->dinfo.jpeg_color_space = sym_to_j_color_space(cs);
	jpeg_calc_output_dimensions(&reader->dinfo);
	return cs;
}

#componentsNumeric

Retrieve the number of components as stored in the JPEG image.

Returns:

  • (Numeric)


327
328
329
330
331
332
# File 'ext/oil/jpeg.c', line 327

static VALUE components(VALUE self)
{
	struct jpeg_decompress_struct * dinfo;
	Data_Get_Struct(self, struct jpeg_decompress_struct, dinfo);
	return INT2FIX(dinfo->num_components);
}

#each(opts, &block) ⇒ self

Yields a series of binary strings that make up the output JPEG image.

Options is a hash which may have the following symbols:

:quality - JPEG quality setting. Betweein 0 and 100. :markers - Custom markers to include in the output JPEG. Must be a hash where

the keys are :APP[0-15] or :COM and the values are arrays of strings that
will be inserted into the markers.

Returns:

  • (self)


751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
# File 'ext/oil/jpeg.c', line 751

static VALUE each(int argc, VALUE *argv, VALUE self)
{
	struct readerdata *reader;
	struct writerdata writer;
	int cmp, state;
	struct write_jpeg_args args;
	unsigned char *inwidthbuf, *outwidthbuf;
	struct yscaler ys;
	VALUE opts;

	rb_scan_args(argc, argv, "01", &opts);

	Data_Get_Struct(self, struct readerdata, reader);

	if (!reader->scale_width) {
		reader->scale_width = reader->dinfo.output_width;
	}
	if (!reader->scale_height) {
		reader->scale_height = reader->dinfo.output_height;
	}

	writer.cinfo.err = &reader->jerr;
	jpeg_create_compress(&writer.cinfo);

	cmp = reader->dinfo.output_components;
	inwidthbuf = malloc(reader->dinfo.output_width * cmp);
	outwidthbuf = malloc(reader->scale_width * cmp);
	yscaler_init(&ys, reader->dinfo.output_height, reader->scale_height,
		reader->scale_width * cmp);

	args.reader = reader;
	args.opts = opts;
	args.writer = &writer;
	args.inwidthbuf = inwidthbuf;
	args.outwidthbuf = outwidthbuf;
	args.ys = &ys;
	reader->locked = 1;
	rb_protect((VALUE(*)(VALUE))each2, (VALUE)&args, &state);

	yscaler_free(&ys);
	free(inwidthbuf);
	free(outwidthbuf);
	jpeg_destroy_compress(&writer.cinfo);

	if (state) {
		rb_jump_tag(state);
	}

	return self;
}

#heightNumeric

Retrieve the height of the image.

Returns:

  • (Numeric)


417
418
419
420
421
422
# File 'ext/oil/jpeg.c', line 417

static VALUE height(VALUE self)
{
	struct jpeg_decompress_struct * dinfo;
	Data_Get_Struct(self, struct jpeg_decompress_struct, dinfo);
	return INT2FIX(dinfo->image_height);
}

#markersHash

Get a hash of raw marker data from the JPEG.

The keys in the hash are the marker codes as symbols. The values are arrays.

Arrays since there may be multiple instances of a single marker in a JPEG marker.

Returns:

  • (Hash)


436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
# File 'ext/oil/jpeg.c', line 436

static VALUE markers(VALUE self)
{
	struct jpeg_decompress_struct *dinfo;
	jpeg_saved_marker_ptr marker;
	VALUE hash, ary, key, val;

	hash = rb_hash_new();

	Data_Get_Struct(self, struct jpeg_decompress_struct, dinfo);

	for (marker=dinfo->marker_list; marker; marker=marker->next) {
		key = marker_code_to_sym(marker->marker);
		ary = rb_hash_aref(hash, key);
		if (NIL_P(ary)) {
			ary = rb_ary_new();
			rb_hash_aset(hash, key, ary);
		}
		val = rb_str_new((char *)marker->data, marker->data_length);
		rb_ary_push(ary, val);
	}

	return hash;
}

#out_color_spaceObject

Returns a symbol representing the color model to which the image will be converted on decompress.



366
367
368
369
370
371
372
373
374
375
# File 'ext/oil/jpeg.c', line 366

static VALUE out_color_space(VALUE self)
{
	struct jpeg_decompress_struct * dinfo;
	ID id;

	Data_Get_Struct(self, struct jpeg_decompress_struct, dinfo);
	id = j_color_space_to_id(dinfo->jpeg_color_space);

	return ID2SYM(id);
}

#scale_denomNumeric

Retrieve the denominator of the fraction by which the JPEG will be scaled as it is read. This is 1, 2, 4, or 8 for libjpeg version 6b. In version 8b this is always the source DCT size, which is 8 for baseline JPEG.

Returns:

  • (Numeric)


506
507
508
509
510
511
# File 'ext/oil/jpeg.c', line 506

static VALUE scale_denom(VALUE self)
{
	struct jpeg_decompress_struct *dinfo;
	Data_Get_Struct(self, struct jpeg_decompress_struct, dinfo);
	return INT2FIX(dinfo->scale_denom);
}

#scale_denom=(number) ⇒ Object

Set the denominator of the fraction by which the JPEG will be scaled as it is read. This can be set to 1, 2, 4, or 8 for libjpeg version 6b. In version 8b this must always be the source DCT size, which is 8 for baseline JPEG.

Prior to version 1.2, libjpeg-turbo will not scale down images on decompression, and this option will do nothing.



525
526
527
528
529
530
531
532
533
534
535
# File 'ext/oil/jpeg.c', line 525

static VALUE set_scale_denom(VALUE self, VALUE scale_denom)
{
	struct readerdata *reader;

	Data_Get_Struct(self, struct readerdata, reader);
	raise_if_locked(reader);

	reader->dinfo.scale_denom = NUM2INT(scale_denom);
	jpeg_calc_output_dimensions(&reader->dinfo);
	return scale_denom;
}

#scale_heightNumeric

Retrieve the height to which the image will be resized after decompression. A height of 0 means the image will remain at original height.

Returns:

  • (Numeric)


577
578
579
580
581
582
# File 'ext/oil/jpeg.c', line 577

static VALUE scale_height(VALUE self)
{
	struct readerdata *reader;
	Data_Get_Struct(self, struct readerdata, reader);
	return INT2FIX(reader->scale_height);
}

#scale_height=(number) ⇒ Object

Set the height to which the image will be resized after decompression. A height of 0 means the image will remain at original height.



592
593
594
595
596
597
598
599
# File 'ext/oil/jpeg.c', line 592

static VALUE set_scale_height(VALUE self, VALUE scale_height)
{
	struct readerdata *reader;
	Data_Get_Struct(self, struct readerdata, reader);
	raise_if_locked(reader);
	reader->scale_height = NUM2INT(scale_height);
	return scale_height;
}

#scale_numNumeric

Retrieve the numerator of the fraction by which the JPEG will be scaled as it is read. This is always 1 for libjpeg version 6b. In version 8b this can be 1 to 16.

Returns:

  • (Numeric)


469
470
471
472
473
474
# File 'ext/oil/jpeg.c', line 469

static VALUE scale_num(VALUE self)
{
	struct jpeg_decompress_struct *dinfo;
	Data_Get_Struct(self, struct jpeg_decompress_struct, dinfo);
	return INT2FIX(dinfo->scale_num);
}

#scale_num=(number) ⇒ Object

Set the numerator of the fraction by which the JPEG will be scaled as it is read. This must always be 1 for libjpeg version 6b. In version 8b this can be set to 1 through 16.



485
486
487
488
489
490
491
492
493
494
495
# File 'ext/oil/jpeg.c', line 485

static VALUE set_scale_num(VALUE self, VALUE scale_num)
{
	struct readerdata *reader;

	Data_Get_Struct(self, struct readerdata, reader);
	raise_if_locked(reader);

	reader->dinfo.scale_num = NUM2INT(scale_num);
	jpeg_calc_output_dimensions(&reader->dinfo);
	return scale_num;
}

#scale_widthNumeric

Retrieve the width to which the image will be resized after decompression. A width of 0 means the image will remain at original width.

Returns:

  • (Numeric)


545
546
547
548
549
550
# File 'ext/oil/jpeg.c', line 545

static VALUE scale_width(VALUE self)
{
	struct readerdata *reader;
	Data_Get_Struct(self, struct readerdata, reader);
	return INT2FIX(reader->scale_width);
}

#scale_width=(number) ⇒ Object

Set the width to which the image will be resized after decompression. A width of 0 means the image will remain at original width.



560
561
562
563
564
565
566
567
# File 'ext/oil/jpeg.c', line 560

static VALUE set_scale_width(VALUE self, VALUE scale_width)
{
	struct readerdata *reader;
	Data_Get_Struct(self, struct readerdata, reader);
	raise_if_locked(reader);
	reader->scale_width = NUM2INT(scale_width);
	return scale_width;
}

#widthNumeric

Retrieve the width of the image.

Returns:

  • (Numeric)


403
404
405
406
407
408
# File 'ext/oil/jpeg.c', line 403

static VALUE width(VALUE self)
{
	struct jpeg_decompress_struct * dinfo;
	Data_Get_Struct(self, struct jpeg_decompress_struct, dinfo);
	return INT2FIX(dinfo->image_width);
}