Movatterモバイル変換


[0]ホーム

URL:


Jump to content
Rosetta Code
Search

Bitmap/PPM conversion through a pipe

From Rosetta Code
<Bitmap
Task
Bitmap/PPM conversion through a pipe
You are encouraged tosolve this task according to the task description, using any language you may know.

Using the data storage type definedon this page for raster images, delegate writing a JPEG file through apipe using theoutput_ppm function definedon this other page.

There are various utilities that can be used for this task, for example:cjpeg (package"jpeg-progs" on Linux, or"media-libs/libjpeg-turbo" on Gentoo),ppmtojpeg (package"netpbm" on Linux),convert (fromImageMagick, multi-platform).

ATS

I use themagick command from ImageMagick. You need all the source files fromBitmap#ATS,Bitmap/Read_a_PPM_file#ATS, andBitmap/Write_a_PPM_file#ATS. (You donot need the files fromGrayscale_image#ATS.)

See alsoBitmap/Read_an_image_through_a_pipe#ATS.

(* This program uses ImageMagick to convert an image, with the target   file specified according to the conventions of ImageMagick. That   allows such things as "gif:foobar.jpg" to mean a GIF named   "foobar.jpg". But, if you leave out the "gif:" prefix, ImageMagick   will make a JPEG. (I notice that one can also insert options to   magick, although this was an unexpected result of my design.) *)(*##myatsccdef=\patscc -std=gnu2x -g -O2 -DATS_MEMALLOC_LIBC \  -o $fname($1) $1 \  bitmap{,_{read,write}_ppm}_task.{s,d}ats*)#include "share/atspre_staload.hats"staload "bitmap_task.sats"staload "bitmap_read_ppm_task.sats"staload "bitmap_write_ppm_task.sats"staload _ = "bitmap_task.dats"staload _ = "bitmap_read_ppm_task.dats"staload _ = "bitmap_write_ppm_task.dats"(*------------------------------------------------------------------*)(* There is support for pipe-I/O in libats/libc, but I cannot (at   least when in a hurry) figure out how it is supposed to be   used. So, as elsewhere in the "raster graphics operations"   category, what is not in the prelude itself I implement with the   foreign function interfaces. :) Using FFI is a typical part of ATS   programming, and one should get used to doing it.      Anyway, here is some UNSAFE support for pipe-I/O. *)typedef charstar = $extype"char *"typedef FILEstar = $extype"FILE *"fn {}fileref_popen_unsafe (command : string,                      mode    : string)    : Option_vt FILEref =  let    val p = $extfcall (ptr, "popen", $UNSAFE.cast{charstar} command,                       $UNSAFE.cast{charstar} mode)  in    if iseqz p then      None_vt ()    else      Some_vt ($UNSAFE.cast{FILEref} p)  endfn {}fileref_pclose_unsafe (f : FILEref)    : int =              (* Returns the exit status of the command. *)  $extfcall (int, "pclose", $UNSAFE.cast{FILEstar} f)(*------------------------------------------------------------------*)implementmain0 (argc, argv) =  let    val args = listize_argc_argv (argc, argv)    val nargs = length args    val inpf =      if nargs < 2 then        stdin_ref      else if args[1] = "-" then        stdin_ref      else        fileref_open_exn (args[1], file_mode_r)    val pix_opt = pixmap_read_ppm<rgb24> inpf    val () = fileref_close inpf  in    case+ pix_opt of    | ~ None_vt () =>      begin        free args;        println! ("For some reason, I failed to read the image.");        exit 1      end    | ~ Some_vt @(pfgc1 | pix1) =>      let        val outf_name = if nargs < 3 then "-" else args[2]        val command = string_append ("magick ppm:- ", outf_name)        val () = free args        val pipe_opt =          (* Temporarily treating a strptr as a string, just to make a             function call of this sort, is not actually unsafe. *)          fileref_popen_unsafe ($UNSAFE.strptr2string command, "w")        val () = free command      in        case+ pipe_opt of        | ~ None_vt () =>          begin            free (pfgc1 | pix1);            println! ("For some reason, I failed to open a pipe ",                      "to magick.");            exit 3          end        | ~ Some_vt outf =>          let            val success = pixmap_write_ppm (outf, pix1)          in            ignoret (fileref_pclose_unsafe outf);            free (pfgc1 | pix1);            if ~success then              begin                println! ("For some reason, I failed to pipe the ",                          "image to magick.");                exit 2              end          end      end  end
Output:

Using SIPI test image 5.1.12:

$ myatscc bitmap_write_through_pipe_task.dats$ ./bitmap_write_through_pipe_task 5.1.12.ppm bitmap_write_through_pipe_task_ATS.jpg

An alarm clock on a book on a book, and a diptych of family portraits. On a table or chest of drawers or some such. Monochrome photograph.

C

Works with:POSIX version .1-2001

This one uses the ImageMagickconvert tool.

/* interface */voidprint_jpg(imageimg,intqual);
#define MAXCMDBUF 100voidprint_jpg(imageimg,intqual){charbuf[MAXCMDBUF];unsignedintn;FILE*pipe;snprintf(buf,MAXCMDBUF,"convert ppm:- -quality %d jpg:-",qual);pipe=popen(buf,"w");if(pipe!=NULL){fprintf(pipe,"P6\n%d %d\n255\n",img->width,img->height);n=img->width*img->height;fwrite(img->buf,sizeof(pixel),n,pipe);pclose(pipe);}}

The code that writes to the pipe is the same ofoutput_ppm of course. A complete example is

#include"imglib.h"intmain(){imageimg;img=alloc_img(100,100);fill_img(img,50,20,200);draw_line(img,0,0,80,80,255,0,0);print_jpg(img,75);free_img(img);}

In order to make it working, you must link it with the raster image functions given by the codeshere andhere

FreeBASIC

Constancho=400Constalto=300DimAsIntegeri,x,yDimAsUlongkolor' Set up graphicsScreenresancho,alto,32Windowtitle"Pattern Generator"' A little extravagant, this draws a design of dots and lines' Fill background with color Rgb(&h40, &h80, &hc0)Line(0,0)-(ancho-1,alto-1),Rgb(64,128,192),BF' Draw random dots Rgb(&h20, &h40, &h80)Fori=1To2000Pset(Rnd*(ancho-1),Rnd*(alto-1)),Rgb(32,64,128)Next' Draw horizontal linesForx=0Toancho-1Fory=240To244Pset(x,y),Rgb(32,64,128)NextFory=260To264Pset(x,y),Rgb(32,64,128)NextNext' Draw vertical linesFory=0Toalto-1Forx=80To84Pset(x,y),Rgb(32,64,128)NextForx=95To99Pset(x,y),Rgb(32,64,128)NextNext' Open PPM file to writeDimAsIntegerff=FreefileOpen"noutput.ppm"ForBinaryAs#ffIfErr>0ThenPrint"Error opening output file":End' Write PPM headerPut#ff,,"P6"&Chr(10)Put#ff,,Str(ancho)&" "&Str(alto)&Chr(10)Put#ff,,"255"&Chr(10)' Write pixel dataFory=0Toalto-1Forx=0Toancho-1kolor=Point(x,y)Put#ff,,Cbyte(kolorShr16)' BluePut#ff,,Cbyte(kolorShr8)' GreenPut#ff,,Cbyte(kolor)' RedNextNextClose#ff' Convert to JPG using ImageMagick  (pipe logic)Shell"magick.exe noutput.ppm noutput.jpg"Sleep

Go

Works with:Go weekly.2011-12-14

(Go 1 should be close)

Using cjpeg:

packagemain// Files required to build supporting package raster are found in:// * Bitmap// * Write a PPM fileimport("fmt""math/rand""os/exec""raster")funcmain(){b:=raster.NewBitmap(400,300)// a little extravagant, this draws a design of dots and linesb.FillRgb(0xc08040)fori:=0;i<2000;i++{b.SetPxRgb(rand.Intn(400),rand.Intn(300),0x804020)}forx:=0;x<400;x++{fory:=240;y<245;y++{b.SetPxRgb(x,y,0x804020)}fory:=260;y<265;y++{b.SetPxRgb(x,y,0x804020)}}fory:=0;y<300;y++{forx:=80;x<85;x++{b.SetPxRgb(x,y,0x804020)}forx:=95;x<100;x++{b.SetPxRgb(x,y,0x804020)}}// pipe logicc:=exec.Command("cjpeg","-outfile","pipeout.jpg")pipe,err:=c.StdinPipe()iferr!=nil{fmt.Println(err)return}err=c.Start()iferr!=nil{fmt.Println(err)return}err=b.WritePpmTo(pipe)iferr!=nil{fmt.Println(err)return}err=pipe.Close()iferr!=nil{fmt.Println(err)}}

Julia

Works with:Julia version 0.6
usingImages,FileIOppmimg=load("data/bitmapInputTest.ppm")save("data/bitmapOutputTest.jpg",ppmimg)

Kotlin

Works with:Ubuntu 16.04

In order to provide a complete runnable example, we repeat bits of code from other relevant tasks and add code which pipes .ppm data to ImageMagick's 'convert' tool which then writes the corresponding .jpg file to disk.

// Version 1.2.40importjava.awt.Colorimportjava.awt.Graphicsimportjava.awt.image.BufferedImageclassBasicBitmapStorage(width:Int,height:Int){valimage=BufferedImage(width,height,BufferedImage.TYPE_3BYTE_BGR)funfill(c:Color){valg=image.graphicsg.color=cg.fillRect(0,0,image.width,image.height)}funsetPixel(x:Int,y:Int,c:Color)=image.setRGB(x,y,c.getRGB())fungetPixel(x:Int,y:Int)=Color(image.getRGB(x,y))}funmain(args:Array<String>){// create BasicBitmapStorage objectvalwidth=640valheight=640valbbs=BasicBitmapStorage(width,height)for(yin0untilheight){for(xin0untilwidth){valc=Color(x%256,y%256,(x*y)%256)bbs.setPixel(x,y,c)}}// now write the object in PPM format to ImageMagick's STDIN via a pipe// so it can be converted to a .jpg file and written to diskvalpb=ProcessBuilder("convert","-","output_piped.jpg")pb.directory(null)pb.redirectInput(ProcessBuilder.Redirect.PIPE)valbuffer=ByteArray(width*3)// write one line at a timevalproc=pb.start()valpStdIn=proc.outputStreampStdIn.use{valheader="P6\n$width $height\n255\n".toByteArray()with(it){write(header)for(yin0untilheight){for(xin0untilwidth){valc=bbs.getPixel(x,y)buffer[x*3]=c.red.toByte()buffer[x*3+1]=c.green.toByte()buffer[x*3+2]=c.blue.toByte()}write(buffer)}}}}

Mathematica /Wolfram Language

The Windows command line does not like quotes in the middle of text, so strings have been turned into character codes.

convert[image_,out_]:=Module[{process=StartProcess[{"wolfram","-noinit","-noprompt","-run","Export[FromCharacterCode["~~ToString[ToCharacterCode[out]]~~"],ImportString[StringRiffle[Table[InputString[],{4}],FromCharacterCode[10]],FromCharacterCode[{80,80,77}]]]"}]},WriteLine[process,image];WriteLine[process,"Quit[]"];];

Nim

We use "convert" command from ImageMagick and "pnmtojpeg" command from Netpbm. The first command allows to specify the output file name, the second writes to stdout and, so, we have to use a redirection. Thus, the way to launch the process is slightly different.

importbitmapimportppm_writeimportosproc# Build an image.varimage=newImage(100,50)image.fill(color(255,0,0))forrowin10..20:forcolin0..<image.w:image[col,row]=color(0,255,0)forrowin30..40:forcolin0..<image.w:image[col,row]=color(0,0,255)# Launch ImageMagick "convert".# Input is taken from stdin and result written in "output1.jpeg".varp=startProcess("convert",args=["ppm:-","output1.jpeg"],options={poUsePath})varstream=p.inputStream()image.writePPM(stream)p.close()# Launch Netpbm "pnmtojpeg".# Input is taken from stdin and output sent to "output2.jpeg".p=startProcess("pnmtojpeg >output2.jpeg",options={poUsePath,poEvalCommand})stream=p.inputStream()image.writePPM(stream)p.close()

OCaml

letprint_jpeg~img?(quality=96)()=letcmd=Printf.sprintf"cjpeg -quality %d"qualityin(*  let cmd = Printf.sprintf "ppmtojpeg -quality %d" quality in  let cmd = Printf.sprintf "convert ppm:- -quality %d jpg:-" quality in  *)letic,oc=Unix.open_processcmdinoutput_ppm~img~oc;trywhiletruedoletc=input_charicinprint_charcdonewithEnd_of_file->();;

Perl

# 20211224 Perl programming solutionusestrict;usewarnings;useImager;useImager::Test'test_image_raw';my$img=test_image_raw();my$IO=Imager::io_new_bufchain();Imager::i_writeppm_wiol($img,$IO)ordie;my$raw=Imager::io_slurp($IO)ordie;openmy$fh,'|-','/usr/local/bin/convert - -compress none output.jpg'ordie;binmode$fh;syswrite$fh,$rawordie;close$fh;
Output:
file output.jpgoutput.jpg: JPEG image data, JFIF standard 1.01, comment: "CREATOR: Imager"magick identify output.jpgoutput.jpg JPEG 150x150 150x150+0+0 8-bit sRGB 3952B 0.000u 0:00.012

Phix

Uses the provided demo\rosetta\viewppm.exw utility to accomplish this task.

-- demo\rosetta\Bitmap_PPM_conversion_through_a_pipe.exwwithoutjs-- file i/o, system_exec(), pipes[!!]includebuiltins\pipeio.eincludebuiltins\serialize.eincludeppm.e-- read_ppm()sequencepipes=repeat(0,3)pipes[PIPEIN]=create_pipe(INHERIT_WRITE)-- Create the child process, with replacement stdin.stringcmd=sprintf("%s viewppm -save test.jpg",{get_interpreter(true)})atomhProc=system_exec(cmd,12,pipes),hPipe=pipes[PIPEIN][WRITE_PIPE]sequenceimg=serialize(read_ppm("Lena.ppm",bFlat:=true))ifnotwrite_to_pipe(hPipe,img)thencrash("error")endif-- Close the pipe handle so the child process stops reading. --hPipe = close_handles(hPipe)pipes=close_handles(pipes)-- (may as well do the lot)?"done"{}=wait_key()

PicoLisp

# Create an empty image of 120 x 90 pixels(setq *Ppm (make (do 90 (link (need 120)))))# Fill background with green color(ppmFill *Ppm 0 255 0)# Draw a diagonal line(for I 80 (ppmSetPixel *Ppm I I 0 0 0))# Write to "img.jpg" through a pipe(ppmWrite *Ppm '("convert" "-" "img.jpg"))

Python

"""Adapted from https://stackoverflow.com/questions/26937143/ppm-to-jpeg-jpg-conversion-for-python-3-4-1Requires pillow-5.3.0 with Python 3.7.1 32-bit on Windows.Sample ppm graphics files from http://www.cs.cornell.edu/courses/cs664/2003fa/images/"""fromPILimportImageim=Image.open("boxes_1.ppm")im.save("boxes_1.jpg")

Does not need to pipe through a conversion utility because the Pillow module does the conversion.

Racket

(define(ppm->jpegbitmap[jpg-file"output"][quality75])(definecommand(format"convert ppm:- -quality ~a jpg:~a.jpg"qualityjpg-file))(match-define(listinoutpiderrctrl)(processcommand))(bitmap->ppmbitmapout)(close-input-portin)(close-output-portout))(ppm->jpegbm)

Raku

(formerly Perl 6)

# Reference:# https://rosettacode.org/wiki/Bitmap/Write_a_PPM_file#Rakuusev6;classPixel {hasuint8 ($.R,$.G,$.B) }classBitmap {hasUInt ($.width,$.height);hasPixel@!data;methodfill(Pixel$p) {@!data =$p.clonexx ($!width*$!height)    }methodpixel($iwhere ^$!width,$jwhere ^$!height          -->Pixel      )isrw {@!data[$i*$!height +$j] }methoddata {@!data }}rolePPM {methodP6returnsBlob {"P6\n{self.width} {self.height}\n255\n".encode('ascii')        ~Blob.new:flatmap { .R, .G, .B },self.data    }}myBitmap$b =Bitmap.new(width =>125,height =>125)butPPM;forflat ^$b.heightX ^$b.width ->$i,$j {$b.pixel($i,$j) =Pixel.new: :R($i*2), :G($j*2), :B(255-$i*2);}my$proc =run'/usr/bin/convert','-','output_piped.jpg', :in;$proc.in.write:$b.P6;$proc.in.close;
Output:
file output_piped.jpgoutput_piped.jpg: JPEG image data, JFIF standard 1.01, aspect ratio, density 1x1, segment length 16, baseline, precision 8, 125x125, frames 3

Ruby

ExtendsWrite ppm file#Ruby. Uses the ImageMagickconvert tool.Additionally, for debugging, allow writing in pixmap P3 (ascii) format.

classPixmapPIXMAP_FORMATS=["P3","P6"]# implemented output formatsPIXMAP_BINARY_FORMATS=["P6"]# implemented output formats which are binarydefwrite_ppm(ios,format="P6")ifnotPIXMAP_FORMATS.include?(format)raiseNotImplementedError,"pixmap format#{format} has not been implemented"endios.putsformat,"#{@width}#{@height}","255"ios.binmodeifPIXMAP_BINARY_FORMATS.include?(format)@height.timesdo|y|@width.timesdo|x|caseformatwhen"P3"thenios.print@data[x][y].values.join(" "),"\n"when"P6"thenios.print@data[x][y].values.pack('C3')endendendenddefsave(filename,opts={:format=>"P6"})File.open(filename,'w')do|f|write_ppm(f,opts[:format])endenddefprint(opts={:format=>"P6"})write_ppm($stdout,opts[:format])enddefsave_as_jpeg(filename,quality=75)pipe=IO.popen("convert ppm:- -quality#{quality} jpg:#{filename}",'w')write_ppm(pipe)pipe.closeendendimage=Pixmap.open('file.ppm')image.save_as_jpeg('file.jpg')

Standard ML

This function uses convert, and retrieves its output

val useOSConvert =  fn ppm =>  let   val img       =   String.translate (fn #"\"" => "\\\""|n=>str n )  ppm ;   val app        = " convert  -  jpeg:- "   val fname      = "/tmp/fConv" ^ (String.extract (Time.toString (Posix.ProcEnv.time()),7,NONE) );   val shellCommand = " echo   \"" ^ img  ^ "\"  | "  ^  app  ;   val me         = (  Posix.FileSys.mkfifo                               (fname,        Posix.FileSys.S.flags [ Posix.FileSys.S.irusr,Posix.FileSys.S.iwusr ]       ) ;                        Posix.Process.fork ()     ) ;  in   if (Option.isSome me) then     let        val fin =BinIO.openIn fname     in        ( Posix.Process.sleep (Time.fromReal 0.1) ;          BinIO.inputAll fin  before  (BinIO.closeIn fin ; OS.FileSys.remove fname ))     end   else     ( OS.Process.system (  shellCommand ^ " > " ^ fname  ^ " 2>&1 "     ) ;                                        Word8Vector.fromList [] before OS.Process.exit OS.Process.success     )  end;

call and return value

useOSConvert "P3 3 2 255 255   0   0   0 255   0    0   0 255   255 255   0   255 255 255  0   0   0"  ;val it =   fromList[0wxFF, 0wxD8, 0wxFF, 0wxE0, 0wx0, 0wx10, 0wx4A, 0wx46, 0wx49,      0wx46, ...]: BinIO.vector

This is the fire-and-forget version.

val demo = fn () =>let val useOSConvert =  fn ppmf =>  let   val appopt     =   ("/usr/local/bin/convert",  ["convert","-",  "/tmp/out.jpeg"])   val p          =   Posix.IO.pipe () ;   val me         =   Posix.Process.fork ()  in   case  me of SOME cpd  =>     (   Posix.IO.close (#outfd p); Posix.IO.dup2 {old=(#infd p), new= Posix.FileSys.stdin } ; Posix.IO.close (#infd p);         Posix.Process.exec appopt)     |   _   =>     (   Posix.IO.close (#infd p);         ppmf (#outfd p) ;         Posix.IO.close (#outfd p) ; OS.Process.exit OS.Process.success      )  end;   fun output_ppm fd =                                                  (* placeholder for the ppm/bitmap functionality *)      Posix.IO.writeVec ( fd ,       Word8VectorSlice.full ( Byte.stringToBytes       "P3 3 2 255 255   0   0    0 255   0   0   0 255  255 255   0 255 255 255   0   0   0 " )       )in  useOSConvert output_ppmend ;

output, after compilation to 'demo'

shell$ demoshell$ file /tmp/out.jpeg/tmp/out.jpeg: JPEG image data, JFIF standard 1.01, aspect ratio, density 1x1, segment length 16, baseline, precision 8, 3x2, frames 3

Tcl

Referring toWrite ppm file#Tcl andBasic bitmap storage#Tcl

Library:Tk
packagerequireTkprocoutput_jpeg{imagefilename{quality75}}{setf[open|[listconvertppm:--quality$qualityjpg:->$filename]w]fconfigure$f-translationbinaryputs-nonewline$f[$imagedata-formatppm]close$f}

However, it is more normal to do this directly with the

Library:TkImg

which is bundled with many Tcl distributions.

packagerequireTkpackagerequireimg::jpegprocoutput_jpeg{imagefilename}{$imagewrite$filename-formatjpeg}setimg[imagecreatephoto-filenamefilename.ppm]output_jpeg$imgfilename.jpg

Wren

Library:DOME

As DOME doesn't have a method for calling an external process (ImageMagick in this case), we first need to create a small plug-in in C to add this functionality.

/* gcc -O3 -std=c11 -shared -o pipeconv.so -fPIC  -I./include pipeconv.c */#include<stdlib.h>#include<string.h>#include"dome.h"staticDOME_API_v0*core;staticWREN_API_v0*wren;staticconstchar*source="""class PipeConv {\n""foreign static convert(from, to)\n""}\n";voidC_convert(WrenVM*vm){constchar*from=wren->getSlotString(vm,1);constchar*to=wren->getSlotString(vm,2);charcommand[strlen(from)+strlen(to)+10];strcpy(command,"convert ");strcat(command,from);strcat(command," ");strcat(command,to);intres=system(command);}DOME_EXPORTDOME_ResultPLUGIN_onInit(DOME_getAPIFunctionDOME_getAPI,DOME_Contextctx){core=DOME_getAPI(API_DOME,DOME_API_VERSION);wren=DOME_getAPI(API_WREN,WREN_API_VERSION);core->registerModule(ctx,"pipeconv",source);core->registerClass(ctx,"pipeconv","PipeConv",NULL,NULL);core->registerFn(ctx,"pipeconv","static PipeConv.convert(_,_)",C_convert);returnDOME_RESULT_SUCCESS;}DOME_EXPORTDOME_ResultPLUGIN_preUpdate(DOME_Contextctx){returnDOME_RESULT_SUCCESS;}DOME_EXPORTDOME_ResultPLUGIN_postUpdate(DOME_Contextctx){returnDOME_RESULT_SUCCESS;}DOME_EXPORTDOME_ResultPLUGIN_preDraw(DOME_Contextctx){returnDOME_RESULT_SUCCESS;}DOME_EXPORTDOME_ResultPLUGIN_postDraw(DOME_Contextctx){returnDOME_RESULT_SUCCESS;}DOME_EXPORTDOME_ResultPLUGIN_onShutdown(DOME_Contextctx){returnDOME_RESULT_SUCCESS;}

This assumes that thedome.h header file is copied to aninclude sub-directory of the current one and that the resultingpipeconv.so shared library file is created in the latter.

We can now use this plug-in in the following script which callsImageMagick to convert theoutput.ppm file to ajpg file and then loads the latter and displays it.

import"graphics"forCanvas,ImageDataimport"dome"forWindowimport"plugin"forPluginPlugin.load("pipeconv")import"pipeconv"forPipeConvclassConvertPPM{constructnew(fileName,fileName2,width,height){Window.resize(width,height)Canvas.resize(width,height)Window.title="Convert PPM file via pipe"// convert .ppm file to .jpg via a pipePipeConv.convert(fileName,fileName2)// load and display .jpg filevarimage=ImageData.loadFromFile(fileName2)image.draw(0,0)}init(){}update(){}draw(alpha){}}varGame=ConvertPPM.new("output.ppm","output_piped.jpg",350,350)

zkl

Translation of:C

Uses the PPM class fromhttp://rosettacode.org/wiki/Bitmap/Bresenham%27s_line_algorithm#zkl

Using the convert utility by ImageMagick:

img:=PPM.readPPMFile("fractal.ppm");p:=System.popen(0'|convert ppm:- jpg:"fractal.jpg"|,"w");img.write(p); p.close();
Retrieved from "https://rosettacode.org/wiki/Bitmap/PPM_conversion_through_a_pipe?oldid=373152"
Categories:
Hidden category:
Cookies help us deliver our services. By using our services, you agree to our use of cookies.

[8]ページ先頭

©2009-2025 Movatter.jp